From 4e1fc946c0f01d801ca61ed604bfbd01214a2033 Mon Sep 17 00:00:00 2001 From: Dnreikronos Date: Mon, 6 Jul 2026 20:01:39 -0300 Subject: [PATCH 01/10] Fix anon const type recovery --- .../rustc_hir_analysis/src/collect/type_of.rs | 80 +++++++++++++++++-- 1 file changed, 74 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 3402f56bef6dc..8539f7b4a1f9d 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -381,7 +381,6 @@ fn anon_const_type_of<'tcx>(icx: &ItemCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx fn const_arg_anon_type_of<'tcx>(icx: &ItemCtxt<'tcx>, arg_hir_id: HirId, span: Span) -> Ty<'tcx> { use hir::*; - use rustc_middle::ty::Ty; let tcx = icx.tcx; @@ -405,16 +404,85 @@ fn const_arg_anon_type_of<'tcx>(icx: &ItemCtxt<'tcx>, arg_hir_id: HirId, span: S icx.lower_ty(ty) } + Node::Expr(Expr { kind: ExprKind::Path(qpath), .. }) => { + path_const_arg_anon_type_of(icx, qpath, arg_hir_id) + .unwrap_or_else(|| const_arg_anon_type_error(tcx, span)) + } + // This is not a `bug!` as const arguments in path segments that did not resolve to anything // will result in `type_of` never being fed. - _ => Ty::new_error_with_message( - tcx, - span, - "`type_of` called on const argument's anon const before the const argument was lowered", - ), + _ => const_arg_anon_type_error(tcx, span), } } +fn const_arg_anon_type_error<'tcx>(tcx: TyCtxt<'tcx>, span: Span) -> Ty<'tcx> { + Ty::new_error_with_message( + tcx, + span, + "`type_of` called on const argument's anon const before the const argument was lowered", + ) +} + +fn path_const_arg_anon_type_of<'tcx>( + icx: &ItemCtxt<'tcx>, + qpath: &hir::QPath<'tcx>, + arg_hir_id: HirId, +) -> Option> { + if let hir::QPath::Resolved(None, path) = qpath { + let [segment] = path.segments else { return None }; + let hir::def::Res::Def(hir::def::DefKind::Fn, def_id) = segment.res else { + return None; + }; + expected_const_arg_type(icx.tcx, def_id, segment, arg_hir_id) + } else { + None + } +} + +fn expected_const_arg_type<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: DefId, + segment: &hir::PathSegment<'tcx>, + arg_hir_id: HirId, +) -> Option> { + if segment.infer_args { + return None; + } + + let generic_args = segment.args(); + if !generic_args.constraints.is_empty() + || generic_args.parenthesized != hir::GenericArgsParentheses::No + { + return None; + } + + let [hir::GenericArg::Const(const_arg)] = generic_args.args else { return None }; + if const_arg.hir_id != arg_hir_id { + return None; + } + + let generics = tcx.generics_of(def_id); + if generics.parent.is_some() + || generics.parent_count != 0 + || generics.has_self + || generics.has_late_bound_regions.is_some() + { + return None; + } + + let [param] = generics.own_params.as_slice() else { return None }; + if !matches!(param.kind, ty::GenericParamDefKind::Const { .. }) { + return None; + } + + let ty = tcx.type_of(param.def_id).instantiate_identity().skip_norm_wip(); + (!ty.has_non_region_param() + && !ty.has_non_region_infer() + && !ty.has_free_regions() + && !ty.has_erased_regions()) + .then_some(ty) +} + fn infer_placeholder_type<'tcx>( cx: &dyn HirTyLowerer<'tcx>, def_id: LocalDefId, From fc1571e81568eedd0ef923aca8626fe758c72d32 Mon Sep 17 00:00:00 2001 From: Dnreikronos Date: Mon, 6 Jul 2026 20:02:18 -0300 Subject: [PATCH 02/10] Add anon const type recovery test --- .../anon-const-type-of-issue-158818.rs | 9 +++++++++ .../anon-const-type-of-issue-158818.stderr | 12 ++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 tests/ui/const-generics/anon-const-type-of-issue-158818.rs create mode 100644 tests/ui/const-generics/anon-const-type-of-issue-158818.stderr diff --git a/tests/ui/const-generics/anon-const-type-of-issue-158818.rs b/tests/ui/const-generics/anon-const-type-of-issue-158818.rs new file mode 100644 index 0000000000000..a62cbaa7e72d8 --- /dev/null +++ b/tests/ui/const-generics/anon-const-type-of-issue-158818.rs @@ -0,0 +1,9 @@ +//@ edition: 2024 +//@ compile-flags: -Zthreads=0 --crate-type lib + +#![allow(dead_code)] + +fn with_option() { + with_option::<{ async || {} }>(); + //~^ ERROR mismatched types +} diff --git a/tests/ui/const-generics/anon-const-type-of-issue-158818.stderr b/tests/ui/const-generics/anon-const-type-of-issue-158818.stderr new file mode 100644 index 0000000000000..3e5445b9f469a --- /dev/null +++ b/tests/ui/const-generics/anon-const-type-of-issue-158818.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/anon-const-type-of-issue-158818.rs:7:21 + | +LL | with_option::<{ async || {} }>(); + | ^^^^^^^^^^^ expected `u32`, found `{async closure@anon-const-type-of-issue-158818.rs:7:21}` + | + = note: expected type `u32` + found closure `{async closure@$DIR/anon-const-type-of-issue-158818.rs:7:21: 7:29}` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. From 92ba0687c1d0baa926f1983844ec18dfb188fa9b Mon Sep 17 00:00:00 2001 From: Joao Roberto Date: Mon, 27 Jul 2026 09:35:03 -0300 Subject: [PATCH 03/10] Handle qualified fn paths in anon const recovery --- compiler/rustc_hir_analysis/src/collect/type_of.rs | 2 +- ...anon-const-type-of-qualified-path-issue-158818.rs | 9 +++++++++ ...-const-type-of-qualified-path-issue-158818.stderr | 12 ++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 tests/ui/const-generics/anon-const-type-of-qualified-path-issue-158818.rs create mode 100644 tests/ui/const-generics/anon-const-type-of-qualified-path-issue-158818.stderr diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 8539f7b4a1f9d..0c33d9b58ff37 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -429,7 +429,7 @@ fn path_const_arg_anon_type_of<'tcx>( arg_hir_id: HirId, ) -> Option> { if let hir::QPath::Resolved(None, path) = qpath { - let [segment] = path.segments else { return None }; + let segment = path.segments.last()?; let hir::def::Res::Def(hir::def::DefKind::Fn, def_id) = segment.res else { return None; }; diff --git a/tests/ui/const-generics/anon-const-type-of-qualified-path-issue-158818.rs b/tests/ui/const-generics/anon-const-type-of-qualified-path-issue-158818.rs new file mode 100644 index 0000000000000..a8c17c00f2418 --- /dev/null +++ b/tests/ui/const-generics/anon-const-type-of-qualified-path-issue-158818.rs @@ -0,0 +1,9 @@ +//@ edition: 2024 +//@ compile-flags: -Zthreads=0 --crate-type lib + +#![allow(dead_code)] + +fn with_option() { + crate::with_option::<{ async || {} }>(); + //~^ ERROR mismatched types +} diff --git a/tests/ui/const-generics/anon-const-type-of-qualified-path-issue-158818.stderr b/tests/ui/const-generics/anon-const-type-of-qualified-path-issue-158818.stderr new file mode 100644 index 0000000000000..855a68e221fbf --- /dev/null +++ b/tests/ui/const-generics/anon-const-type-of-qualified-path-issue-158818.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/anon-const-type-of-qualified-path-issue-158818.rs:7:28 + | +LL | crate::with_option::<{ async || {} }>(); + | ^^^^^^^^^^^ expected `u32`, found `{async closure@anon-const-type-of-qualified-path-issue-158818.rs:7:28}` + | + = note: expected type `u32` + found closure `{async closure@$DIR/anon-const-type-of-qualified-path-issue-158818.rs:7:28: 7:36}` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. From 39036ba74845ba49fab001a1d8c41b39b2ec81c3 Mon Sep 17 00:00:00 2001 From: Joao Roberto Date: Mon, 27 Jul 2026 10:16:59 -0300 Subject: [PATCH 04/10] Normalize async closure diagnostics in UI tests --- tests/ui/const-generics/anon-const-type-of-issue-158818.rs | 2 ++ tests/ui/const-generics/anon-const-type-of-issue-158818.stderr | 2 +- .../anon-const-type-of-qualified-path-issue-158818.rs | 2 ++ .../anon-const-type-of-qualified-path-issue-158818.stderr | 2 +- 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/ui/const-generics/anon-const-type-of-issue-158818.rs b/tests/ui/const-generics/anon-const-type-of-issue-158818.rs index a62cbaa7e72d8..cd81244b21a5a 100644 --- a/tests/ui/const-generics/anon-const-type-of-issue-158818.rs +++ b/tests/ui/const-generics/anon-const-type-of-issue-158818.rs @@ -7,3 +7,5 @@ fn with_option() { with_option::<{ async || {} }>(); //~^ ERROR mismatched types } + +//@ normalize-stderr: "found `\{async closure@[^`]*\}`" -> "found `{async closure@...}`" diff --git a/tests/ui/const-generics/anon-const-type-of-issue-158818.stderr b/tests/ui/const-generics/anon-const-type-of-issue-158818.stderr index 3e5445b9f469a..d2cbd4e7bf76d 100644 --- a/tests/ui/const-generics/anon-const-type-of-issue-158818.stderr +++ b/tests/ui/const-generics/anon-const-type-of-issue-158818.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/anon-const-type-of-issue-158818.rs:7:21 | LL | with_option::<{ async || {} }>(); - | ^^^^^^^^^^^ expected `u32`, found `{async closure@anon-const-type-of-issue-158818.rs:7:21}` + | ^^^^^^^^^^^ expected `u32`, found `{async closure@...}` | = note: expected type `u32` found closure `{async closure@$DIR/anon-const-type-of-issue-158818.rs:7:21: 7:29}` diff --git a/tests/ui/const-generics/anon-const-type-of-qualified-path-issue-158818.rs b/tests/ui/const-generics/anon-const-type-of-qualified-path-issue-158818.rs index a8c17c00f2418..38a2a1eaf60b9 100644 --- a/tests/ui/const-generics/anon-const-type-of-qualified-path-issue-158818.rs +++ b/tests/ui/const-generics/anon-const-type-of-qualified-path-issue-158818.rs @@ -7,3 +7,5 @@ fn with_option() { crate::with_option::<{ async || {} }>(); //~^ ERROR mismatched types } + +//@ normalize-stderr: "found `\{async closure@[^`]*\}`" -> "found `{async closure@...}`" diff --git a/tests/ui/const-generics/anon-const-type-of-qualified-path-issue-158818.stderr b/tests/ui/const-generics/anon-const-type-of-qualified-path-issue-158818.stderr index 855a68e221fbf..9c2dcc9570858 100644 --- a/tests/ui/const-generics/anon-const-type-of-qualified-path-issue-158818.stderr +++ b/tests/ui/const-generics/anon-const-type-of-qualified-path-issue-158818.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/anon-const-type-of-qualified-path-issue-158818.rs:7:28 | LL | crate::with_option::<{ async || {} }>(); - | ^^^^^^^^^^^ expected `u32`, found `{async closure@anon-const-type-of-qualified-path-issue-158818.rs:7:28}` + | ^^^^^^^^^^^ expected `u32`, found `{async closure@...}` | = note: expected type `u32` found closure `{async closure@$DIR/anon-const-type-of-qualified-path-issue-158818.rs:7:28: 7:36}` From 7025329d57ec4975458e01ebc933cd2e2818c754 Mon Sep 17 00:00:00 2001 From: Joao Roberto Date: Mon, 27 Jul 2026 10:26:53 -0300 Subject: [PATCH 05/10] Retry CI after Docker Hub timeout From 5676f71e219e06a5d3904935f133cdc9110da9b7 Mon Sep 17 00:00:00 2001 From: Joao Roberto Date: Thu, 30 Jul 2026 15:57:32 -0300 Subject: [PATCH 06/10] Move const arg type error into closure --- .../rustc_hir_analysis/src/collect/type_of.rs | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 0c33d9b58ff37..b41d86413974a 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -381,8 +381,16 @@ fn anon_const_type_of<'tcx>(icx: &ItemCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx fn const_arg_anon_type_of<'tcx>(icx: &ItemCtxt<'tcx>, arg_hir_id: HirId, span: Span) -> Ty<'tcx> { use hir::*; + use rustc_middle::ty::Ty; let tcx = icx.tcx; + let type_error = || { + Ty::new_error_with_message( + tcx, + span, + "`type_of` called on const argument's anon const before the const argument was lowered", + ) + }; match tcx.parent_hir_node(arg_hir_id) { // Array length const arguments do not have `type_of` fed as there is never a corresponding @@ -405,24 +413,15 @@ fn const_arg_anon_type_of<'tcx>(icx: &ItemCtxt<'tcx>, arg_hir_id: HirId, span: S } Node::Expr(Expr { kind: ExprKind::Path(qpath), .. }) => { - path_const_arg_anon_type_of(icx, qpath, arg_hir_id) - .unwrap_or_else(|| const_arg_anon_type_error(tcx, span)) + path_const_arg_anon_type_of(icx, qpath, arg_hir_id).unwrap_or_else(type_error) } // This is not a `bug!` as const arguments in path segments that did not resolve to anything // will result in `type_of` never being fed. - _ => const_arg_anon_type_error(tcx, span), + _ => type_error(), } } -fn const_arg_anon_type_error<'tcx>(tcx: TyCtxt<'tcx>, span: Span) -> Ty<'tcx> { - Ty::new_error_with_message( - tcx, - span, - "`type_of` called on const argument's anon const before the const argument was lowered", - ) -} - fn path_const_arg_anon_type_of<'tcx>( icx: &ItemCtxt<'tcx>, qpath: &hir::QPath<'tcx>, From c374b4684f8b1468f70aa180144b77d36cd81b3f Mon Sep 17 00:00:00 2001 From: Joao Roberto Date: Sun, 2 Aug 2026 17:46:00 -0300 Subject: [PATCH 07/10] Recover anon const arg type across omittable params Generalize the recovery to match arguments positionally against the generic parameters, skipping those that need no explicit argument: elided early-bound lifetimes, synthetic `impl Trait` type parameters, and trailing type parameters with defaults. Bail only when there are more arguments than can be matched. Omitting such a parameter leaves fewer arguments than parameters, so the exact-count check made recovery feed `{type error}` for the anon const while the real lowering later fed the true type, tripping a double-feed ICE under the `-Zthreads=0` front-end race. --- .../rustc_hir_analysis/src/collect/type_of.rs | 40 +++++++++++++++---- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index b41d86413974a..934c4c23c50c0 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -455,11 +455,6 @@ fn expected_const_arg_type<'tcx>( return None; } - let [hir::GenericArg::Const(const_arg)] = generic_args.args else { return None }; - if const_arg.hir_id != arg_hir_id { - return None; - } - let generics = tcx.generics_of(def_id); if generics.parent.is_some() || generics.parent_count != 0 @@ -469,11 +464,42 @@ fn expected_const_arg_type<'tcx>( return None; } - let [param] = generics.own_params.as_slice() else { return None }; - if !matches!(param.kind, ty::GenericParamDefKind::Const { .. }) { + // Early lifetimes may be elided, `impl Trait` parameters are synthesized without a + // corresponding HIR argument, and trailing parameters with defaults may be omitted. All of + // these can leave fewer arguments than parameters, so only bail out when there are *more* + // arguments than can be matched positionally. + let has_lifetime_args = generic_args.has_lifetime_args(); + let params_with_explicit_args = || { + generics.own_params.iter().filter(|param| match param.kind { + ty::GenericParamDefKind::Lifetime => has_lifetime_args, + ty::GenericParamDefKind::Type { synthetic, .. } => !synthetic, + ty::GenericParamDefKind::Const { .. } => true, + }) + }; + + if generic_args.args.len() > params_with_explicit_args().count() { return None; } + let mut target_param = None; + for (arg, param) in generic_args.args.iter().zip(params_with_explicit_args()) { + match (arg, ¶m.kind) { + (hir::GenericArg::Lifetime(_), ty::GenericParamDefKind::Lifetime) + | ( + hir::GenericArg::Type(_) | hir::GenericArg::Infer(_), + ty::GenericParamDefKind::Type { .. }, + ) => {} + (hir::GenericArg::Const(const_arg), ty::GenericParamDefKind::Const { .. }) => { + if const_arg.hir_id == arg_hir_id { + target_param = Some(param); + } + } + (hir::GenericArg::Infer(_), ty::GenericParamDefKind::Const { .. }) => {} + _ => return None, + } + } + let param = target_param?; + let ty = tcx.type_of(param.def_id).instantiate_identity().skip_norm_wip(); (!ty.has_non_region_param() && !ty.has_non_region_infer() From 5f3afb14d4d10535bdbf00acff5e152d8f22a084 Mon Sep 17 00:00:00 2001 From: Joao Roberto Date: Sun, 2 Aug 2026 17:46:14 -0300 Subject: [PATCH 08/10] Add regression tests for anon const type recovery Each exercises the early `type_of` query under the `-Zthreads=0` front-end race with an omittable generic parameter: a synthetic `impl Trait` param, an elided early-bound lifetime, multiple explicit args, and a defaulted trailing type parameter. --- ...st-type-of-defaulted-param-issue-158818.rs | 12 ++++++++++ ...ype-of-defaulted-param-issue-158818.stderr | 22 +++++++++++++++++++ ...onst-type-of-multiple-args-issue-158818.rs | 11 ++++++++++ ...-type-of-multiple-args-issue-158818.stderr | 12 ++++++++++ ...t-type-of-omitted-lifetime-issue-158818.rs | 14 ++++++++++++ ...pe-of-omitted-lifetime-issue-158818.stderr | 12 ++++++++++ ...st-type-of-synthetic-param-issue-158818.rs | 11 ++++++++++ ...ype-of-synthetic-param-issue-158818.stderr | 12 ++++++++++ 8 files changed, 106 insertions(+) create mode 100644 tests/ui/const-generics/anon-const-type-of-defaulted-param-issue-158818.rs create mode 100644 tests/ui/const-generics/anon-const-type-of-defaulted-param-issue-158818.stderr create mode 100644 tests/ui/const-generics/anon-const-type-of-multiple-args-issue-158818.rs create mode 100644 tests/ui/const-generics/anon-const-type-of-multiple-args-issue-158818.stderr create mode 100644 tests/ui/const-generics/anon-const-type-of-omitted-lifetime-issue-158818.rs create mode 100644 tests/ui/const-generics/anon-const-type-of-omitted-lifetime-issue-158818.stderr create mode 100644 tests/ui/const-generics/anon-const-type-of-synthetic-param-issue-158818.rs create mode 100644 tests/ui/const-generics/anon-const-type-of-synthetic-param-issue-158818.stderr diff --git a/tests/ui/const-generics/anon-const-type-of-defaulted-param-issue-158818.rs b/tests/ui/const-generics/anon-const-type-of-defaulted-param-issue-158818.rs new file mode 100644 index 0000000000000..e10f46176ebb3 --- /dev/null +++ b/tests/ui/const-generics/anon-const-type-of-defaulted-param-issue-158818.rs @@ -0,0 +1,12 @@ +//@ edition: 2024 +//@ compile-flags: -Zthreads=0 --crate-type lib + +#![allow(dead_code)] +#![allow(invalid_type_param_default)] + +fn f() { + f::<{ async || {} }>(); + //~^ ERROR mismatched types +} + +//@ normalize-stderr: "found `\{async closure@[^`]*\}`" -> "found `{async closure@...}`" diff --git a/tests/ui/const-generics/anon-const-type-of-defaulted-param-issue-158818.stderr b/tests/ui/const-generics/anon-const-type-of-defaulted-param-issue-158818.stderr new file mode 100644 index 0000000000000..33071f2a3a8df --- /dev/null +++ b/tests/ui/const-generics/anon-const-type-of-defaulted-param-issue-158818.stderr @@ -0,0 +1,22 @@ +error[E0308]: mismatched types + --> $DIR/anon-const-type-of-defaulted-param-issue-158818.rs:8:11 + | +LL | f::<{ async || {} }>(); + | ^^^^^^^^^^^ expected `u8`, found `{async closure@...}` + | + = note: expected type `u8` + found closure `{async closure@$DIR/anon-const-type-of-defaulted-param-issue-158818.rs:8:11: 8:19}` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. +Future incompatibility report: Future breakage diagnostic: +warning: defaults for generic parameters are not allowed here + --> $DIR/anon-const-type-of-defaulted-param-issue-158818.rs:7:19 + | +LL | fn f() { + | ^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #36887 + diff --git a/tests/ui/const-generics/anon-const-type-of-multiple-args-issue-158818.rs b/tests/ui/const-generics/anon-const-type-of-multiple-args-issue-158818.rs new file mode 100644 index 0000000000000..f4257bf245b68 --- /dev/null +++ b/tests/ui/const-generics/anon-const-type-of-multiple-args-issue-158818.rs @@ -0,0 +1,11 @@ +//@ edition: 2024 +//@ compile-flags: -Zthreads=0 --crate-type lib + +#![allow(dead_code)] + +fn f() { + f::(); + //~^ ERROR mismatched types +} + +//@ normalize-stderr: "found `\{async closure@[^`]*\}`" -> "found `{async closure@...}`" diff --git a/tests/ui/const-generics/anon-const-type-of-multiple-args-issue-158818.stderr b/tests/ui/const-generics/anon-const-type-of-multiple-args-issue-158818.stderr new file mode 100644 index 0000000000000..6ce0d39dbb6de --- /dev/null +++ b/tests/ui/const-generics/anon-const-type-of-multiple-args-issue-158818.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/anon-const-type-of-multiple-args-issue-158818.rs:7:15 + | +LL | f::(); + | ^^^^^^^^^^^ expected `u8`, found `{async closure@...}` + | + = note: expected type `u8` + found closure `{async closure@$DIR/anon-const-type-of-multiple-args-issue-158818.rs:7:15: 7:23}` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/anon-const-type-of-omitted-lifetime-issue-158818.rs b/tests/ui/const-generics/anon-const-type-of-omitted-lifetime-issue-158818.rs new file mode 100644 index 0000000000000..caff674789378 --- /dev/null +++ b/tests/ui/const-generics/anon-const-type-of-omitted-lifetime-issue-158818.rs @@ -0,0 +1,14 @@ +//@ edition: 2024 +//@ compile-flags: -Zthreads=0 --crate-type lib + +#![allow(dead_code)] + +fn f<'a, const N: u8>() +where + 'a: 'static, +{ + f::<{ async || {} }>(); + //~^ ERROR mismatched types +} + +//@ normalize-stderr: "found `\{async closure@[^`]*\}`" -> "found `{async closure@...}`" diff --git a/tests/ui/const-generics/anon-const-type-of-omitted-lifetime-issue-158818.stderr b/tests/ui/const-generics/anon-const-type-of-omitted-lifetime-issue-158818.stderr new file mode 100644 index 0000000000000..601fa14224c22 --- /dev/null +++ b/tests/ui/const-generics/anon-const-type-of-omitted-lifetime-issue-158818.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/anon-const-type-of-omitted-lifetime-issue-158818.rs:10:11 + | +LL | f::<{ async || {} }>(); + | ^^^^^^^^^^^ expected `u8`, found `{async closure@...}` + | + = note: expected type `u8` + found closure `{async closure@$DIR/anon-const-type-of-omitted-lifetime-issue-158818.rs:10:11: 10:19}` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/anon-const-type-of-synthetic-param-issue-158818.rs b/tests/ui/const-generics/anon-const-type-of-synthetic-param-issue-158818.rs new file mode 100644 index 0000000000000..3957c27613150 --- /dev/null +++ b/tests/ui/const-generics/anon-const-type-of-synthetic-param-issue-158818.rs @@ -0,0 +1,11 @@ +//@ edition: 2024 +//@ compile-flags: -Zthreads=0 --crate-type lib + +#![allow(dead_code)] + +fn f(_: impl Sized) { + f::<{ async || {} }>(()); + //~^ ERROR mismatched types +} + +//@ normalize-stderr: "found `\{async closure@[^`]*\}`" -> "found `{async closure@...}`" diff --git a/tests/ui/const-generics/anon-const-type-of-synthetic-param-issue-158818.stderr b/tests/ui/const-generics/anon-const-type-of-synthetic-param-issue-158818.stderr new file mode 100644 index 0000000000000..44dcb77bb8413 --- /dev/null +++ b/tests/ui/const-generics/anon-const-type-of-synthetic-param-issue-158818.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/anon-const-type-of-synthetic-param-issue-158818.rs:7:11 + | +LL | f::<{ async || {} }>(()); + | ^^^^^^^^^^^ expected `u8`, found `{async closure@...}` + | + = note: expected type `u8` + found closure `{async closure@$DIR/anon-const-type-of-synthetic-param-issue-158818.rs:7:11: 7:19}` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. From e35c6ea6132ddbc7e6287f93a51df6e29e68abdc Mon Sep 17 00:00:00 2001 From: Joao Roberto Date: Fri, 21 Aug 2026 14:24:53 -0300 Subject: [PATCH 09/10] Generate coroutine by-move bodies after typeck `needs_coroutine_by_move_body_def_id` asks for `type_of`, and for a body owner nested inside a const argument's anon const that goes through `typeck` of the anon const, which needs the anon const's own type. That type is never computed, only fed while the enclosing body is type-checked. Asking for it in the same pass that type-checks the bodies lets the parallel front end reach the nested body owner first, computing and caching an error type for the anon const that then conflicts with the type fed later on. Since nothing reports an error in that case, the delayed bugs surface as an ICE. Split it into a second pass over the body owners so every body has been type-checked, and every const argument lowered, before any nested body owner is asked for its type. --- compiler/rustc_hir_analysis/src/lib.rs | 10 +++ .../anon-const-type-of-issue-158818.rs | 64 +++++++++++++- .../anon-const-type-of-issue-158818.stderr | 84 +++++++++++++++++-- 3 files changed, 149 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 1f342f10f8b17..0e79764a3e456 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -194,6 +194,16 @@ pub fn check_crate(tcx: TyCtxt<'_>) { { tcx.ensure_ok().typeck(item_def_id); } + }); + + // This has to be a second pass over the body owners, after every body has been + // type-checked above. `needs_coroutine_by_move_body_def_id` asks for `type_of`, and for a + // body owner nested inside a const argument's anon const that goes through `typeck` of the + // anon const, which needs the anon const's own type. That type is never computed, only fed + // while the enclosing body is type-checked. Doing this in the pass above lets the parallel + // front end reach the nested body owner first, computing (and caching) an error type for + // the anon const that then conflicts with the type fed later on. + tcx.par_hir_body_owners(|item_def_id| { // Ensure we generate the new `DefId` before finishing `check_crate`. // Afterwards we freeze the list of `DefId`s. if tcx.needs_coroutine_by_move_body_def_id(item_def_id.to_def_id()) { diff --git a/tests/ui/const-generics/anon-const-type-of-issue-158818.rs b/tests/ui/const-generics/anon-const-type-of-issue-158818.rs index cd81244b21a5a..3052ceefa4759 100644 --- a/tests/ui/const-generics/anon-const-type-of-issue-158818.rs +++ b/tests/ui/const-generics/anon-const-type-of-issue-158818.rs @@ -1,11 +1,69 @@ +// The type of a const argument's anon const is never computed, only fed while the enclosing body +// is type-checked. Under the parallel front end, `check_crate` used to ask for the `type_of` of a +// body owner nested inside such an anon const before that had happened, computing and caching an +// error type that then conflicted with the type fed later on. +// +// Each case below reaches the anon const through a different kind of path or position, none of +// which is resolved before the enclosing body is type-checked. They all live in one body so that +// the parallel front end cannot interleave their diagnostics. + //@ edition: 2024 //@ compile-flags: -Zthreads=0 --crate-type lib #![allow(dead_code)] -fn with_option() { - with_option::<{ async || {} }>(); +struct Foo; +struct Tuple(u8); + +trait Trait { + fn assoc(); +} + +impl Trait for Foo<0> { + fn assoc() {} +} + +impl Foo { + fn inherent() {} +} + +mod submodule { + pub fn free() {} +} + +fn free() {} + +fn preceded() {} + +// The late-bound `'a` is not a generic parameter, leaving this function with fewer parameters +// than it declares. Elided late-bound lifetimes in the signature do the same. +fn late_bound<'a, const N: u8>(_: &'a ()) {} + +// `impl Sized` is a synthetic parameter, with no argument of its own. +fn synthetic(_: impl Sized) {} + +fn cases() { + free::<{ async || {} }>(); + //~^ ERROR mismatched types + submodule::free::<{ async || {} }>(); + //~^ ERROR mismatched types + preceded::(); + //~^ ERROR mismatched types + late_bound::<{ async || {} }>(&()); + //~^ ERROR mismatched types + synthetic::<{ async || {} }>(()); + //~^ ERROR mismatched types + as Trait>::assoc::<{ async || {} }>(); + //~^ ERROR mismatched types + Foo::<0>::inherent::<{ async || {} }>(); + //~^ ERROR mismatched types + let _ = Tuple::<{ async || {} }>(0); + //~^ ERROR mismatched types + + // Not a path expression at all: the const argument sits in a type annotation, and is only + // lowered once typeck reaches this statement. + let _: Foo<{ async || {} }>; //~^ ERROR mismatched types } -//@ normalize-stderr: "found `\{async closure@[^`]*\}`" -> "found `{async closure@...}`" +//@ normalize-stderr: "\{async closure@[^`]*\}" -> "{async closure@...}" diff --git a/tests/ui/const-generics/anon-const-type-of-issue-158818.stderr b/tests/ui/const-generics/anon-const-type-of-issue-158818.stderr index d2cbd4e7bf76d..d0ee9786e294c 100644 --- a/tests/ui/const-generics/anon-const-type-of-issue-158818.stderr +++ b/tests/ui/const-generics/anon-const-type-of-issue-158818.stderr @@ -1,12 +1,84 @@ error[E0308]: mismatched types - --> $DIR/anon-const-type-of-issue-158818.rs:7:21 + --> $DIR/anon-const-type-of-issue-158818.rs:46:14 | -LL | with_option::<{ async || {} }>(); - | ^^^^^^^^^^^ expected `u32`, found `{async closure@...}` +LL | free::<{ async || {} }>(); + | ^^^^^^^^^^^ expected `u8`, found `{async closure@...}` | - = note: expected type `u32` - found closure `{async closure@$DIR/anon-const-type-of-issue-158818.rs:7:21: 7:29}` + = note: expected type `u8` + found closure `{async closure@...}` -error: aborting due to 1 previous error +error[E0308]: mismatched types + --> $DIR/anon-const-type-of-issue-158818.rs:48:25 + | +LL | submodule::free::<{ async || {} }>(); + | ^^^^^^^^^^^ expected `u8`, found `{async closure@...}` + | + = note: expected type `u8` + found closure `{async closure@...}` + +error[E0308]: mismatched types + --> $DIR/anon-const-type-of-issue-158818.rs:50:22 + | +LL | preceded::(); + | ^^^^^^^^^^^ expected `u8`, found `{async closure@...}` + | + = note: expected type `u8` + found closure `{async closure@...}` + +error[E0308]: mismatched types + --> $DIR/anon-const-type-of-issue-158818.rs:52:20 + | +LL | late_bound::<{ async || {} }>(&()); + | ^^^^^^^^^^^ expected `u8`, found `{async closure@...}` + | + = note: expected type `u8` + found closure `{async closure@...}` + +error[E0308]: mismatched types + --> $DIR/anon-const-type-of-issue-158818.rs:54:19 + | +LL | synthetic::<{ async || {} }>(()); + | ^^^^^^^^^^^ expected `u8`, found `{async closure@...}` + | + = note: expected type `u8` + found closure `{async closure@...}` + +error[E0308]: mismatched types + --> $DIR/anon-const-type-of-issue-158818.rs:56:34 + | +LL | as Trait>::assoc::<{ async || {} }>(); + | ^^^^^^^^^^^ expected `u8`, found `{async closure@...}` + | + = note: expected type `u8` + found closure `{async closure@...}` + +error[E0308]: mismatched types + --> $DIR/anon-const-type-of-issue-158818.rs:58:28 + | +LL | Foo::<0>::inherent::<{ async || {} }>(); + | ^^^^^^^^^^^ expected `u8`, found `{async closure@...}` + | + = note: expected type `u8` + found closure `{async closure@...}` + +error[E0308]: mismatched types + --> $DIR/anon-const-type-of-issue-158818.rs:60:23 + | +LL | let _ = Tuple::<{ async || {} }>(0); + | ^^^^^^^^^^^ expected `u8`, found `{async closure@...}` + | + = note: expected type `u8` + found closure `{async closure@...}` + +error[E0308]: mismatched types + --> $DIR/anon-const-type-of-issue-158818.rs:65:18 + | +LL | let _: Foo<{ async || {} }>; + | ^^^^^^^^^^^ expected `u8`, found `{async closure@...}` + | + = note: expected type `u8` + found closure `{async closure@...}` + +error: aborting due to 9 previous errors For more information about this error, try `rustc --explain E0308`. From 023a32724805ecf16203ef770ffa053e8b1ca84c Mon Sep 17 00:00:00 2001 From: Joao Roberto Date: Fri, 21 Aug 2026 14:26:54 -0300 Subject: [PATCH 10/10] Remove anon const type recovery from type_of Recovering the type from the HIR path meant re-deriving what the generic argument lowering already works out, and only covered the cases the partial classifier recognized: free function paths resolved to `DefKind::Fn`, with no late-bound lifetimes. Anything else still cached an error type and tripped the double-feed ICE, including associated functions, tuple struct constructors, inherent type-relative paths, and const arguments in type annotations, which are not path expressions at all and so cannot be classified this way. With the by-move bodies generated after typeck the anon const's type is always fed before anything asks for it, so drop the recovery along with the tests that only exercised its argument counting. The shapes they covered are folded into the main regression test. --- .../rustc_hir_analysis/src/collect/type_of.rs | 103 +----------------- ...onst-type-of-multiple-args-issue-158818.rs | 11 -- ...-type-of-multiple-args-issue-158818.stderr | 12 -- ...t-type-of-omitted-lifetime-issue-158818.rs | 14 --- ...pe-of-omitted-lifetime-issue-158818.stderr | 12 -- ...nst-type-of-qualified-path-issue-158818.rs | 11 -- ...type-of-qualified-path-issue-158818.stderr | 12 -- ...st-type-of-synthetic-param-issue-158818.rs | 11 -- ...ype-of-synthetic-param-issue-158818.stderr | 12 -- 9 files changed, 5 insertions(+), 193 deletions(-) delete mode 100644 tests/ui/const-generics/anon-const-type-of-multiple-args-issue-158818.rs delete mode 100644 tests/ui/const-generics/anon-const-type-of-multiple-args-issue-158818.stderr delete mode 100644 tests/ui/const-generics/anon-const-type-of-omitted-lifetime-issue-158818.rs delete mode 100644 tests/ui/const-generics/anon-const-type-of-omitted-lifetime-issue-158818.stderr delete mode 100644 tests/ui/const-generics/anon-const-type-of-qualified-path-issue-158818.rs delete mode 100644 tests/ui/const-generics/anon-const-type-of-qualified-path-issue-158818.stderr delete mode 100644 tests/ui/const-generics/anon-const-type-of-synthetic-param-issue-158818.rs delete mode 100644 tests/ui/const-generics/anon-const-type-of-synthetic-param-issue-158818.stderr diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 934c4c23c50c0..3402f56bef6dc 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -384,13 +384,6 @@ fn const_arg_anon_type_of<'tcx>(icx: &ItemCtxt<'tcx>, arg_hir_id: HirId, span: S use rustc_middle::ty::Ty; let tcx = icx.tcx; - let type_error = || { - Ty::new_error_with_message( - tcx, - span, - "`type_of` called on const argument's anon const before the const argument was lowered", - ) - }; match tcx.parent_hir_node(arg_hir_id) { // Array length const arguments do not have `type_of` fed as there is never a corresponding @@ -412,100 +405,14 @@ fn const_arg_anon_type_of<'tcx>(icx: &ItemCtxt<'tcx>, arg_hir_id: HirId, span: S icx.lower_ty(ty) } - Node::Expr(Expr { kind: ExprKind::Path(qpath), .. }) => { - path_const_arg_anon_type_of(icx, qpath, arg_hir_id).unwrap_or_else(type_error) - } - // This is not a `bug!` as const arguments in path segments that did not resolve to anything // will result in `type_of` never being fed. - _ => type_error(), - } -} - -fn path_const_arg_anon_type_of<'tcx>( - icx: &ItemCtxt<'tcx>, - qpath: &hir::QPath<'tcx>, - arg_hir_id: HirId, -) -> Option> { - if let hir::QPath::Resolved(None, path) = qpath { - let segment = path.segments.last()?; - let hir::def::Res::Def(hir::def::DefKind::Fn, def_id) = segment.res else { - return None; - }; - expected_const_arg_type(icx.tcx, def_id, segment, arg_hir_id) - } else { - None - } -} - -fn expected_const_arg_type<'tcx>( - tcx: TyCtxt<'tcx>, - def_id: DefId, - segment: &hir::PathSegment<'tcx>, - arg_hir_id: HirId, -) -> Option> { - if segment.infer_args { - return None; - } - - let generic_args = segment.args(); - if !generic_args.constraints.is_empty() - || generic_args.parenthesized != hir::GenericArgsParentheses::No - { - return None; - } - - let generics = tcx.generics_of(def_id); - if generics.parent.is_some() - || generics.parent_count != 0 - || generics.has_self - || generics.has_late_bound_regions.is_some() - { - return None; - } - - // Early lifetimes may be elided, `impl Trait` parameters are synthesized without a - // corresponding HIR argument, and trailing parameters with defaults may be omitted. All of - // these can leave fewer arguments than parameters, so only bail out when there are *more* - // arguments than can be matched positionally. - let has_lifetime_args = generic_args.has_lifetime_args(); - let params_with_explicit_args = || { - generics.own_params.iter().filter(|param| match param.kind { - ty::GenericParamDefKind::Lifetime => has_lifetime_args, - ty::GenericParamDefKind::Type { synthetic, .. } => !synthetic, - ty::GenericParamDefKind::Const { .. } => true, - }) - }; - - if generic_args.args.len() > params_with_explicit_args().count() { - return None; - } - - let mut target_param = None; - for (arg, param) in generic_args.args.iter().zip(params_with_explicit_args()) { - match (arg, ¶m.kind) { - (hir::GenericArg::Lifetime(_), ty::GenericParamDefKind::Lifetime) - | ( - hir::GenericArg::Type(_) | hir::GenericArg::Infer(_), - ty::GenericParamDefKind::Type { .. }, - ) => {} - (hir::GenericArg::Const(const_arg), ty::GenericParamDefKind::Const { .. }) => { - if const_arg.hir_id == arg_hir_id { - target_param = Some(param); - } - } - (hir::GenericArg::Infer(_), ty::GenericParamDefKind::Const { .. }) => {} - _ => return None, - } + _ => Ty::new_error_with_message( + tcx, + span, + "`type_of` called on const argument's anon const before the const argument was lowered", + ), } - let param = target_param?; - - let ty = tcx.type_of(param.def_id).instantiate_identity().skip_norm_wip(); - (!ty.has_non_region_param() - && !ty.has_non_region_infer() - && !ty.has_free_regions() - && !ty.has_erased_regions()) - .then_some(ty) } fn infer_placeholder_type<'tcx>( diff --git a/tests/ui/const-generics/anon-const-type-of-multiple-args-issue-158818.rs b/tests/ui/const-generics/anon-const-type-of-multiple-args-issue-158818.rs deleted file mode 100644 index f4257bf245b68..0000000000000 --- a/tests/ui/const-generics/anon-const-type-of-multiple-args-issue-158818.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ edition: 2024 -//@ compile-flags: -Zthreads=0 --crate-type lib - -#![allow(dead_code)] - -fn f() { - f::(); - //~^ ERROR mismatched types -} - -//@ normalize-stderr: "found `\{async closure@[^`]*\}`" -> "found `{async closure@...}`" diff --git a/tests/ui/const-generics/anon-const-type-of-multiple-args-issue-158818.stderr b/tests/ui/const-generics/anon-const-type-of-multiple-args-issue-158818.stderr deleted file mode 100644 index 6ce0d39dbb6de..0000000000000 --- a/tests/ui/const-generics/anon-const-type-of-multiple-args-issue-158818.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/anon-const-type-of-multiple-args-issue-158818.rs:7:15 - | -LL | f::(); - | ^^^^^^^^^^^ expected `u8`, found `{async closure@...}` - | - = note: expected type `u8` - found closure `{async closure@$DIR/anon-const-type-of-multiple-args-issue-158818.rs:7:15: 7:23}` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/anon-const-type-of-omitted-lifetime-issue-158818.rs b/tests/ui/const-generics/anon-const-type-of-omitted-lifetime-issue-158818.rs deleted file mode 100644 index caff674789378..0000000000000 --- a/tests/ui/const-generics/anon-const-type-of-omitted-lifetime-issue-158818.rs +++ /dev/null @@ -1,14 +0,0 @@ -//@ edition: 2024 -//@ compile-flags: -Zthreads=0 --crate-type lib - -#![allow(dead_code)] - -fn f<'a, const N: u8>() -where - 'a: 'static, -{ - f::<{ async || {} }>(); - //~^ ERROR mismatched types -} - -//@ normalize-stderr: "found `\{async closure@[^`]*\}`" -> "found `{async closure@...}`" diff --git a/tests/ui/const-generics/anon-const-type-of-omitted-lifetime-issue-158818.stderr b/tests/ui/const-generics/anon-const-type-of-omitted-lifetime-issue-158818.stderr deleted file mode 100644 index 601fa14224c22..0000000000000 --- a/tests/ui/const-generics/anon-const-type-of-omitted-lifetime-issue-158818.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/anon-const-type-of-omitted-lifetime-issue-158818.rs:10:11 - | -LL | f::<{ async || {} }>(); - | ^^^^^^^^^^^ expected `u8`, found `{async closure@...}` - | - = note: expected type `u8` - found closure `{async closure@$DIR/anon-const-type-of-omitted-lifetime-issue-158818.rs:10:11: 10:19}` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/anon-const-type-of-qualified-path-issue-158818.rs b/tests/ui/const-generics/anon-const-type-of-qualified-path-issue-158818.rs deleted file mode 100644 index 38a2a1eaf60b9..0000000000000 --- a/tests/ui/const-generics/anon-const-type-of-qualified-path-issue-158818.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ edition: 2024 -//@ compile-flags: -Zthreads=0 --crate-type lib - -#![allow(dead_code)] - -fn with_option() { - crate::with_option::<{ async || {} }>(); - //~^ ERROR mismatched types -} - -//@ normalize-stderr: "found `\{async closure@[^`]*\}`" -> "found `{async closure@...}`" diff --git a/tests/ui/const-generics/anon-const-type-of-qualified-path-issue-158818.stderr b/tests/ui/const-generics/anon-const-type-of-qualified-path-issue-158818.stderr deleted file mode 100644 index 9c2dcc9570858..0000000000000 --- a/tests/ui/const-generics/anon-const-type-of-qualified-path-issue-158818.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/anon-const-type-of-qualified-path-issue-158818.rs:7:28 - | -LL | crate::with_option::<{ async || {} }>(); - | ^^^^^^^^^^^ expected `u32`, found `{async closure@...}` - | - = note: expected type `u32` - found closure `{async closure@$DIR/anon-const-type-of-qualified-path-issue-158818.rs:7:28: 7:36}` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/anon-const-type-of-synthetic-param-issue-158818.rs b/tests/ui/const-generics/anon-const-type-of-synthetic-param-issue-158818.rs deleted file mode 100644 index 3957c27613150..0000000000000 --- a/tests/ui/const-generics/anon-const-type-of-synthetic-param-issue-158818.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ edition: 2024 -//@ compile-flags: -Zthreads=0 --crate-type lib - -#![allow(dead_code)] - -fn f(_: impl Sized) { - f::<{ async || {} }>(()); - //~^ ERROR mismatched types -} - -//@ normalize-stderr: "found `\{async closure@[^`]*\}`" -> "found `{async closure@...}`" diff --git a/tests/ui/const-generics/anon-const-type-of-synthetic-param-issue-158818.stderr b/tests/ui/const-generics/anon-const-type-of-synthetic-param-issue-158818.stderr deleted file mode 100644 index 44dcb77bb8413..0000000000000 --- a/tests/ui/const-generics/anon-const-type-of-synthetic-param-issue-158818.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/anon-const-type-of-synthetic-param-issue-158818.rs:7:11 - | -LL | f::<{ async || {} }>(()); - | ^^^^^^^^^^^ expected `u8`, found `{async closure@...}` - | - = note: expected type `u8` - found closure `{async closure@$DIR/anon-const-type-of-synthetic-param-issue-158818.rs:7:11: 7:19}` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0308`.