@@ -23,6 +23,60 @@ pub fn test_opaque_hidden_types(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed>
23
23
res
24
24
}
25
25
26
+ /// Checks "defining uses" of opaque `impl Trait` in associated types.
27
+ /// These can only be defined by associated items of the same trait.
28
+ #[ instrument( skip( tcx) , level = "debug" ) ]
29
+ pub ( super ) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type (
30
+ tcx : TyCtxt < ' _ > ,
31
+ def_id : LocalDefId ,
32
+ ) -> Ty < ' _ > {
33
+ let mut parent_def_id = def_id;
34
+ while tcx. def_kind ( parent_def_id) == def:: DefKind :: OpaqueTy {
35
+ // Account for `type Alias = impl Trait<Foo = impl Trait>;` (#116031)
36
+ parent_def_id = tcx. local_parent ( parent_def_id) ;
37
+ }
38
+ let impl_def_id = tcx. local_parent ( parent_def_id) ;
39
+ match tcx. def_kind ( impl_def_id) {
40
+ DefKind :: Impl { .. } => { }
41
+ other => bug ! ( "invalid impl trait in assoc type parent: {other:?}" ) ,
42
+ }
43
+
44
+ let mut locator = TaitConstraintLocator { def_id, tcx, found : None , typeck_types : vec ! [ ] } ;
45
+
46
+ for & assoc_id in tcx. associated_item_def_ids ( impl_def_id) {
47
+ let assoc = tcx. associated_item ( assoc_id) ;
48
+ match assoc. kind {
49
+ ty:: AssocKind :: Const | ty:: AssocKind :: Fn => {
50
+ locator. check ( assoc_id. expect_local ( ) , true )
51
+ }
52
+ // Associated types don't have bodies, so they can't constrain hidden types
53
+ ty:: AssocKind :: Type => { }
54
+ }
55
+ }
56
+
57
+ if let Some ( hidden) = locator. found {
58
+ // Only check against typeck if we didn't already error
59
+ if !hidden. ty . references_error ( ) {
60
+ for concrete_type in locator. typeck_types {
61
+ if concrete_type. ty != tcx. erase_regions ( hidden. ty )
62
+ && !( concrete_type, hidden) . references_error ( )
63
+ {
64
+ hidden. report_mismatch ( & concrete_type, def_id, tcx) . emit ( ) ;
65
+ }
66
+ }
67
+ }
68
+
69
+ hidden. ty
70
+ } else {
71
+ let reported = tcx. dcx ( ) . emit_err ( UnconstrainedOpaqueType {
72
+ span : tcx. def_span ( def_id) ,
73
+ name : tcx. item_name ( parent_def_id. to_def_id ( ) ) ,
74
+ what : "impl" ,
75
+ } ) ;
76
+ Ty :: new_error ( tcx, reported)
77
+ }
78
+ }
79
+
26
80
/// Checks "defining uses" of opaque `impl Trait` types to ensure that they meet the restrictions
27
81
/// laid for "higher-order pattern unification".
28
82
/// This ensures that inference is tractable.
@@ -130,7 +184,7 @@ struct TaitConstraintLocator<'tcx> {
130
184
131
185
impl TaitConstraintLocator < ' _ > {
132
186
#[ instrument( skip( self ) , level = "debug" ) ]
133
- fn check ( & mut self , item_def_id : LocalDefId ) {
187
+ fn check ( & mut self , item_def_id : LocalDefId , impl_trait_in_assoc_type : bool ) {
134
188
// Don't try to check items that cannot possibly constrain the type.
135
189
if !self . tcx . has_typeck_results ( item_def_id) {
136
190
debug ! ( "no constraint: no typeck results" ) ;
@@ -182,7 +236,12 @@ impl TaitConstraintLocator<'_> {
182
236
continue ;
183
237
}
184
238
constrained = true ;
185
- if !self . tcx . opaque_types_defined_by ( item_def_id) . contains ( & self . def_id ) {
239
+ let opaque_types_defined_by = if impl_trait_in_assoc_type {
240
+ self . tcx . impl_trait_in_assoc_types_defined_by ( item_def_id)
241
+ } else {
242
+ self . tcx . opaque_types_defined_by ( item_def_id)
243
+ } ;
244
+ if !opaque_types_defined_by. contains ( & self . def_id ) {
186
245
self . tcx . dcx ( ) . emit_err ( TaitForwardCompat {
187
246
span : hidden_type. span ,
188
247
item_span : self
@@ -240,29 +299,29 @@ impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
240
299
}
241
300
fn visit_expr ( & mut self , ex : & ' tcx Expr < ' tcx > ) {
242
301
if let hir:: ExprKind :: Closure ( closure) = ex. kind {
243
- self . check ( closure. def_id ) ;
302
+ self . check ( closure. def_id , false ) ;
244
303
}
245
304
intravisit:: walk_expr ( self , ex) ;
246
305
}
247
306
fn visit_item ( & mut self , it : & ' tcx Item < ' tcx > ) {
248
307
trace ! ( ?it. owner_id) ;
249
308
// The opaque type itself or its children are not within its reveal scope.
250
309
if it. owner_id . def_id != self . def_id {
251
- self . check ( it. owner_id . def_id ) ;
310
+ self . check ( it. owner_id . def_id , false ) ;
252
311
intravisit:: walk_item ( self , it) ;
253
312
}
254
313
}
255
314
fn visit_impl_item ( & mut self , it : & ' tcx ImplItem < ' tcx > ) {
256
315
trace ! ( ?it. owner_id) ;
257
316
// The opaque type itself or its children are not within its reveal scope.
258
317
if it. owner_id . def_id != self . def_id {
259
- self . check ( it. owner_id . def_id ) ;
318
+ self . check ( it. owner_id . def_id , false ) ;
260
319
intravisit:: walk_impl_item ( self , it) ;
261
320
}
262
321
}
263
322
fn visit_trait_item ( & mut self , it : & ' tcx TraitItem < ' tcx > ) {
264
323
trace ! ( ?it. owner_id) ;
265
- self . check ( it. owner_id . def_id ) ;
324
+ self . check ( it. owner_id . def_id , false ) ;
266
325
intravisit:: walk_trait_item ( self , it) ;
267
326
}
268
327
fn visit_foreign_item ( & mut self , it : & ' tcx hir:: ForeignItem < ' tcx > ) {
0 commit comments