11use rustc_data_structures:: fx:: FxHashSet ;
2- use rustc_errors:: ErrorGuaranteed ;
32use rustc_hir:: { def:: DefKind , def_id:: LocalDefId } ;
43use rustc_middle:: query:: Providers ;
54use rustc_middle:: ty:: util:: { CheckRegions , NotUniqueParam } ;
@@ -19,21 +18,26 @@ struct OpaqueTypeCollector<'tcx> {
1918
2019 /// Avoid infinite recursion due to recursive declarations.
2120 seen : FxHashSet < LocalDefId > ,
21+
22+ span : Option < Span > ,
2223}
2324
2425impl < ' tcx > OpaqueTypeCollector < ' tcx > {
25- fn collect (
26- tcx : TyCtxt < ' tcx > ,
27- item : LocalDefId ,
28- val : ty:: Binder < ' tcx , impl TypeVisitable < TyCtxt < ' tcx > > > ,
29- ) -> Vec < LocalDefId > {
30- let mut collector = Self { tcx, opaques : Vec :: new ( ) , item, seen : Default :: default ( ) } ;
31- val. skip_binder ( ) . visit_with ( & mut collector) ;
32- collector. opaques
26+ fn new ( tcx : TyCtxt < ' tcx > , item : LocalDefId ) -> Self {
27+ Self { tcx, opaques : Vec :: new ( ) , item, seen : Default :: default ( ) , span : None }
3328 }
3429
3530 fn span ( & self ) -> Span {
36- self . tcx . def_span ( self . item )
31+ self . span . unwrap_or_else ( || {
32+ self . tcx . def_ident_span ( self . item ) . unwrap_or_else ( || self . tcx . def_span ( self . item ) )
33+ } )
34+ }
35+
36+ fn visit_spanned ( & mut self , span : Span , value : impl TypeVisitable < TyCtxt < ' tcx > > ) {
37+ let old = self . span ;
38+ self . span = Some ( span) ;
39+ value. visit_with ( self ) ;
40+ self . span = old;
3741 }
3842
3943 fn parent_trait_ref ( & self ) -> Option < ty:: TraitRef < ' tcx > > {
@@ -60,53 +64,57 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
6064}
6165
6266impl < ' tcx > TypeVisitor < TyCtxt < ' tcx > > for OpaqueTypeCollector < ' tcx > {
63- type BreakTy = ErrorGuaranteed ;
64-
6567 #[ instrument( skip( self ) , ret, level = "trace" ) ]
66- fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> ControlFlow < ErrorGuaranteed > {
68+ fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> ControlFlow < !> {
69+ t. super_visit_with ( self ) ?;
6770 match t. kind ( ) {
6871 ty:: Alias ( ty:: Opaque , alias_ty) if alias_ty. def_id . is_local ( ) => {
6972 if !self . seen . insert ( alias_ty. def_id . expect_local ( ) ) {
7073 return ControlFlow :: Continue ( ( ) ) ;
7174 }
75+
76+ self . opaques . push ( alias_ty. def_id . expect_local ( ) ) ;
77+
7278 match self . tcx . uses_unique_generic_params ( alias_ty. substs , CheckRegions :: Bound ) {
7379 Ok ( ( ) ) => {
7480 // FIXME: implement higher kinded lifetime bounds on nested opaque types. They are not
7581 // supported at all, so this is sound to do, but once we want to support them, you'll
7682 // start seeing the error below.
7783
78- self . opaques . push ( alias_ty. def_id . expect_local ( ) ) ;
79-
8084 // Collect opaque types nested within the associated type bounds of this opaque type.
81- for ( pred, _span) in self
85+ // We use identity substs here, because we already know that the opaque type uses
86+ // only generic parameters, and thus substituting would not give us more information.
87+ for ( pred, span) in self
8288 . tcx
8389 . explicit_item_bounds ( alias_ty. def_id )
84- . subst_iter_copied ( self . tcx , alias_ty . substs )
90+ . subst_identity_iter_copied ( )
8591 {
8692 trace ! ( ?pred) ;
87- pred . visit_with ( self ) ? ;
93+ self . visit_spanned ( span , pred ) ;
8894 }
89-
90- ControlFlow :: Continue ( ( ) )
9195 }
9296 Err ( NotUniqueParam :: NotParam ( arg) ) => {
93- let err = self . tcx . sess . emit_err ( NotParam {
97+ self . tcx . sess . emit_err ( NotParam {
9498 arg,
9599 span : self . span ( ) ,
96100 opaque_span : self . tcx . def_span ( alias_ty. def_id ) ,
97101 } ) ;
98- ControlFlow :: Break ( err)
99102 }
100103 Err ( NotUniqueParam :: DuplicateParam ( arg) ) => {
101- let err = self . tcx . sess . emit_err ( DuplicateArg {
104+ self . tcx . sess . emit_err ( DuplicateArg {
102105 arg,
103106 span : self . span ( ) ,
104107 opaque_span : self . tcx . def_span ( alias_ty. def_id ) ,
105108 } ) ;
106- ControlFlow :: Break ( err)
107109 }
108110 }
109111 }
112+ ty:: Alias ( ty:: Weak , alias_ty) if alias_ty. def_id . is_local ( ) => {
113+ self . tcx
114+ . type_of ( alias_ty. def_id )
115+ . subst ( self . tcx , alias_ty. substs )
116+ . visit_with ( self ) ?;
117+ }
110118 ty:: Alias ( ty:: Projection , alias_ty) => {
111119 // This avoids having to do normalization of `Self::AssocTy` by only
112120 // supporting the case of a method defining opaque types from assoc types
@@ -136,26 +144,44 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
136144 ty:: InternalSubsts :: identity_for_item ( self . tcx , parent) ,
137145 ) ;
138146
139- if !check_substs_compatible ( self . tcx , assoc, impl_substs) {
147+ if check_substs_compatible ( self . tcx , assoc, impl_substs) {
148+ return self
149+ . tcx
150+ . type_of ( assoc. def_id )
151+ . subst ( self . tcx , impl_substs)
152+ . visit_with ( self ) ;
153+ } else {
140154 self . tcx . sess . delay_span_bug (
141155 self . tcx . def_span ( assoc. def_id ) ,
142156 "item had incorrect substs" ,
143157 ) ;
144- return ControlFlow :: Continue ( ( ) ) ;
145158 }
146-
147- return self
148- . tcx
149- . type_of ( assoc. def_id )
150- . subst ( self . tcx , impl_substs)
151- . visit_with ( self ) ;
152159 }
153160 }
154161 }
155- t. super_visit_with ( self )
156162 }
157- _ => t. super_visit_with ( self ) ,
163+ ty:: Adt ( def, _) if def. did ( ) . is_local ( ) => {
164+ if !self . seen . insert ( def. did ( ) . expect_local ( ) ) {
165+ return ControlFlow :: Continue ( ( ) ) ;
166+ }
167+ for variant in def. variants ( ) . iter ( ) {
168+ for field in variant. fields . iter ( ) {
169+ // Don't use the `ty::Adt` substs, we either
170+ // * found the opaque in the substs
171+ // * will find the opaque in the unsubstituted fields
172+ // The only other situation that can occur is that after substituting,
173+ // some projection resolves to an opaque that we would have otherwise
174+ // not found. While we could substitute and walk those, that would mean we
175+ // would have to walk all substitutions of an Adt, which can quickly
176+ // degenerate into looking at an exponential number of types.
177+ let ty = self . tcx . type_of ( field. did ) . subst_identity ( ) ;
178+ self . visit_spanned ( self . tcx . def_span ( field. did ) , ty) ;
179+ }
180+ }
181+ }
182+ _ => trace ! ( kind=?t. kind( ) ) ,
158183 }
184+ ControlFlow :: Continue ( ( ) )
159185 }
160186}
161187
@@ -166,21 +192,29 @@ fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [
166192 match kind {
167193 // We're also doing this for `AssocTy` for the wf checks in `check_opaque_meets_bounds`
168194 DefKind :: Fn | DefKind :: AssocFn | DefKind :: AssocTy | DefKind :: AssocConst => {
169- let defined_opaques = match kind {
170- DefKind :: Fn => {
171- OpaqueTypeCollector :: collect ( tcx, item, tcx. fn_sig ( item) . subst_identity ( ) )
195+ let mut collector = OpaqueTypeCollector :: new ( tcx, item) ;
196+ match kind {
197+ // Walk over the signature of the function-like to find the opaques.
198+ DefKind :: AssocFn | DefKind :: Fn => {
199+ let ty_sig = tcx. fn_sig ( item) . subst_identity ( ) ;
200+ let hir_sig = tcx. hir ( ) . get_by_def_id ( item) . fn_sig ( ) . unwrap ( ) ;
201+ // Walk over the inputs and outputs manually in order to get good spans for them.
202+ collector. visit_spanned ( hir_sig. decl . output . span ( ) , ty_sig. output ( ) ) ;
203+ for ( hir, ty) in hir_sig. decl . inputs . iter ( ) . zip ( ty_sig. inputs ( ) . iter ( ) ) {
204+ collector. visit_spanned ( hir. span , ty. map_bound ( |x| * x) ) ;
205+ }
172206 }
173- DefKind :: AssocFn => {
174- OpaqueTypeCollector :: collect ( tcx, item, tcx. fn_sig ( item) . subst_identity ( ) )
207+ // Walk over the type of the item to find opaques.
208+ DefKind :: AssocTy | DefKind :: AssocConst => {
209+ let span = match tcx. hir ( ) . get_by_def_id ( item) . ty ( ) {
210+ Some ( ty) => ty. span ,
211+ _ => tcx. def_span ( item) ,
212+ } ;
213+ collector. visit_spanned ( span, tcx. type_of ( item) . subst_identity ( ) ) ;
175214 }
176- DefKind :: AssocTy | DefKind :: AssocConst => OpaqueTypeCollector :: collect (
177- tcx,
178- item,
179- ty:: Binder :: dummy ( tcx. type_of ( item) . subst_identity ( ) ) ,
180- ) ,
181215 _ => unreachable ! ( ) ,
182- } ;
183- tcx. arena . alloc_from_iter ( defined_opaques )
216+ }
217+ tcx. arena . alloc_from_iter ( collector . opaques )
184218 }
185219 DefKind :: Mod
186220 | DefKind :: Struct
@@ -209,7 +243,9 @@ fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [
209243 | DefKind :: GlobalAsm
210244 | DefKind :: Impl { .. }
211245 | DefKind :: Closure
212- | DefKind :: Generator => & [ ] ,
246+ | DefKind :: Generator => {
247+ span_bug ! ( tcx. def_span( item) , "{kind:?} is type checked as part of its parent" )
248+ }
213249 }
214250}
215251
0 commit comments