14
14
//! At present, however, we do run collection across all items in the
15
15
//! crate as a kind of pass. This should eventually be factored away.
16
16
17
- use std:: cell:: Cell ;
17
+ use std:: cell:: { Cell , RefCell } ;
18
18
use std:: iter;
19
19
use std:: ops:: Bound ;
20
20
21
21
use rustc_abi:: ExternAbi ;
22
22
use rustc_ast:: Recovered ;
23
23
use rustc_data_structures:: captures:: Captures ;
24
- use rustc_data_structures:: fx:: { FxHashSet , FxIndexMap } ;
24
+ use rustc_data_structures:: fx:: { FxHashMap , FxHashSet , FxIndexMap } ;
25
25
use rustc_data_structures:: unord:: UnordMap ;
26
26
use 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,
28
29
} ;
29
30
use rustc_hir:: def:: DefKind ;
30
31
use rustc_hir:: def_id:: { DefId , LocalDefId } ;
@@ -36,7 +37,9 @@ use rustc_middle::hir::nested_filter;
36
37
use rustc_middle:: query:: Providers ;
37
38
use rustc_middle:: ty:: fold:: fold_regions;
38
39
use 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
+ } ;
40
43
use rustc_middle:: { bug, span_bug} ;
41
44
use rustc_span:: symbol:: { Ident , Symbol , kw, sym} ;
42
45
use rustc_span:: { DUMMY_SP , Span } ;
@@ -46,7 +49,8 @@ use rustc_trait_selection::traits::ObligationCtxt;
46
49
use tracing:: { debug, instrument} ;
47
50
48
51
use 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 } ;
50
54
use crate :: hir_ty_lowering:: { FeedConstTy , HirTyLowerer , RegionInferReason } ;
51
55
52
56
pub ( crate ) mod dump;
@@ -127,6 +131,7 @@ pub struct ItemCtxt<'tcx> {
127
131
tcx : TyCtxt < ' tcx > ,
128
132
item_def_id : LocalDefId ,
129
133
tainted_by_errors : Cell < Option < ErrorGuaranteed > > ,
134
+ pub ( crate ) forbidden_params : RefCell < FxHashMap < Parameter , ty:: GenericParamDef > > ,
130
135
}
131
136
132
137
///////////////////////////////////////////////////////////////////////////
@@ -375,7 +380,12 @@ fn bad_placeholder<'cx, 'tcx>(
375
380
376
381
impl < ' tcx > ItemCtxt < ' tcx > {
377
382
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
+ }
379
389
}
380
390
381
391
pub fn lower_ty ( & self , hir_ty : & hir:: Ty < ' tcx > ) -> Ty < ' tcx > {
@@ -396,6 +406,58 @@ impl<'tcx> ItemCtxt<'tcx> {
396
406
None => Ok ( ( ) ) ,
397
407
}
398
408
}
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
+ }
399
461
}
400
462
401
463
impl < ' tcx > HirTyLowerer < ' tcx > for ItemCtxt < ' tcx > {
@@ -538,8 +600,25 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
538
600
ty. ty_adt_def ( )
539
601
}
540
602
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
+ }
543
622
}
544
623
545
624
fn infcx ( & self ) -> Option < & InferCtxt < ' tcx > > {
0 commit comments