1
1
use rustc_data_structures:: fx:: FxHashSet ;
2
+ use rustc_hir:: intravisit:: Visitor ;
2
3
use rustc_hir:: { def:: DefKind , def_id:: LocalDefId } ;
4
+ use rustc_hir:: { intravisit, CRATE_HIR_ID } ;
3
5
use rustc_middle:: query:: Providers ;
4
6
use rustc_middle:: ty:: util:: { CheckRegions , NotUniqueParam } ;
5
7
use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
@@ -51,7 +53,7 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
51
53
52
54
fn parent ( & self ) -> Option < LocalDefId > {
53
55
match self . tcx . def_kind ( self . item ) {
54
- DefKind :: Fn => None ,
56
+ DefKind :: AnonConst | DefKind :: InlineConst | DefKind :: Fn | DefKind :: TyAlias => None ,
55
57
DefKind :: AssocFn | DefKind :: AssocTy | DefKind :: AssocConst => {
56
58
Some ( self . tcx . local_parent ( self . item ) )
57
59
}
@@ -61,6 +63,73 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
61
63
) ,
62
64
}
63
65
}
66
+
67
+ /// Returns `true` if `opaque_hir_id` is a sibling or a child of a sibling of `self.item`.
68
+ ///
69
+ /// Example:
70
+ /// ```ignore UNSOLVED (is this a bug?)
71
+ /// # #![feature(type_alias_impl_trait)]
72
+ /// pub mod foo {
73
+ /// pub mod bar {
74
+ /// pub trait Bar { /* ... */ }
75
+ /// pub type Baz = impl Bar;
76
+ ///
77
+ /// # impl Bar for () {}
78
+ /// fn f1() -> Baz { /* ... */ }
79
+ /// }
80
+ /// fn f2() -> bar::Baz { /* ... */ }
81
+ /// }
82
+ /// ```
83
+ ///
84
+ /// and `opaque_def_id` is the `DefId` of the definition of the opaque type `Baz`.
85
+ /// For the above example, this function returns `true` for `f1` and `false` for `f2`.
86
+ #[ instrument( level = "trace" , skip( self ) , ret) ]
87
+ fn check_tait_defining_scope ( & self , opaque_def_id : LocalDefId ) -> bool {
88
+ let mut hir_id = self . tcx . hir ( ) . local_def_id_to_hir_id ( self . item ) ;
89
+ let opaque_hir_id = self . tcx . hir ( ) . local_def_id_to_hir_id ( opaque_def_id) ;
90
+
91
+ // Named opaque types can be defined by any siblings or children of siblings.
92
+ let scope = self . tcx . hir ( ) . get_defining_scope ( opaque_hir_id) ;
93
+ // We walk up the node tree until we hit the root or the scope of the opaque type.
94
+ while hir_id != scope && hir_id != CRATE_HIR_ID {
95
+ hir_id = self . tcx . hir ( ) . get_parent_item ( hir_id) . into ( ) ;
96
+ }
97
+ // Syntactically, we are allowed to define the concrete type if:
98
+ hir_id == scope
99
+ }
100
+
101
+ fn collect_body_and_predicate_taits ( & mut self ) {
102
+ // Look at all where bounds.
103
+ self . tcx . predicates_of ( self . item ) . instantiate_identity ( self . tcx ) . visit_with ( self ) ;
104
+ // An item is allowed to constrain opaques declared within its own body (but not nested within
105
+ // nested functions).
106
+ self . collect_taits_declared_in_body ( ) ;
107
+ }
108
+
109
+ #[ instrument( level = "trace" , skip( self ) ) ]
110
+ fn collect_taits_declared_in_body ( & mut self ) {
111
+ let body = self . tcx . hir ( ) . body ( self . tcx . hir ( ) . body_owned_by ( self . item ) ) . value ;
112
+ struct TaitInBodyFinder < ' a , ' tcx > {
113
+ collector : & ' a mut OpaqueTypeCollector < ' tcx > ,
114
+ }
115
+ impl < ' v > intravisit:: Visitor < ' v > for TaitInBodyFinder < ' _ , ' _ > {
116
+ #[ instrument( level = "trace" , skip( self ) ) ]
117
+ fn visit_nested_item ( & mut self , id : rustc_hir:: ItemId ) {
118
+ let id = id. owner_id . def_id ;
119
+ if let DefKind :: TyAlias = self . collector . tcx . def_kind ( id) {
120
+ let items = self . collector . tcx . opaque_types_defined_by ( id) ;
121
+ self . collector . opaques . extend ( items) ;
122
+ }
123
+ }
124
+ #[ instrument( level = "trace" , skip( self ) ) ]
125
+ // Recurse into these, as they are type checked with their parent
126
+ fn visit_nested_body ( & mut self , id : rustc_hir:: BodyId ) {
127
+ let body = self . collector . tcx . hir ( ) . body ( id) ;
128
+ self . visit_body ( body) ;
129
+ }
130
+ }
131
+ TaitInBodyFinder { collector : self } . visit_expr ( body) ;
132
+ }
64
133
}
65
134
66
135
impl < ' tcx > TypeVisitor < TyCtxt < ' tcx > > for OpaqueTypeCollector < ' tcx > {
@@ -73,6 +142,21 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
73
142
return ControlFlow :: Continue ( ( ) ) ;
74
143
}
75
144
145
+ // TAITs outside their defining scopes are ignored.
146
+ let origin = self . tcx . opaque_type_origin ( alias_ty. def_id . expect_local ( ) ) ;
147
+ trace ! ( ?origin) ;
148
+ match origin {
149
+ rustc_hir:: OpaqueTyOrigin :: FnReturn ( _)
150
+ | rustc_hir:: OpaqueTyOrigin :: AsyncFn ( _) => { }
151
+ rustc_hir:: OpaqueTyOrigin :: TyAlias { in_assoc_ty } => {
152
+ if !in_assoc_ty {
153
+ if !self . check_tait_defining_scope ( alias_ty. def_id . expect_local ( ) ) {
154
+ return ControlFlow :: Continue ( ( ) ) ;
155
+ }
156
+ }
157
+ }
158
+ }
159
+
76
160
self . opaques . push ( alias_ty. def_id . expect_local ( ) ) ;
77
161
78
162
match self . tcx . uses_unique_generic_params ( alias_ty. substs , CheckRegions :: Bound ) {
@@ -188,65 +272,63 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
188
272
fn opaque_types_defined_by < ' tcx > ( tcx : TyCtxt < ' tcx > , item : LocalDefId ) -> & ' tcx [ LocalDefId ] {
189
273
let kind = tcx. def_kind ( item) ;
190
274
trace ! ( ?kind) ;
191
- // FIXME(type_alias_impl_trait): This is definitely still wrong except for RPIT and impl trait in assoc types.
275
+ let mut collector = OpaqueTypeCollector :: new ( tcx , item ) ;
192
276
match kind {
277
+ // Walk over the signature of the function-like to find the opaques.
278
+ DefKind :: AssocFn | DefKind :: Fn => {
279
+ let ty_sig = tcx. fn_sig ( item) . subst_identity ( ) ;
280
+ let hir_sig = tcx. hir ( ) . get_by_def_id ( item) . fn_sig ( ) . unwrap ( ) ;
281
+ // Walk over the inputs and outputs manually in order to get good spans for them.
282
+ collector. visit_spanned ( hir_sig. decl . output . span ( ) , ty_sig. output ( ) ) ;
283
+ for ( hir, ty) in hir_sig. decl . inputs . iter ( ) . zip ( ty_sig. inputs ( ) . iter ( ) ) {
284
+ collector. visit_spanned ( hir. span , ty. map_bound ( |x| * x) ) ;
285
+ }
286
+ collector. collect_body_and_predicate_taits ( ) ;
287
+ }
288
+ // Walk over the type of the item to find opaques.
289
+ DefKind :: Static ( _) | DefKind :: Const | DefKind :: AssocConst | DefKind :: AnonConst => {
290
+ let span = match tcx. hir ( ) . get_by_def_id ( item) . ty ( ) {
291
+ Some ( ty) => ty. span ,
292
+ _ => tcx. def_span ( item) ,
293
+ } ;
294
+ collector. visit_spanned ( span, tcx. type_of ( item) . subst_identity ( ) ) ;
295
+ collector. collect_body_and_predicate_taits ( ) ;
296
+ }
193
297
// We're also doing this for `AssocTy` for the wf checks in `check_opaque_meets_bounds`
194
- DefKind :: Fn | DefKind :: AssocFn | DefKind :: AssocTy | DefKind :: AssocConst => {
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
- }
206
- }
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 ( ) ) ;
214
- }
215
- _ => unreachable ! ( ) ,
298
+ DefKind :: TyAlias | DefKind :: AssocTy => {
299
+ tcx. type_of ( item) . subst_identity ( ) . visit_with ( & mut collector) ;
300
+ }
301
+ DefKind :: OpaqueTy => {
302
+ for ( pred, span) in tcx. explicit_item_bounds ( item) . subst_identity_iter_copied ( ) {
303
+ collector. visit_spanned ( span, pred) ;
216
304
}
217
- tcx. arena . alloc_from_iter ( collector. opaques )
218
305
}
219
306
DefKind :: Mod
220
307
| DefKind :: Struct
221
308
| DefKind :: Union
222
309
| DefKind :: Enum
223
310
| DefKind :: Variant
224
311
| DefKind :: Trait
225
- | DefKind :: TyAlias
226
312
| DefKind :: ForeignTy
227
313
| DefKind :: TraitAlias
228
314
| DefKind :: TyParam
229
- | DefKind :: Const
230
315
| DefKind :: ConstParam
231
- | DefKind :: Static ( _)
232
316
| DefKind :: Ctor ( _, _)
233
317
| DefKind :: Macro ( _)
234
318
| DefKind :: ExternCrate
235
319
| DefKind :: Use
236
320
| DefKind :: ForeignMod
237
- | DefKind :: AnonConst
238
- | DefKind :: InlineConst
239
- | DefKind :: OpaqueTy
240
321
| DefKind :: ImplTraitPlaceholder
241
322
| DefKind :: Field
242
323
| DefKind :: LifetimeParam
243
324
| DefKind :: GlobalAsm
244
- | DefKind :: Impl { .. }
245
- | DefKind :: Closure
246
- | DefKind :: Generator => {
247
- span_bug ! ( tcx. def_span ( item) , "{kind:?} is type checked as part of its parent" )
325
+ | DefKind :: Impl { .. } => { }
326
+ // Closures and generators are type checked with their parent, so there is no difference here.
327
+ DefKind :: Closure | DefKind :: Generator | DefKind :: InlineConst => {
328
+ return tcx . opaque_types_defined_by ( tcx. local_parent ( item) ) ;
248
329
}
249
330
}
331
+ tcx. arena . alloc_from_iter ( collector. opaques )
250
332
}
251
333
252
334
pub ( super ) fn provide ( providers : & mut Providers ) {
0 commit comments