@@ -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 ( ) , 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+
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.
@@ -130,7 +184,7 @@ struct TaitConstraintLocator<'tcx> {
130184
131185impl TaitConstraintLocator < ' _ > {
132186 #[ 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 ) {
134188 // Don't try to check items that cannot possibly constrain the type.
135189 if !self . tcx . has_typeck_results ( item_def_id) {
136190 debug ! ( "no constraint: no typeck results" ) ;
@@ -182,7 +236,12 @@ impl TaitConstraintLocator<'_> {
182236 continue ;
183237 }
184238 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 ) {
186245 self . tcx . dcx ( ) . emit_err ( TaitForwardCompat {
187246 span : hidden_type. span ,
188247 item_span : self
@@ -240,29 +299,29 @@ impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
240299 }
241300 fn visit_expr ( & mut self , ex : & ' tcx Expr < ' tcx > ) {
242301 if let hir:: ExprKind :: Closure ( closure) = ex. kind {
243- self . check ( closure. def_id ) ;
302+ self . check ( closure. def_id , false ) ;
244303 }
245304 intravisit:: walk_expr ( self , ex) ;
246305 }
247306 fn visit_item ( & mut self , it : & ' tcx Item < ' tcx > ) {
248307 trace ! ( ?it. owner_id) ;
249308 // The opaque type itself or its children are not within its reveal scope.
250309 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 ) ;
252311 intravisit:: walk_item ( self , it) ;
253312 }
254313 }
255314 fn visit_impl_item ( & mut self , it : & ' tcx ImplItem < ' tcx > ) {
256315 trace ! ( ?it. owner_id) ;
257316 // The opaque type itself or its children are not within its reveal scope.
258317 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 ) ;
260319 intravisit:: walk_impl_item ( self , it) ;
261320 }
262321 }
263322 fn visit_trait_item ( & mut self , it : & ' tcx TraitItem < ' tcx > ) {
264323 trace ! ( ?it. owner_id) ;
265- self . check ( it. owner_id . def_id ) ;
324+ self . check ( it. owner_id . def_id , false ) ;
266325 intravisit:: walk_trait_item ( self , it) ;
267326 }
268327 fn visit_foreign_item ( & mut self , it : & ' tcx hir:: ForeignItem < ' tcx > ) {
0 commit comments