@@ -23,6 +23,60 @@ pub fn test_opaque_hidden_types(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed>
2323 res
2424}
2525
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+
2680/// Checks "defining uses" of opaque `impl Trait` types to ensure that they meet the restrictions
2781/// laid for "higher-order pattern unification".
2882/// This ensures that inference is tractable.
@@ -128,9 +182,15 @@ struct TaitConstraintLocator<'tcx> {
128182 typeck_types : Vec < ty:: OpaqueHiddenType < ' tcx > > ,
129183}
130184
185+ #[ derive( Debug ) ]
186+ enum ImplTraitSource {
187+ AssocTy ,
188+ TyAlias ,
189+ }
190+
131191impl TaitConstraintLocator < ' _ > {
132192 #[ 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 ) {
134194 // Don't try to check items that cannot possibly constrain the type.
135195 if !self . tcx . has_typeck_results ( item_def_id) {
136196 debug ! ( "no constraint: no typeck results" ) ;
@@ -182,7 +242,13 @@ impl TaitConstraintLocator<'_> {
182242 continue ;
183243 }
184244 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 ) {
186252 self . tcx . dcx ( ) . emit_err ( TaitForwardCompat {
187253 span : hidden_type. span ,
188254 item_span : self
@@ -240,29 +306,29 @@ impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
240306 }
241307 fn visit_expr ( & mut self , ex : & ' tcx Expr < ' tcx > ) {
242308 if let hir:: ExprKind :: Closure ( closure) = ex. kind {
243- self . check ( closure. def_id ) ;
309+ self . check ( closure. def_id , ImplTraitSource :: TyAlias ) ;
244310 }
245311 intravisit:: walk_expr ( self , ex) ;
246312 }
247313 fn visit_item ( & mut self , it : & ' tcx Item < ' tcx > ) {
248314 trace ! ( ?it. owner_id) ;
249315 // The opaque type itself or its children are not within its reveal scope.
250316 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 ) ;
252318 intravisit:: walk_item ( self , it) ;
253319 }
254320 }
255321 fn visit_impl_item ( & mut self , it : & ' tcx ImplItem < ' tcx > ) {
256322 trace ! ( ?it. owner_id) ;
257323 // The opaque type itself or its children are not within its reveal scope.
258324 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 ) ;
260326 intravisit:: walk_impl_item ( self , it) ;
261327 }
262328 }
263329 fn visit_trait_item ( & mut self , it : & ' tcx TraitItem < ' tcx > ) {
264330 trace ! ( ?it. owner_id) ;
265- self . check ( it. owner_id . def_id ) ;
331+ self . check ( it. owner_id . def_id , ImplTraitSource :: TyAlias ) ;
266332 intravisit:: walk_trait_item ( self , it) ;
267333 }
268334 fn visit_foreign_item ( & mut self , it : & ' tcx hir:: ForeignItem < ' tcx > ) {
0 commit comments