diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 06e83a7486100..47bea76adf664 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2815,6 +2815,18 @@ impl<'hir> LoweringContext<'_, 'hir> { ) -> hir::ConstArg<'hir> { let tcx = self.tcx; + // Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments + // currently have to be wrapped in curly brackets, so it's necessary to special-case. + let expr = if let ExprKind::Block(block, _) = &anon.value.kind + && let [stmt] = block.stmts.as_slice() + && let StmtKind::Expr(expr) = &stmt.kind + && let ExprKind::Path(..) = &expr.kind + { + expr + } else { + &anon.value + }; + // We cannot change parsing depending on feature gates available, // we can only require feature gates to be active as a delayed check. // Thus we just parse anon consts generally and make the real decision @@ -2830,22 +2842,22 @@ impl<'hir> LoweringContext<'_, 'hir> { span: lowered_anon.span, } } + MgcaDisambiguation::Direct + if self.direct_const_arg_has_primitive_fallback_path(&expr) => + { + // Primitive associated constants rely on expression fallback + self.create_def(anon.id, None, DefKind::AnonConst, span); + let lowered_anon = self.lower_anon_const_to_anon_const(anon, span); + ConstArg { + hir_id: self.next_id(), + kind: hir::ConstArgKind::Anon(lowered_anon), + span: lowered_anon.span, + } + } MgcaDisambiguation::Direct => self.lower_expr_to_const_arg_direct(&anon.value), }; } - // Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments - // currently have to be wrapped in curly brackets, so it's necessary to special-case. - let expr = if let ExprKind::Block(block, _) = &anon.value.kind - && let [stmt] = block.stmts.as_slice() - && let StmtKind::Expr(expr) = &stmt.kind - && let ExprKind::Path(..) = &expr.kind - { - expr - } else { - &anon.value - }; - let maybe_res = self.get_partial_res(expr.id).and_then(|partial_res| partial_res.full_res()); if let ExprKind::Path(qself, path) = &expr.kind @@ -2877,6 +2889,18 @@ impl<'hir> LoweringContext<'_, 'hir> { } } + fn direct_const_arg_has_primitive_fallback_path(&self, expr: &Expr) -> bool { + let ExprKind::Path(None, path) = &expr.kind else { + return false; + }; + + self.get_partial_res(expr.id).is_some_and(|partial_res| { + matches!(partial_res.base_res(), Res::PrimTy(_)) + && partial_res.unresolved_segments() > 0 + && partial_res.unresolved_segments() == path.segments.len() - 1 + }) + } + /// See [`hir::ConstArg`] for when to use this function vs /// [`Self::lower_anon_const_to_const_arg`]. fn lower_anon_const_to_anon_const( diff --git a/tests/ui/const-generics/gca/primitive-associated-consts-issue-158506.rs b/tests/ui/const-generics/gca/primitive-associated-consts-issue-158506.rs new file mode 100644 index 0000000000000..8e0d459be89cb --- /dev/null +++ b/tests/ui/const-generics/gca/primitive-associated-consts-issue-158506.rs @@ -0,0 +1,14 @@ +//@ check-pass + +#![feature(min_generic_const_args)] +#![allow(incomplete_features)] + +struct TakesU8; +struct TakesI8; + +type _U8Max = TakesU8<{ u8::MAX }>; +type _U8Min = TakesU8<{ u8::MIN }>; +type _I8Max = TakesI8<{ i8::MAX }>; +type _I8Min = TakesI8<{ i8::MIN }>; + +fn main() {}