@@ -38,8 +38,8 @@ use rustc_middle::middle::stability::AllowUnstable;
3838use rustc_middle:: mir:: interpret:: LitToConstInput ;
3939use rustc_middle:: ty:: print:: PrintPolyTraitRefExt as _;
4040use rustc_middle:: ty:: {
41- self , Const , GenericArgKind , GenericArgsRef , GenericParamDefKind , Ty , TyCtxt , TypeVisitableExt ,
42- TypingMode , Upcast , fold_regions,
41+ self , Const , GenericArgKind , GenericArgsRef , GenericParamDefKind , Ty , TyCtxt ,
42+ TypeSuperFoldable , TypeVisitableExt , TypingMode , Upcast , fold_regions,
4343} ;
4444use rustc_middle:: { bug, span_bug} ;
4545use rustc_session:: lint:: builtin:: AMBIGUOUS_ASSOCIATED_ITEMS ;
@@ -394,7 +394,118 @@ pub trait GenericArgsLowerer<'a, 'tcx> {
394394 ) -> ty:: GenericArg < ' tcx > ;
395395}
396396
397+ struct ForbidMCGParamUsesFolder < ' tcx > {
398+ tcx : TyCtxt < ' tcx > ,
399+ anon_const_def_id : LocalDefId ,
400+ span : Span ,
401+ is_self_alias : bool ,
402+ }
403+
404+ impl < ' tcx > ForbidMCGParamUsesFolder < ' tcx > {
405+ fn error ( & self ) -> ErrorGuaranteed {
406+ let msg = if self . is_self_alias {
407+ "generic `Self` types are currently not permitted in anonymous constants"
408+ } else {
409+ "generic parameters may not be used in const operations"
410+ } ;
411+ let mut diag = self . tcx . dcx ( ) . struct_span_err ( self . span , msg) ;
412+ if self . is_self_alias {
413+ let anon_const_hir_id: HirId = HirId :: make_owner ( self . anon_const_def_id ) ;
414+ let parent_impl = self . tcx . hir_parent_owner_iter ( anon_const_hir_id) . find_map (
415+ |( _, node) | match node {
416+ hir:: OwnerNode :: Item ( hir:: Item {
417+ kind : hir:: ItemKind :: Impl ( impl_) , ..
418+ } ) => Some ( impl_) ,
419+ _ => None ,
420+ } ,
421+ ) ;
422+ if let Some ( impl_) = parent_impl {
423+ diag. span_note ( impl_. self_ty . span , "not a concrete type" ) ;
424+ }
425+ }
426+ diag. emit ( )
427+ }
428+ }
429+
430+ impl < ' tcx > ty:: TypeFolder < TyCtxt < ' tcx > > for ForbidMCGParamUsesFolder < ' tcx > {
431+ fn cx ( & self ) -> TyCtxt < ' tcx > {
432+ self . tcx
433+ }
434+
435+ fn fold_ty ( & mut self , t : Ty < ' tcx > ) -> Ty < ' tcx > {
436+ if matches ! ( t. kind( ) , ty:: Param ( ..) ) {
437+ return Ty :: new_error ( self . tcx , self . error ( ) ) ;
438+ }
439+ t. super_fold_with ( self )
440+ }
441+
442+ fn fold_const ( & mut self , c : Const < ' tcx > ) -> Const < ' tcx > {
443+ if matches ! ( c. kind( ) , ty:: ConstKind :: Param ( ..) ) {
444+ return Const :: new_error ( self . tcx , self . error ( ) ) ;
445+ }
446+ c. super_fold_with ( self )
447+ }
448+
449+ fn fold_region ( & mut self , r : ty:: Region < ' tcx > ) -> ty:: Region < ' tcx > {
450+ if matches ! ( r. kind( ) , ty:: RegionKind :: ReEarlyParam ( ..) | ty:: RegionKind :: ReLateParam ( ..) ) {
451+ return ty:: Region :: new_error ( self . tcx , self . error ( ) ) ;
452+ }
453+ r
454+ }
455+ }
456+
397457impl < ' tcx > dyn HirTyLowerer < ' tcx > + ' _ {
458+ /// See `check_param_uses_if_mcg`.
459+ ///
460+ /// FIXME(mgca): this is pub only for instantiate_value_path and would be nice to avoid altogether
461+ pub fn check_param_res_if_mcg_for_instantiate_value_path (
462+ & self ,
463+ res : Res ,
464+ span : Span ,
465+ ) -> Result < ( ) , ErrorGuaranteed > {
466+ let tcx = self . tcx ( ) ;
467+ let parent_def_id = self . item_def_id ( ) ;
468+ if let Res :: Def ( DefKind :: ConstParam , _) = res
469+ && tcx. def_kind ( parent_def_id) == DefKind :: AnonConst
470+ && let ty:: AnonConstKind :: MCG = tcx. anon_const_kind ( parent_def_id)
471+ {
472+ let folder = ForbidMCGParamUsesFolder {
473+ tcx,
474+ anon_const_def_id : parent_def_id,
475+ span,
476+ is_self_alias : false ,
477+ } ;
478+ return Err ( folder. error ( ) ) ;
479+ }
480+ Ok ( ( ) )
481+ }
482+
483+ /// Check for uses of generic parameters that are not in scope due to this being
484+ /// in a non-generic anon const context.
485+ #[ must_use = "need to use transformed output" ]
486+ fn check_param_uses_if_mcg < T > ( & self , term : T , span : Span , is_self_alias : bool ) -> T
487+ where
488+ T : ty:: TypeFoldable < TyCtxt < ' tcx > > ,
489+ {
490+ let tcx = self . tcx ( ) ;
491+ let parent_def_id = self . item_def_id ( ) ;
492+ if tcx. def_kind ( parent_def_id) == DefKind :: AnonConst
493+ && let ty:: AnonConstKind :: MCG = tcx. anon_const_kind ( parent_def_id)
494+ // Fast path if contains no params/escaping bound vars.
495+ && ( term. has_param ( ) || term. has_escaping_bound_vars ( ) )
496+ {
497+ let mut folder = ForbidMCGParamUsesFolder {
498+ tcx,
499+ anon_const_def_id : parent_def_id,
500+ span,
501+ is_self_alias,
502+ } ;
503+ term. fold_with ( & mut folder)
504+ } else {
505+ term
506+ }
507+ }
508+
398509 /// Lower a lifetime from the HIR to our internal notion of a lifetime called a *region*.
399510 #[ instrument( level = "debug" , skip( self ) , ret) ]
400511 pub fn lower_lifetime (
@@ -403,15 +514,16 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
403514 reason : RegionInferReason < ' _ > ,
404515 ) -> ty:: Region < ' tcx > {
405516 if let Some ( resolved) = self . tcx ( ) . named_bound_var ( lifetime. hir_id ) {
406- self . lower_resolved_lifetime ( resolved)
517+ let region = self . lower_resolved_lifetime ( resolved) ;
518+ self . check_param_uses_if_mcg ( region, lifetime. ident . span , false )
407519 } else {
408520 self . re_infer ( lifetime. ident . span , reason)
409521 }
410522 }
411523
412524 /// Lower a lifetime from the HIR to our internal notion of a lifetime called a *region*.
413525 #[ instrument( level = "debug" , skip( self ) , ret) ]
414- pub fn lower_resolved_lifetime ( & self , resolved : rbv:: ResolvedArg ) -> ty:: Region < ' tcx > {
526+ fn lower_resolved_lifetime ( & self , resolved : rbv:: ResolvedArg ) -> ty:: Region < ' tcx > {
415527 let tcx = self . tcx ( ) ;
416528
417529 match resolved {
@@ -1256,9 +1368,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
12561368 TypeRelativePath :: AssocItem ( def_id, args) => {
12571369 let alias_ty = ty:: AliasTy :: new_from_args ( tcx, def_id, args) ;
12581370 let ty = Ty :: new_alias ( tcx, alias_ty. kind ( tcx) , alias_ty) ;
1371+ let ty = self . check_param_uses_if_mcg ( ty, span, false ) ;
12591372 Ok ( ( ty, tcx. def_kind ( def_id) , def_id) )
12601373 }
12611374 TypeRelativePath :: Variant { adt, variant_did } => {
1375+ let adt = self . check_param_uses_if_mcg ( adt, span, false ) ;
12621376 Ok ( ( adt, DefKind :: Variant , variant_did) )
12631377 }
12641378 }
@@ -1275,7 +1389,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
12751389 span : Span ,
12761390 ) -> Result < Const < ' tcx > , ErrorGuaranteed > {
12771391 let tcx = self . tcx ( ) ;
1278- let ( def_id , args ) = match self . lower_type_relative_path (
1392+ match self . lower_type_relative_path (
12791393 self_ty,
12801394 hir_self_ty,
12811395 segment,
@@ -1292,15 +1406,16 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
12921406 err. note ( "the declaration in the trait must be marked with `#[type_const]`" ) ;
12931407 return Err ( err. emit ( ) ) ;
12941408 }
1295- ( def_id, args)
1409+ let ct = Const :: new_unevaluated ( tcx, ty:: UnevaluatedConst :: new ( def_id, args) ) ;
1410+ let ct = self . check_param_uses_if_mcg ( ct, span, false ) ;
1411+ Ok ( ct)
12961412 }
12971413 // FIXME(mgca): implement support for this once ready to support all adt ctor expressions,
12981414 // not just const ctors
12991415 TypeRelativePath :: Variant { .. } => {
13001416 span_bug ! ( span, "unexpected variant res for type associated const path" )
13011417 }
1302- } ;
1303- Ok ( Const :: new_unevaluated ( tcx, ty:: UnevaluatedConst :: new ( def_id, args) ) )
1418+ }
13041419 }
13051420
13061421 /// Lower a [type-relative][hir::QPath::TypeRelative] (and type-level) path.
@@ -2032,9 +2147,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
20322147 GenericsArgsErrExtend :: None
20332148 } ,
20342149 ) ;
2035- tcx. types . self_param
2150+ self . check_param_uses_if_mcg ( tcx. types . self_param , span , false )
20362151 }
2037- Res :: SelfTyAlias { alias_to : def_id, forbid_generic, .. } => {
2152+ Res :: SelfTyAlias { alias_to : def_id, forbid_generic : _ , .. } => {
20382153 // `Self` in impl (we know the concrete type).
20392154 assert_eq ! ( opt_self_ty, None ) ;
20402155 // Try to evaluate any array length constants.
@@ -2043,42 +2158,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
20432158 path. segments . iter ( ) ,
20442159 GenericsArgsErrExtend :: SelfTyAlias { def_id, span } ,
20452160 ) ;
2046- // HACK(min_const_generics): Forbid generic `Self` types
2047- // here as we can't easily do that during nameres.
2048- //
2049- // We do this before normalization as we otherwise allow
2050- // ```rust
2051- // trait AlwaysApplicable { type Assoc; }
2052- // impl<T: ?Sized> AlwaysApplicable for T { type Assoc = usize; }
2053- //
2054- // trait BindsParam<T> {
2055- // type ArrayTy;
2056- // }
2057- // impl<T> BindsParam<T> for <T as AlwaysApplicable>::Assoc {
2058- // type ArrayTy = [u8; Self::MAX];
2059- // }
2060- // ```
2061- // Note that the normalization happens in the param env of
2062- // the anon const, which is empty. This is why the
2063- // `AlwaysApplicable` impl needs a `T: ?Sized` bound for
2064- // this to compile if we were to normalize here.
2065- if forbid_generic && ty. has_param ( ) {
2066- let mut err = self . dcx ( ) . struct_span_err (
2067- path. span ,
2068- "generic `Self` types are currently not permitted in anonymous constants" ,
2069- ) ;
2070- if let Some ( hir:: Node :: Item ( & hir:: Item {
2071- kind : hir:: ItemKind :: Impl ( impl_) ,
2072- ..
2073- } ) ) = tcx. hir_get_if_local ( def_id)
2074- {
2075- err. span_note ( impl_. self_ty . span , "not a concrete type" ) ;
2076- }
2077- let reported = err. emit ( ) ;
2078- Ty :: new_error ( tcx, reported)
2079- } else {
2080- ty
2081- }
2161+ self . check_param_uses_if_mcg ( ty, span, true )
20822162 }
20832163 Res :: Def ( DefKind :: AssocTy , def_id) => {
20842164 let trait_segment = if let [ modules @ .., trait_, _item] = path. segments {
@@ -2138,7 +2218,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
21382218 /// and late-bound ones to [`ty::Bound`].
21392219 pub ( crate ) fn lower_ty_param ( & self , hir_id : HirId ) -> Ty < ' tcx > {
21402220 let tcx = self . tcx ( ) ;
2141- match tcx. named_bound_var ( hir_id) {
2221+
2222+ let ty = match tcx. named_bound_var ( hir_id) {
21422223 Some ( rbv:: ResolvedArg :: LateBound ( debruijn, index, def_id) ) => {
21432224 let br = ty:: BoundTy {
21442225 var : ty:: BoundVar :: from_u32 ( index) ,
@@ -2154,7 +2235,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
21542235 }
21552236 Some ( rbv:: ResolvedArg :: Error ( guar) ) => Ty :: new_error ( tcx, guar) ,
21562237 arg => bug ! ( "unexpected bound var resolution for {hir_id:?}: {arg:?}" ) ,
2157- }
2238+ } ;
2239+ self . check_param_uses_if_mcg ( ty, tcx. hir_span ( hir_id) , false )
21582240 }
21592241
21602242 /// Lower a const parameter from the HIR to our internal notion of a constant.
@@ -2164,7 +2246,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
21642246 pub ( crate ) fn lower_const_param ( & self , param_def_id : DefId , path_hir_id : HirId ) -> Const < ' tcx > {
21652247 let tcx = self . tcx ( ) ;
21662248
2167- match tcx. named_bound_var ( path_hir_id) {
2249+ let ct = match tcx. named_bound_var ( path_hir_id) {
21682250 Some ( rbv:: ResolvedArg :: EarlyBound ( _) ) => {
21692251 // Find the name and index of the const parameter by indexing the generics of
21702252 // the parent item and construct a `ParamConst`.
@@ -2181,7 +2263,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
21812263 ) ,
21822264 Some ( rbv:: ResolvedArg :: Error ( guar) ) => ty:: Const :: new_error ( tcx, guar) ,
21832265 arg => bug ! ( "unexpected bound var resolution for {:?}: {arg:?}" , path_hir_id) ,
2184- }
2266+ } ;
2267+ self . check_param_uses_if_mcg ( ct, tcx. hir_span ( path_hir_id) , false )
21852268 }
21862269
21872270 /// Lower a [`hir::ConstArg`] to a (type-level) [`ty::Const`](Const).
@@ -2386,7 +2469,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
23862469 ) -> Const < ' tcx > {
23872470 let tcx = self . tcx ( ) ;
23882471 let span = path. span ;
2389- match path. res {
2472+ let ct = match path. res {
23902473 Res :: Def ( DefKind :: ConstParam , def_id) => {
23912474 assert_eq ! ( opt_self_ty, None ) ;
23922475 let _ = self . prohibit_generic_args (
@@ -2475,7 +2558,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
24752558 span,
24762559 format ! ( "invalid Res {res:?} for const path" ) ,
24772560 ) ,
2478- }
2561+ } ;
2562+ self . check_param_uses_if_mcg ( ct, span, false )
24792563 }
24802564
24812565 /// Literals are eagerly converted to a constant, everything else becomes `Unevaluated`.
@@ -2520,20 +2604,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
25202604 _ => expr,
25212605 } ;
25222606
2523- // FIXME(mgca): remove this delayed bug once we start checking this
2524- // when lowering `Ty/ConstKind::Param`s more generally.
2525- if let hir:: ExprKind :: Path ( hir:: QPath :: Resolved (
2526- _,
2527- & hir:: Path { res : Res :: Def ( DefKind :: ConstParam , _) , .. } ,
2528- ) ) = expr. kind
2529- {
2530- let e = tcx. dcx ( ) . span_delayed_bug (
2531- expr. span ,
2532- "try_lower_anon_const_lit: received const param which shouldn't be possible" ,
2533- ) ;
2534- return Some ( ty:: Const :: new_error ( tcx, e) ) ;
2535- } ;
2536-
25372607 let lit_input = match expr. kind {
25382608 hir:: ExprKind :: Lit ( lit) => Some ( LitToConstInput { lit : lit. node , ty, neg : false } ) ,
25392609 hir:: ExprKind :: Unary ( hir:: UnOp :: Neg , expr) => match expr. kind {
@@ -2787,6 +2857,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
27872857 let args = ty:: GenericArgs :: for_item ( tcx, def_id, |param, _| {
27882858 if let Some ( i) = ( param. index as usize ) . checked_sub ( offset) {
27892859 let ( lifetime, _) = lifetimes[ i] ;
2860+ // FIXME(mgca): should we be calling self.check_params_use_if_mcg here too?
27902861 self . lower_resolved_lifetime ( lifetime) . into ( )
27912862 } else {
27922863 tcx. mk_param_from_def ( param)
0 commit comments