@@ -44,6 +44,59 @@ fn orphan_check_impl(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGua
4444 } ;
4545 let sp = tcx. sess . source_map ( ) . guess_head_span ( item. span ) ;
4646 let tr = impl_. of_trait . as_ref ( ) . unwrap ( ) ;
47+
48+ // Ensure no opaque types are present in this impl header. See issues #76202 and #86411 for examples,
49+ // and #84660 where it would otherwise allow unsoundness.
50+ if trait_ref. has_opaque_types ( ) {
51+ trace ! ( "{:#?}" , item) ;
52+ // First we find the opaque type in question.
53+ for ty in trait_ref. substs {
54+ for ty in ty. walk ( ) {
55+ let ty:: subst:: GenericArgKind :: Type ( ty) = ty. unpack ( ) else { continue } ;
56+ let ty:: Opaque ( def_id, _) = * ty. kind ( ) else { continue } ;
57+ trace ! ( ?def_id) ;
58+
59+ // Then we search for mentions of the opaque type's type alias in the HIR
60+ struct SpanFinder < ' tcx > {
61+ sp : Span ,
62+ def_id : DefId ,
63+ tcx : TyCtxt < ' tcx > ,
64+ }
65+ impl < ' v , ' tcx > hir:: intravisit:: Visitor < ' v > for SpanFinder < ' tcx > {
66+ #[ instrument( level = "trace" , skip( self , _id) ) ]
67+ fn visit_path ( & mut self , path : & ' v hir:: Path < ' v > , _id : hir:: HirId ) {
68+ // You can't mention an opaque type directly, so we look for type aliases
69+ if let hir:: def:: Res :: Def ( hir:: def:: DefKind :: TyAlias , def_id) = path. res {
70+ // And check if that type alias's type contains the opaque type we're looking for
71+ for arg in self . tcx . type_of ( def_id) . walk ( ) {
72+ if let GenericArgKind :: Type ( ty) = arg. unpack ( ) {
73+ if let ty:: Opaque ( def_id, _) = * ty. kind ( ) {
74+ if def_id == self . def_id {
75+ // Finally we update the span to the mention of the type alias
76+ self . sp = path. span ;
77+ return ;
78+ }
79+ }
80+ }
81+ }
82+ }
83+ hir:: intravisit:: walk_path ( self , path)
84+ }
85+ }
86+
87+ let mut visitor = SpanFinder { sp, def_id, tcx } ;
88+ hir:: intravisit:: walk_item ( & mut visitor, item) ;
89+ let reported = tcx
90+ . sess
91+ . struct_span_err ( visitor. sp , "cannot implement trait on type alias impl trait" )
92+ . span_note ( tcx. def_span ( def_id) , "type alias impl trait defined here" )
93+ . emit ( ) ;
94+ return Err ( reported) ;
95+ }
96+ }
97+ span_bug ! ( sp, "opaque type not found, but `has_opaque_types` is set" )
98+ }
99+
47100 match traits:: orphan_check ( tcx, item. def_id . to_def_id ( ) ) {
48101 Ok ( ( ) ) => { }
49102 Err ( err) => emit_orphan_check_error (
@@ -143,58 +196,6 @@ fn orphan_check_impl(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGua
143196 }
144197 }
145198
146- // Ensure no opaque types are present in this impl header. See issues #76202 and #86411 for examples,
147- // and #84660 where it would otherwise allow unsoundness.
148- if trait_ref. has_opaque_types ( ) {
149- trace ! ( "{:#?}" , item) ;
150- // First we find the opaque type in question.
151- for ty in trait_ref. substs {
152- for ty in ty. walk ( ) {
153- let ty:: subst:: GenericArgKind :: Type ( ty) = ty. unpack ( ) else { continue } ;
154- let ty:: Opaque ( def_id, _) = * ty. kind ( ) else { continue } ;
155- trace ! ( ?def_id) ;
156-
157- // Then we search for mentions of the opaque type's type alias in the HIR
158- struct SpanFinder < ' tcx > {
159- sp : Span ,
160- def_id : DefId ,
161- tcx : TyCtxt < ' tcx > ,
162- }
163- impl < ' v , ' tcx > hir:: intravisit:: Visitor < ' v > for SpanFinder < ' tcx > {
164- #[ instrument( level = "trace" , skip( self , _id) ) ]
165- fn visit_path ( & mut self , path : & ' v hir:: Path < ' v > , _id : hir:: HirId ) {
166- // You can't mention an opaque type directly, so we look for type aliases
167- if let hir:: def:: Res :: Def ( hir:: def:: DefKind :: TyAlias , def_id) = path. res {
168- // And check if that type alias's type contains the opaque type we're looking for
169- for arg in self . tcx . type_of ( def_id) . walk ( ) {
170- if let GenericArgKind :: Type ( ty) = arg. unpack ( ) {
171- if let ty:: Opaque ( def_id, _) = * ty. kind ( ) {
172- if def_id == self . def_id {
173- // Finally we update the span to the mention of the type alias
174- self . sp = path. span ;
175- return ;
176- }
177- }
178- }
179- }
180- }
181- hir:: intravisit:: walk_path ( self , path)
182- }
183- }
184-
185- let mut visitor = SpanFinder { sp, def_id, tcx } ;
186- hir:: intravisit:: walk_item ( & mut visitor, item) ;
187- let reported = tcx
188- . sess
189- . struct_span_err ( visitor. sp , "cannot implement trait on type alias impl trait" )
190- . span_note ( tcx. def_span ( def_id) , "type alias impl trait defined here" )
191- . emit ( ) ;
192- return Err ( reported) ;
193- }
194- }
195- span_bug ! ( sp, "opaque type not found, but `has_opaque_types` is set" )
196- }
197-
198199 Ok ( ( ) )
199200}
200201
0 commit comments