1+ use std:: ops:: ControlFlow ;
2+
13use rustc_data_structures:: fx:: { FxIndexMap , FxIndexSet } ;
24use rustc_errors:: { codes:: * , struct_span_code_err} ;
35use rustc_hir as hir;
46use rustc_hir:: def:: { DefKind , Res } ;
57use rustc_hir:: def_id:: { DefId , LocalDefId } ;
68use rustc_middle:: ty:: { self as ty, IsSuggestable , Ty , TyCtxt } ;
79use rustc_span:: symbol:: Ident ;
8- use rustc_span:: { ErrorGuaranteed , Span } ;
10+ use rustc_span:: { ErrorGuaranteed , Span , Symbol } ;
911use rustc_trait_selection:: traits;
1012use rustc_type_ir:: visit:: { TypeSuperVisitable , TypeVisitable , TypeVisitableExt , TypeVisitor } ;
1113use smallvec:: SmallVec ;
@@ -533,7 +535,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
533535 }
534536}
535537
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.
537539///
538540/// FIXME(const_generics): This is a temporary and semi-artifical restriction until the
539541/// arrival of *generic const generics*[^1].
@@ -552,17 +554,23 @@ fn check_assoc_const_binding_type<'tcx>(
552554) -> Ty < ' tcx > {
553555 // We can't perform the checks for early-bound params during name resolution unlike E0770
554556 // 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.
555560
556- // FIXME(fmease): Reject escaping late-bound vars.
557561 let ty = ty. skip_binder ( ) ;
558- if !ty. has_param ( ) {
562+ if !ty. has_param ( ) && !ty . has_escaping_bound_vars ( ) {
559563 return ty;
560564 }
561565
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 ( ) ;
564573
565- let mut guar = None ;
566574 let ty_note = ty
567575 . make_suggestable ( tcx, false )
568576 . map ( |ty| crate :: errors:: TyOfAssocConstBindingNote { assoc_const, ty } ) ;
@@ -593,35 +601,100 @@ fn check_assoc_const_binding_type<'tcx>(
593601 ty_note,
594602 } ) ) ;
595603 }
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+ }
596616
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" ) ) ;
598618 Ty :: new_error ( tcx, guar)
599619}
600620
601- struct GenericParamCollector {
621+ struct GenericParamAndBoundVarCollector < ' tcx > {
622+ tcx : TyCtxt < ' tcx > ,
602623 params : FxIndexSet < u32 > ,
624+ vars : FxIndexSet < ( DefId , Symbol ) > ,
625+ depth : ty:: DebruijnIndex ,
603626}
604627
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+
606641 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+ _ => { }
611660 }
661+ ControlFlow :: Continue ( ( ) )
612662 }
613663
614664 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+ _ => { }
617682 }
683+ ControlFlow :: Continue ( ( ) )
618684 }
619685
620686 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+ _ => { }
625697 }
698+ ControlFlow :: Continue ( ( ) )
626699 }
627700}
0 commit comments