@@ -21,6 +21,60 @@ pub fn test_opaque_hidden_types(tcx: TyCtxt<'_>) {
21
21
}
22
22
}
23
23
24
+ /// Checks "defining uses" of opaque `impl Trait` in associated types.
25
+ /// These can only be defined by associated items of the same trait.
26
+ #[ instrument( skip( tcx) , level = "debug" ) ]
27
+ pub ( super ) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type (
28
+ tcx : TyCtxt < ' _ > ,
29
+ def_id : LocalDefId ,
30
+ ) -> Ty < ' _ > {
31
+ let mut parent_def_id = def_id;
32
+ while tcx. def_kind ( parent_def_id) == def:: DefKind :: OpaqueTy {
33
+ // Account for `type Alias = impl Trait<Foo = impl Trait>;` (#116031)
34
+ parent_def_id = tcx. local_parent ( parent_def_id) ;
35
+ }
36
+ let impl_def_id = tcx. local_parent ( parent_def_id) ;
37
+ match tcx. def_kind ( impl_def_id) {
38
+ DefKind :: Impl { .. } => { }
39
+ other => bug ! ( "invalid impl trait in assoc type parent: {other:?}" ) ,
40
+ }
41
+
42
+ let mut locator = TaitConstraintLocator { def_id, tcx, found : None , typeck_types : vec ! [ ] } ;
43
+
44
+ for & assoc_id in tcx. associated_item_def_ids ( impl_def_id) {
45
+ let assoc = tcx. associated_item ( assoc_id) ;
46
+ match assoc. kind {
47
+ ty:: AssocKind :: Const | ty:: AssocKind :: Fn => {
48
+ locator. check ( assoc_id. expect_local ( ) , true )
49
+ }
50
+ // Associated types don't have bodies, so they can't constrain hidden types
51
+ ty:: AssocKind :: Type => { }
52
+ }
53
+ }
54
+
55
+ if let Some ( hidden) = locator. found {
56
+ // Only check against typeck if we didn't already error
57
+ if !hidden. ty . references_error ( ) {
58
+ for concrete_type in locator. typeck_types {
59
+ if concrete_type. ty != tcx. erase_regions ( hidden. ty )
60
+ && !( concrete_type, hidden) . references_error ( )
61
+ {
62
+ hidden. report_mismatch ( & concrete_type, def_id, tcx) . emit ( ) ;
63
+ }
64
+ }
65
+ }
66
+
67
+ hidden. ty
68
+ } else {
69
+ let reported = tcx. dcx ( ) . emit_err ( UnconstrainedOpaqueType {
70
+ span : tcx. def_span ( def_id) ,
71
+ name : tcx. item_name ( parent_def_id. to_def_id ( ) ) ,
72
+ what : "impl" ,
73
+ } ) ;
74
+ Ty :: new_error ( tcx, reported)
75
+ }
76
+ }
77
+
24
78
/// Checks "defining uses" of opaque `impl Trait` types to ensure that they meet the restrictions
25
79
/// laid for "higher-order pattern unification".
26
80
/// This ensures that inference is tractable.
@@ -128,7 +182,7 @@ struct TaitConstraintLocator<'tcx> {
128
182
129
183
impl TaitConstraintLocator < ' _ > {
130
184
#[ instrument( skip( self ) , level = "debug" ) ]
131
- fn check ( & mut self , item_def_id : LocalDefId ) {
185
+ fn check ( & mut self , item_def_id : LocalDefId , impl_trait_in_assoc_type : bool ) {
132
186
// Don't try to check items that cannot possibly constrain the type.
133
187
if !self . tcx . has_typeck_results ( item_def_id) {
134
188
debug ! ( "no constraint: no typeck results" ) ;
@@ -158,7 +212,12 @@ impl TaitConstraintLocator<'_> {
158
212
continue ;
159
213
}
160
214
constrained = true ;
161
- if !self . tcx . opaque_types_defined_by ( item_def_id) . contains ( & self . def_id ) {
215
+ let opaque_types_defined_by = if impl_trait_in_assoc_type {
216
+ self . tcx . impl_trait_in_assoc_types_defined_by ( item_def_id)
217
+ } else {
218
+ self . tcx . opaque_types_defined_by ( item_def_id)
219
+ } ;
220
+ if !opaque_types_defined_by. contains ( & self . def_id ) {
162
221
self . tcx . dcx ( ) . emit_err ( TaitForwardCompat {
163
222
span : hidden_type. span ,
164
223
item_span : self
@@ -216,29 +275,29 @@ impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
216
275
}
217
276
fn visit_expr ( & mut self , ex : & ' tcx Expr < ' tcx > ) {
218
277
if let hir:: ExprKind :: Closure ( closure) = ex. kind {
219
- self . check ( closure. def_id ) ;
278
+ self . check ( closure. def_id , false ) ;
220
279
}
221
280
intravisit:: walk_expr ( self , ex) ;
222
281
}
223
282
fn visit_item ( & mut self , it : & ' tcx Item < ' tcx > ) {
224
283
trace ! ( ?it. owner_id) ;
225
284
// The opaque type itself or its children are not within its reveal scope.
226
285
if it. owner_id . def_id != self . def_id {
227
- self . check ( it. owner_id . def_id ) ;
286
+ self . check ( it. owner_id . def_id , false ) ;
228
287
intravisit:: walk_item ( self , it) ;
229
288
}
230
289
}
231
290
fn visit_impl_item ( & mut self , it : & ' tcx ImplItem < ' tcx > ) {
232
291
trace ! ( ?it. owner_id) ;
233
292
// The opaque type itself or its children are not within its reveal scope.
234
293
if it. owner_id . def_id != self . def_id {
235
- self . check ( it. owner_id . def_id ) ;
294
+ self . check ( it. owner_id . def_id , false ) ;
236
295
intravisit:: walk_impl_item ( self , it) ;
237
296
}
238
297
}
239
298
fn visit_trait_item ( & mut self , it : & ' tcx TraitItem < ' tcx > ) {
240
299
trace ! ( ?it. owner_id) ;
241
- self . check ( it. owner_id . def_id ) ;
300
+ self . check ( it. owner_id . def_id , false ) ;
242
301
intravisit:: walk_trait_item ( self , it) ;
243
302
}
244
303
fn visit_foreign_item ( & mut self , it : & ' tcx hir:: ForeignItem < ' tcx > ) {
0 commit comments