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 & late-bound generic params in the type of associated 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,24 @@ 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+
570+ vars : Default :: default ( ) ,
571+ depth : ty:: INNERMOST ,
572+ } ;
573+ let mut guar = ty. visit_with ( & mut collector) . break_value ( ) ;
564574
565- let mut guar = None ;
566575 let ty_note = ty
567576 . make_suggestable ( tcx, false )
568577 . map ( |ty| crate :: errors:: TyOfAssocConstBindingNote { assoc_const, ty } ) ;
@@ -593,35 +602,100 @@ fn check_assoc_const_binding_type<'tcx>(
593602 ty_note,
594603 } ) ) ;
595604 }
605+ for ( var_def_id, var_name) in collector. vars {
606+ guar. get_or_insert ( tcx. dcx ( ) . emit_err (
607+ crate :: errors:: EscapingBoundVarInTyOfAssocConstBinding {
608+ span : assoc_const. span ,
609+ assoc_const,
610+ var_name,
611+ var_def_kind : tcx. def_descr ( var_def_id) ,
612+ var_defined_here_label : tcx. def_ident_span ( var_def_id) . unwrap ( ) ,
613+ ty_note,
614+ } ,
615+ ) ) ;
616+ }
596617
597- let guar = guar. unwrap_or_else ( || bug ! ( "failed to find gen params in ty" ) ) ;
618+ let guar = guar. unwrap_or_else ( || bug ! ( "failed to find gen params or bound vars in ty" ) ) ;
598619 Ty :: new_error ( tcx, guar)
599620}
600621
601- struct GenericParamCollector {
622+ struct GenericParamAndBoundVarCollector < ' tcx > {
623+ tcx : TyCtxt < ' tcx > ,
602624 params : FxIndexSet < u32 > ,
625+ vars : FxIndexSet < ( DefId , Symbol ) > ,
626+ depth : ty:: DebruijnIndex ,
603627}
604628
605- impl < ' tcx > TypeVisitor < TyCtxt < ' tcx > > for GenericParamCollector {
629+ impl < ' tcx > TypeVisitor < TyCtxt < ' tcx > > for GenericParamAndBoundVarCollector < ' tcx > {
630+ type Result = ControlFlow < ErrorGuaranteed > ;
631+
632+ fn visit_binder < T : TypeVisitable < TyCtxt < ' tcx > > > (
633+ & mut self ,
634+ binder : & ty:: Binder < ' tcx , T > ,
635+ ) -> Self :: Result {
636+ self . depth . shift_in ( 1 ) ;
637+ let result = binder. super_visit_with ( self ) ;
638+ self . depth . shift_out ( 1 ) ;
639+ result
640+ }
641+
606642 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 )
643+ match ty. kind ( ) {
644+ ty:: Param ( param) => {
645+ self . params . insert ( param. index ) ;
646+ }
647+ ty:: Bound ( db, bt) if * db >= self . depth => {
648+ self . vars . insert ( match bt. kind {
649+ ty:: BoundTyKind :: Param ( def_id, name) => ( def_id, name) ,
650+ ty:: BoundTyKind :: Anon => {
651+ let reported = self
652+ . tcx
653+ . dcx ( )
654+ . delayed_bug ( format ! ( "unexpected anon bound ty: {:?}" , bt. var) ) ;
655+ return ControlFlow :: Break ( reported) ;
656+ }
657+ } ) ;
658+ }
659+ _ if ty. has_param ( ) || ty. has_bound_vars ( ) => return ty. super_visit_with ( self ) ,
660+ _ => { }
611661 }
662+ ControlFlow :: Continue ( ( ) )
612663 }
613664
614665 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 ) ;
666+ match re. kind ( ) {
667+ ty:: ReEarlyParam ( param) => {
668+ self . params . insert ( param. index ) ;
669+ }
670+ ty:: ReBound ( db, br) if db >= self . depth => {
671+ self . vars . insert ( match br. kind {
672+ ty:: BrNamed ( def_id, name) => ( def_id, name) ,
673+ ty:: BrAnon | ty:: BrEnv => {
674+ let guar = self
675+ . tcx
676+ . dcx ( )
677+ . delayed_bug ( format ! ( "unexpected bound region kind: {:?}" , br. kind) ) ;
678+ return ControlFlow :: Break ( guar) ;
679+ }
680+ } ) ;
681+ }
682+ _ => { }
617683 }
684+ ControlFlow :: Continue ( ( ) )
618685 }
619686
620687 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 )
688+ match ct. kind ( ) {
689+ ty:: ConstKind :: Param ( param) => {
690+ self . params . insert ( param. index ) ;
691+ }
692+ ty:: ConstKind :: Bound ( db, ty:: BoundVar { .. } ) if db >= self . depth => {
693+ let guar = self . tcx . dcx ( ) . delayed_bug ( "unexpected escaping late-bound const var" ) ;
694+ return ControlFlow :: Break ( guar) ;
695+ }
696+ _ if ct. has_param ( ) || ct. has_bound_vars ( ) => return ct. super_visit_with ( self ) ,
697+ _ => { }
625698 }
699+ ControlFlow :: Continue ( ( ) )
626700 }
627701}
0 commit comments