@@ -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 ( ) , ImplTraitSource :: AssocTy )
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.
@@ -128,9 +182,15 @@ struct TaitConstraintLocator<'tcx> {
128
182
typeck_types : Vec < ty:: OpaqueHiddenType < ' tcx > > ,
129
183
}
130
184
185
+ #[ derive( Debug ) ]
186
+ enum ImplTraitSource {
187
+ AssocTy ,
188
+ TyAlias ,
189
+ }
190
+
131
191
impl TaitConstraintLocator < ' _ > {
132
192
#[ instrument( skip( self ) , level = "debug" ) ]
133
- fn check ( & mut self , item_def_id : LocalDefId ) {
193
+ fn check ( & mut self , item_def_id : LocalDefId , source : ImplTraitSource ) {
134
194
// Don't try to check items that cannot possibly constrain the type.
135
195
if !self . tcx . has_typeck_results ( item_def_id) {
136
196
debug ! ( "no constraint: no typeck results" ) ;
@@ -182,7 +242,13 @@ impl TaitConstraintLocator<'_> {
182
242
continue ;
183
243
}
184
244
constrained = true ;
185
- if !self . tcx . opaque_types_defined_by ( item_def_id) . contains ( & self . def_id ) {
245
+ let opaque_types_defined_by = match source {
246
+ ImplTraitSource :: AssocTy => {
247
+ self . tcx . impl_trait_in_assoc_types_defined_by ( item_def_id)
248
+ }
249
+ ImplTraitSource :: TyAlias => self . tcx . opaque_types_defined_by ( item_def_id) ,
250
+ } ;
251
+ if !opaque_types_defined_by. contains ( & self . def_id ) {
186
252
self . tcx . dcx ( ) . emit_err ( TaitForwardCompat {
187
253
span : hidden_type. span ,
188
254
item_span : self
@@ -240,29 +306,29 @@ impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
240
306
}
241
307
fn visit_expr ( & mut self , ex : & ' tcx Expr < ' tcx > ) {
242
308
if let hir:: ExprKind :: Closure ( closure) = ex. kind {
243
- self . check ( closure. def_id ) ;
309
+ self . check ( closure. def_id , ImplTraitSource :: TyAlias ) ;
244
310
}
245
311
intravisit:: walk_expr ( self , ex) ;
246
312
}
247
313
fn visit_item ( & mut self , it : & ' tcx Item < ' tcx > ) {
248
314
trace ! ( ?it. owner_id) ;
249
315
// The opaque type itself or its children are not within its reveal scope.
250
316
if it. owner_id . def_id != self . def_id {
251
- self . check ( it. owner_id . def_id ) ;
317
+ self . check ( it. owner_id . def_id , ImplTraitSource :: TyAlias ) ;
252
318
intravisit:: walk_item ( self , it) ;
253
319
}
254
320
}
255
321
fn visit_impl_item ( & mut self , it : & ' tcx ImplItem < ' tcx > ) {
256
322
trace ! ( ?it. owner_id) ;
257
323
// The opaque type itself or its children are not within its reveal scope.
258
324
if it. owner_id . def_id != self . def_id {
259
- self . check ( it. owner_id . def_id ) ;
325
+ self . check ( it. owner_id . def_id , ImplTraitSource :: TyAlias ) ;
260
326
intravisit:: walk_impl_item ( self , it) ;
261
327
}
262
328
}
263
329
fn visit_trait_item ( & mut self , it : & ' tcx TraitItem < ' tcx > ) {
264
330
trace ! ( ?it. owner_id) ;
265
- self . check ( it. owner_id . def_id ) ;
331
+ self . check ( it. owner_id . def_id , ImplTraitSource :: TyAlias ) ;
266
332
intravisit:: walk_trait_item ( self , it) ;
267
333
}
268
334
fn visit_foreign_item ( & mut self , it : & ' tcx hir:: ForeignItem < ' tcx > ) {
0 commit comments