16
16
17
17
use rustc_ast:: Recovered ;
18
18
use rustc_data_structures:: captures:: Captures ;
19
- use rustc_data_structures:: fx:: { FxHashSet , FxIndexMap } ;
19
+ use rustc_data_structures:: fx:: { FxHashMap , FxHashSet , FxIndexMap } ;
20
20
use rustc_data_structures:: unord:: UnordMap ;
21
21
use rustc_errors:: {
22
- struct_span_code_err, Applicability , Diag , DiagCtxtHandle , ErrorGuaranteed , StashKey , E0228 ,
22
+ struct_span_code_err, Applicability , Diag , DiagCtxtHandle , ErrorGuaranteed , StashKey , E0207 ,
23
+ E0228 ,
23
24
} ;
24
25
use rustc_hir:: def:: DefKind ;
25
26
use rustc_hir:: def_id:: { DefId , LocalDefId } ;
@@ -31,7 +32,9 @@ use rustc_infer::traits::ObligationCause;
31
32
use rustc_middle:: hir:: nested_filter;
32
33
use rustc_middle:: query:: Providers ;
33
34
use rustc_middle:: ty:: util:: { Discr , IntTypeExt } ;
34
- use rustc_middle:: ty:: { self , AdtKind , Const , IsSuggestable , Ty , TyCtxt , Upcast } ;
35
+ use rustc_middle:: ty:: {
36
+ self , AdtKind , Const , IsSuggestable , Ty , TyCtxt , TypeVisitableExt as _, Upcast ,
37
+ } ;
35
38
use rustc_middle:: { bug, span_bug} ;
36
39
use rustc_span:: symbol:: { kw, sym, Ident , Symbol } ;
37
40
use rustc_span:: { Span , DUMMY_SP } ;
@@ -40,11 +43,13 @@ use rustc_trait_selection::error_reporting::traits::suggestions::NextTypeParamNa
40
43
use rustc_trait_selection:: infer:: InferCtxtExt ;
41
44
use rustc_trait_selection:: traits:: ObligationCtxt ;
42
45
use std:: cell:: Cell ;
46
+ use std:: cell:: RefCell ;
43
47
use std:: iter;
44
48
use std:: ops:: Bound ;
45
49
46
50
use crate :: check:: intrinsic:: intrinsic_operation_unsafety;
47
- use crate :: errors;
51
+ use crate :: constrained_generic_params:: { self as cgp, Parameter } ;
52
+ use crate :: errors:: { self , UnconstrainedGenericParameter } ;
48
53
use crate :: hir_ty_lowering:: { HirTyLowerer , RegionInferReason } ;
49
54
50
55
pub ( crate ) mod dump;
@@ -121,6 +126,7 @@ pub struct ItemCtxt<'tcx> {
121
126
tcx : TyCtxt < ' tcx > ,
122
127
item_def_id : LocalDefId ,
123
128
tainted_by_errors : Cell < Option < ErrorGuaranteed > > ,
129
+ pub forbidden_params : RefCell < FxHashMap < Parameter , ty:: GenericParamDef > > ,
124
130
}
125
131
126
132
///////////////////////////////////////////////////////////////////////////
@@ -351,7 +357,12 @@ fn bad_placeholder<'cx, 'tcx>(
351
357
352
358
impl < ' tcx > ItemCtxt < ' tcx > {
353
359
pub fn new ( tcx : TyCtxt < ' tcx > , item_def_id : LocalDefId ) -> ItemCtxt < ' tcx > {
354
- ItemCtxt { tcx, item_def_id, tainted_by_errors : Cell :: new ( None ) }
360
+ ItemCtxt {
361
+ tcx,
362
+ item_def_id,
363
+ tainted_by_errors : Cell :: new ( None ) ,
364
+ forbidden_params : Default :: default ( ) ,
365
+ }
355
366
}
356
367
357
368
pub fn lower_ty ( & self , hir_ty : & hir:: Ty < ' tcx > ) -> Ty < ' tcx > {
@@ -372,6 +383,58 @@ impl<'tcx> ItemCtxt<'tcx> {
372
383
None => Ok ( ( ) ) ,
373
384
}
374
385
}
386
+
387
+ fn forbid_unconstrained_lifetime_params_from_parent_impl ( & self ) -> Result < ( ) , ErrorGuaranteed > {
388
+ let tcx = self . tcx ;
389
+ let impl_def_id = tcx. hir ( ) . get_parent_item ( self . hir_id ( ) ) ;
390
+ let impl_self_ty = tcx. type_of ( impl_def_id) . instantiate_identity ( ) ;
391
+ impl_self_ty. error_reported ( ) ?;
392
+ let impl_generics = tcx. generics_of ( impl_def_id) ;
393
+ let impl_predicates = tcx. predicates_of ( impl_def_id) ;
394
+ let impl_trait_ref =
395
+ tcx. impl_trait_ref ( impl_def_id) . map ( ty:: EarlyBinder :: instantiate_identity) ;
396
+
397
+ impl_trait_ref. error_reported ( ) ?;
398
+
399
+ let mut input_parameters = cgp:: parameters_for_impl ( tcx, impl_self_ty, impl_trait_ref) ;
400
+
401
+ cgp:: identify_constrained_generic_params (
402
+ tcx,
403
+ impl_predicates,
404
+ impl_trait_ref,
405
+ & mut input_parameters,
406
+ ) ;
407
+
408
+ for param in & impl_generics. own_params {
409
+ let p = match param. kind {
410
+ // This is a horrible concession to reality. It'd be
411
+ // better to just ban unconstrained lifetimes outright, but in
412
+ // practice people do non-hygienic macros like:
413
+ //
414
+ // ```
415
+ // macro_rules! __impl_slice_eq1 {
416
+ // ($Lhs: ty, $Rhs: ty, $Bound: ident) => {
417
+ // impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq<B> {
418
+ // ....
419
+ // }
420
+ // }
421
+ // }
422
+ // ```
423
+ //
424
+ // In a concession to backwards compatibility, we continue to
425
+ // permit those, so long as the lifetimes aren't used in
426
+ // associated types. This is sound, because lifetimes
427
+ // used elsewhere are not projected back out.
428
+ ty:: GenericParamDefKind :: Type { .. } => continue ,
429
+ ty:: GenericParamDefKind :: Lifetime => param. to_early_bound_region_data ( ) . into ( ) ,
430
+ ty:: GenericParamDefKind :: Const { .. } => continue ,
431
+ } ;
432
+ if !input_parameters. contains ( & p) {
433
+ self . forbidden_params . borrow_mut ( ) . insert ( p, param. clone ( ) ) ;
434
+ }
435
+ }
436
+ Ok ( ( ) )
437
+ }
375
438
}
376
439
377
440
impl < ' tcx > HirTyLowerer < ' tcx > for ItemCtxt < ' tcx > {
@@ -513,8 +576,25 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
513
576
ty. ty_adt_def ( )
514
577
}
515
578
516
- fn record_ty ( & self , _hir_id : hir:: HirId , _ty : Ty < ' tcx > , _span : Span ) {
517
- // There's no place to record types from signatures?
579
+ fn record_ty ( & self , _hir_id : hir:: HirId , ty : Ty < ' tcx > , span : Span ) {
580
+ // There's no place to record types from signatures
581
+
582
+ if !self . forbidden_params . borrow ( ) . is_empty ( ) {
583
+ for param in cgp:: parameters_for ( self . tcx , ty, true ) {
584
+ if let Some ( param) = self . forbidden_params . borrow_mut ( ) . remove ( & param) {
585
+ let mut diag = self . dcx ( ) . create_err ( UnconstrainedGenericParameter {
586
+ span : self . tcx . def_span ( param. def_id ) ,
587
+ param_name : param. name ,
588
+ param_def_kind : self . tcx . def_descr ( param. def_id ) ,
589
+ const_param_note : None ,
590
+ const_param_note2 : None ,
591
+ lifetime_help : Some ( span) ,
592
+ } ) ;
593
+ diag. code ( E0207 ) ;
594
+ diag. emit ( ) ;
595
+ }
596
+ }
597
+ }
518
598
}
519
599
520
600
fn infcx ( & self ) -> Option < & InferCtxt < ' tcx > > {
0 commit comments