1
+ use std:: ops:: ControlFlow ;
2
+
1
3
use rustc_data_structures:: fx:: { FxIndexMap , FxIndexSet } ;
2
4
use rustc_errors:: { codes:: * , struct_span_code_err} ;
3
5
use rustc_hir as hir;
4
6
use rustc_hir:: def:: { DefKind , Res } ;
5
7
use rustc_hir:: def_id:: { DefId , LocalDefId } ;
6
8
use rustc_middle:: ty:: { self as ty, IsSuggestable , Ty , TyCtxt } ;
7
9
use rustc_span:: symbol:: Ident ;
8
- use rustc_span:: { ErrorGuaranteed , Span } ;
10
+ use rustc_span:: { ErrorGuaranteed , Span , Symbol } ;
9
11
use rustc_trait_selection:: traits;
10
12
use rustc_type_ir:: visit:: { TypeSuperVisitable , TypeVisitable , TypeVisitableExt , TypeVisitor } ;
11
13
use smallvec:: SmallVec ;
@@ -533,7 +535,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
533
535
}
534
536
}
535
537
536
- /// Detect and reject early-bound generic params in the type of associated const bindings.
538
+ /// Detect and reject early-bound & escaping late-bound generic params in the type of assoc const bindings.
537
539
///
538
540
/// FIXME(const_generics): This is a temporary and semi-artifical restriction until the
539
541
/// arrival of *generic const generics*[^1].
@@ -552,17 +554,23 @@ fn check_assoc_const_binding_type<'tcx>(
552
554
) -> Ty < ' tcx > {
553
555
// We can't perform the checks for early-bound params during name resolution unlike E0770
554
556
// because this information depends on *type* resolution.
557
+ // We can't perform these checks in `resolve_bound_vars` either for the same reason.
558
+ // Consider the trait ref `for<'a> Trait<'a, C = { &0 }>`. We need to know the fully
559
+ // resolved type of `Trait::C` in order to know if it references `'a` or not.
555
560
556
- // FIXME(fmease): Reject escaping late-bound vars.
557
561
let ty = ty. skip_binder ( ) ;
558
- if !ty. has_param ( ) {
562
+ if !ty. has_param ( ) && !ty . has_escaping_bound_vars ( ) {
559
563
return ty;
560
564
}
561
565
562
- let mut collector = GenericParamCollector { params : Default :: default ( ) } ;
563
- ty. visit_with ( & mut collector) ;
566
+ let mut collector = GenericParamAndBoundVarCollector {
567
+ tcx,
568
+ params : Default :: default ( ) ,
569
+ vars : Default :: default ( ) ,
570
+ depth : ty:: INNERMOST ,
571
+ } ;
572
+ let mut guar = ty. visit_with ( & mut collector) . break_value ( ) ;
564
573
565
- let mut guar = None ;
566
574
let ty_note = ty
567
575
. make_suggestable ( tcx, false )
568
576
. map ( |ty| crate :: errors:: TyOfAssocConstBindingNote { assoc_const, ty } ) ;
@@ -593,35 +601,100 @@ fn check_assoc_const_binding_type<'tcx>(
593
601
ty_note,
594
602
} ) ) ;
595
603
}
604
+ for ( var_def_id, var_name) in collector. vars {
605
+ guar. get_or_insert ( tcx. dcx ( ) . emit_err (
606
+ crate :: errors:: EscapingBoundVarInTyOfAssocConstBinding {
607
+ span : assoc_const. span ,
608
+ assoc_const,
609
+ var_name,
610
+ var_def_kind : tcx. def_descr ( var_def_id) ,
611
+ var_defined_here_label : tcx. def_ident_span ( var_def_id) . unwrap ( ) ,
612
+ ty_note,
613
+ } ,
614
+ ) ) ;
615
+ }
596
616
597
- let guar = guar. unwrap_or_else ( || bug ! ( "failed to find gen params in ty" ) ) ;
617
+ let guar = guar. unwrap_or_else ( || bug ! ( "failed to find gen params or bound vars in ty" ) ) ;
598
618
Ty :: new_error ( tcx, guar)
599
619
}
600
620
601
- struct GenericParamCollector {
621
+ struct GenericParamAndBoundVarCollector < ' tcx > {
622
+ tcx : TyCtxt < ' tcx > ,
602
623
params : FxIndexSet < u32 > ,
624
+ vars : FxIndexSet < ( DefId , Symbol ) > ,
625
+ depth : ty:: DebruijnIndex ,
603
626
}
604
627
605
- impl < ' tcx > TypeVisitor < TyCtxt < ' tcx > > for GenericParamCollector {
628
+ impl < ' tcx > TypeVisitor < TyCtxt < ' tcx > > for GenericParamAndBoundVarCollector < ' tcx > {
629
+ type Result = ControlFlow < ErrorGuaranteed > ;
630
+
631
+ fn visit_binder < T : TypeVisitable < TyCtxt < ' tcx > > > (
632
+ & mut self ,
633
+ binder : & ty:: Binder < ' tcx , T > ,
634
+ ) -> Self :: Result {
635
+ self . depth . shift_in ( 1 ) ;
636
+ let result = binder. super_visit_with ( self ) ;
637
+ self . depth . shift_out ( 1 ) ;
638
+ result
639
+ }
640
+
606
641
fn visit_ty ( & mut self , ty : Ty < ' tcx > ) -> Self :: Result {
607
- if let ty:: Param ( param) = ty. kind ( ) {
608
- self . params . insert ( param. index ) ;
609
- } else if ty. has_param ( ) {
610
- ty. super_visit_with ( self )
642
+ match ty. kind ( ) {
643
+ ty:: Param ( param) => {
644
+ self . params . insert ( param. index ) ;
645
+ }
646
+ ty:: Bound ( db, bt) if * db >= self . depth => {
647
+ self . vars . insert ( match bt. kind {
648
+ ty:: BoundTyKind :: Param ( def_id, name) => ( def_id, name) ,
649
+ ty:: BoundTyKind :: Anon => {
650
+ let reported = self
651
+ . tcx
652
+ . dcx ( )
653
+ . delayed_bug ( format ! ( "unexpected anon bound ty: {:?}" , bt. var) ) ;
654
+ return ControlFlow :: Break ( reported) ;
655
+ }
656
+ } ) ;
657
+ }
658
+ _ if ty. has_param ( ) || ty. has_bound_vars ( ) => return ty. super_visit_with ( self ) ,
659
+ _ => { }
611
660
}
661
+ ControlFlow :: Continue ( ( ) )
612
662
}
613
663
614
664
fn visit_region ( & mut self , re : ty:: Region < ' tcx > ) -> Self :: Result {
615
- if let ty:: ReEarlyParam ( param) = re. kind ( ) {
616
- self . params . insert ( param. index ) ;
665
+ match re. kind ( ) {
666
+ ty:: ReEarlyParam ( param) => {
667
+ self . params . insert ( param. index ) ;
668
+ }
669
+ ty:: ReBound ( db, br) if db >= self . depth => {
670
+ self . vars . insert ( match br. kind {
671
+ ty:: BrNamed ( def_id, name) => ( def_id, name) ,
672
+ ty:: BrAnon | ty:: BrEnv => {
673
+ let guar = self
674
+ . tcx
675
+ . dcx ( )
676
+ . delayed_bug ( format ! ( "unexpected bound region kind: {:?}" , br. kind) ) ;
677
+ return ControlFlow :: Break ( guar) ;
678
+ }
679
+ } ) ;
680
+ }
681
+ _ => { }
617
682
}
683
+ ControlFlow :: Continue ( ( ) )
618
684
}
619
685
620
686
fn visit_const ( & mut self , ct : ty:: Const < ' tcx > ) -> Self :: Result {
621
- if let ty:: ConstKind :: Param ( param) = ct. kind ( ) {
622
- self . params . insert ( param. index ) ;
623
- } else if ct. has_param ( ) {
624
- ct. super_visit_with ( self )
687
+ match ct. kind ( ) {
688
+ ty:: ConstKind :: Param ( param) => {
689
+ self . params . insert ( param. index ) ;
690
+ }
691
+ ty:: ConstKind :: Bound ( db, ty:: BoundVar { .. } ) if db >= self . depth => {
692
+ let guar = self . tcx . dcx ( ) . delayed_bug ( "unexpected escaping late-bound const var" ) ;
693
+ return ControlFlow :: Break ( guar) ;
694
+ }
695
+ _ if ct. has_param ( ) || ct. has_bound_vars ( ) => return ct. super_visit_with ( self ) ,
696
+ _ => { }
625
697
}
698
+ ControlFlow :: Continue ( ( ) )
626
699
}
627
700
}
0 commit comments