1414//! At present, however, we do run collection across all items in the
1515//! crate as a kind of pass. This should eventually be factored away.
1616
17- use std:: cell:: Cell ;
17+ use std:: cell:: { Cell , RefCell } ;
1818use std:: iter;
1919use std:: ops:: Bound ;
2020
2121use rustc_abi:: ExternAbi ;
2222use rustc_ast:: Recovered ;
2323use rustc_data_structures:: captures:: Captures ;
24- use rustc_data_structures:: fx:: { FxHashSet , FxIndexMap } ;
24+ use rustc_data_structures:: fx:: { FxHashMap , FxHashSet , FxIndexMap } ;
2525use rustc_data_structures:: unord:: UnordMap ;
2626use rustc_errors:: {
27- Applicability , Diag , DiagCtxtHandle , E0228 , ErrorGuaranteed , StashKey , struct_span_code_err,
27+ Applicability , Diag , DiagCtxtHandle , E0207 , E0228 , ErrorGuaranteed , StashKey ,
28+ struct_span_code_err,
2829} ;
2930use rustc_hir:: def:: DefKind ;
3031use rustc_hir:: def_id:: { DefId , LocalDefId } ;
@@ -36,7 +37,9 @@ use rustc_middle::hir::nested_filter;
3637use rustc_middle:: query:: Providers ;
3738use rustc_middle:: ty:: fold:: fold_regions;
3839use rustc_middle:: ty:: util:: { Discr , IntTypeExt } ;
39- use rustc_middle:: ty:: { self , AdtKind , Const , IsSuggestable , Ty , TyCtxt , TypingMode } ;
40+ use rustc_middle:: ty:: {
41+ self , AdtKind , Const , IsSuggestable , Ty , TyCtxt , TypeVisitableExt as _, TypingMode ,
42+ } ;
4043use rustc_middle:: { bug, span_bug} ;
4144use rustc_span:: symbol:: { Ident , Symbol , kw, sym} ;
4245use rustc_span:: { DUMMY_SP , Span } ;
@@ -46,7 +49,8 @@ use rustc_trait_selection::traits::ObligationCtxt;
4649use tracing:: { debug, instrument} ;
4750
4851use crate :: check:: intrinsic:: intrinsic_operation_unsafety;
49- use crate :: errors;
52+ use crate :: constrained_generic_params:: { self as cgp, Parameter } ;
53+ use crate :: errors:: { self , UnconstrainedGenericParameter } ;
5054use crate :: hir_ty_lowering:: { FeedConstTy , HirTyLowerer , RegionInferReason } ;
5155
5256pub ( crate ) mod dump;
@@ -127,6 +131,7 @@ pub struct ItemCtxt<'tcx> {
127131 tcx : TyCtxt < ' tcx > ,
128132 item_def_id : LocalDefId ,
129133 tainted_by_errors : Cell < Option < ErrorGuaranteed > > ,
134+ pub ( crate ) forbidden_params : RefCell < FxHashMap < Parameter , ty:: GenericParamDef > > ,
130135}
131136
132137///////////////////////////////////////////////////////////////////////////
@@ -375,7 +380,12 @@ fn bad_placeholder<'cx, 'tcx>(
375380
376381impl < ' tcx > ItemCtxt < ' tcx > {
377382 pub fn new ( tcx : TyCtxt < ' tcx > , item_def_id : LocalDefId ) -> ItemCtxt < ' tcx > {
378- ItemCtxt { tcx, item_def_id, tainted_by_errors : Cell :: new ( None ) }
383+ ItemCtxt {
384+ tcx,
385+ item_def_id,
386+ tainted_by_errors : Cell :: new ( None ) ,
387+ forbidden_params : Default :: default ( ) ,
388+ }
379389 }
380390
381391 pub fn lower_ty ( & self , hir_ty : & hir:: Ty < ' tcx > ) -> Ty < ' tcx > {
@@ -396,6 +406,58 @@ impl<'tcx> ItemCtxt<'tcx> {
396406 None => Ok ( ( ) ) ,
397407 }
398408 }
409+
410+ fn forbid_unconstrained_lifetime_params_from_parent_impl ( & self ) -> Result < ( ) , ErrorGuaranteed > {
411+ let tcx = self . tcx ;
412+ let impl_def_id = tcx. hir ( ) . get_parent_item ( self . hir_id ( ) ) ;
413+ let impl_self_ty = tcx. type_of ( impl_def_id) . instantiate_identity ( ) ;
414+ impl_self_ty. error_reported ( ) ?;
415+ let impl_generics = tcx. generics_of ( impl_def_id) ;
416+ let impl_predicates = tcx. predicates_of ( impl_def_id) ;
417+ let impl_trait_ref =
418+ tcx. impl_trait_ref ( impl_def_id) . map ( ty:: EarlyBinder :: instantiate_identity) ;
419+
420+ impl_trait_ref. error_reported ( ) ?;
421+
422+ let mut input_parameters = cgp:: parameters_for_impl ( tcx, impl_self_ty, impl_trait_ref) ;
423+
424+ cgp:: identify_constrained_generic_params (
425+ tcx,
426+ impl_predicates,
427+ impl_trait_ref,
428+ & mut input_parameters,
429+ ) ;
430+
431+ for param in & impl_generics. own_params {
432+ let p = match param. kind {
433+ // This is a horrible concession to reality. It'd be
434+ // better to just ban unconstrained lifetimes outright, but in
435+ // practice people do non-hygienic macros like:
436+ //
437+ // ```
438+ // macro_rules! __impl_slice_eq1 {
439+ // ($Lhs: ty, $Rhs: ty, $Bound: ident) => {
440+ // impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq<B> {
441+ // ....
442+ // }
443+ // }
444+ // }
445+ // ```
446+ //
447+ // In a concession to backwards compatibility, we continue to
448+ // permit those, so long as the lifetimes aren't used in
449+ // associated types. This is sound, because lifetimes
450+ // used elsewhere are not projected back out.
451+ ty:: GenericParamDefKind :: Type { .. } => continue ,
452+ ty:: GenericParamDefKind :: Lifetime => param. to_early_bound_region_data ( ) . into ( ) ,
453+ ty:: GenericParamDefKind :: Const { .. } => continue ,
454+ } ;
455+ if !input_parameters. contains ( & p) {
456+ self . forbidden_params . borrow_mut ( ) . insert ( p, param. clone ( ) ) ;
457+ }
458+ }
459+ Ok ( ( ) )
460+ }
399461}
400462
401463impl < ' tcx > HirTyLowerer < ' tcx > for ItemCtxt < ' tcx > {
@@ -538,8 +600,25 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
538600 ty. ty_adt_def ( )
539601 }
540602
541- fn record_ty ( & self , _hir_id : hir:: HirId , _ty : Ty < ' tcx > , _span : Span ) {
542- // There's no place to record types from signatures?
603+ fn record_ty ( & self , _hir_id : hir:: HirId , ty : Ty < ' tcx > , span : Span ) {
604+ // There's no place to record types from signatures
605+
606+ if !self . forbidden_params . borrow ( ) . is_empty ( ) {
607+ for param in cgp:: parameters_for ( self . tcx , ty, true ) {
608+ if let Some ( param) = self . forbidden_params . borrow_mut ( ) . remove ( & param) {
609+ let mut diag = self . dcx ( ) . create_err ( UnconstrainedGenericParameter {
610+ span : self . tcx . def_span ( param. def_id ) ,
611+ param_name : param. name ,
612+ param_def_kind : self . tcx . def_descr ( param. def_id ) ,
613+ const_param_note : false ,
614+ const_param_note2 : false ,
615+ lifetime_help : Some ( span) ,
616+ } ) ;
617+ diag. code ( E0207 ) ;
618+ diag. emit ( ) ;
619+ }
620+ }
621+ }
543622 }
544623
545624 fn infcx ( & self ) -> Option < & InferCtxt < ' tcx > > {
0 commit comments