@@ -59,7 +59,20 @@ pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: Local
59
59
}
60
60
}
61
61
62
- let Some ( hidden) = locator. found else {
62
+ if let Some ( hidden) = locator. found {
63
+ // Only check against typeck if we didn't already error
64
+ if !hidden. ty . references_error ( ) {
65
+ for concrete_type in locator. typeck_types {
66
+ if concrete_type. ty != tcx. erase_regions ( hidden. ty )
67
+ && !( concrete_type, hidden) . references_error ( )
68
+ {
69
+ hidden. report_mismatch ( & concrete_type, def_id, tcx) . emit ( ) ;
70
+ }
71
+ }
72
+ }
73
+
74
+ hidden. ty
75
+ } else {
63
76
let reported = tcx. sess . emit_err ( UnconstrainedOpaqueType {
64
77
span : tcx. def_span ( def_id) ,
65
78
name : tcx. item_name ( tcx. local_parent ( def_id) . to_def_id ( ) ) ,
@@ -70,21 +83,8 @@ pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: Local
70
83
_ => "item" ,
71
84
} ,
72
85
} ) ;
73
- return tcx. ty_error ( reported) ;
74
- } ;
75
-
76
- // Only check against typeck if we didn't already error
77
- if !hidden. ty . references_error ( ) {
78
- for concrete_type in locator. typeck_types {
79
- if concrete_type. ty != tcx. erase_regions ( hidden. ty )
80
- && !( concrete_type, hidden) . references_error ( )
81
- {
82
- hidden. report_mismatch ( & concrete_type, def_id, tcx) . emit ( ) ;
83
- }
84
- }
86
+ tcx. ty_error ( reported)
85
87
}
86
-
87
- hidden. ty
88
88
}
89
89
90
90
struct TaitConstraintLocator < ' tcx > {
@@ -130,13 +130,28 @@ impl TaitConstraintLocator<'_> {
130
130
self . found = Some ( ty:: OpaqueHiddenType { span : DUMMY_SP , ty : self . tcx . ty_error ( guar) } ) ;
131
131
return ;
132
132
}
133
- let Some ( & typeck_hidden_ty) = tables. concrete_opaque_types . get ( & self . def_id ) else {
133
+
134
+ let mut constrained = false ;
135
+ for ( & opaque_type_key, & hidden_type) in & tables. concrete_opaque_types {
136
+ if opaque_type_key. def_id != self . def_id {
137
+ continue ;
138
+ }
139
+ constrained = true ;
140
+ let concrete_type =
141
+ self . tcx . erase_regions ( hidden_type. remap_generic_params_to_declaration_params (
142
+ opaque_type_key,
143
+ self . tcx ,
144
+ true ,
145
+ ) ) ;
146
+ if self . typeck_types . iter ( ) . all ( |prev| prev. ty != concrete_type. ty ) {
147
+ self . typeck_types . push ( concrete_type) ;
148
+ }
149
+ }
150
+
151
+ if !constrained {
134
152
debug ! ( "no constraints in typeck results" ) ;
135
153
return ;
136
154
} ;
137
- if self . typeck_types . iter ( ) . all ( |prev| prev. ty != typeck_hidden_ty. ty ) {
138
- self . typeck_types . push ( typeck_hidden_ty) ;
139
- }
140
155
141
156
// Use borrowck to get the type with unerased regions.
142
157
let concrete_opaque_types = & self . tcx . mir_borrowck ( item_def_id) . concrete_opaque_types ;
@@ -190,8 +205,8 @@ impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
190
205
}
191
206
}
192
207
193
- pub ( super ) fn find_opaque_ty_constraints_for_rpit (
194
- tcx : TyCtxt < ' _ > ,
208
+ pub ( super ) fn find_opaque_ty_constraints_for_rpit < ' tcx > (
209
+ tcx : TyCtxt < ' tcx > ,
195
210
def_id : LocalDefId ,
196
211
owner_def_id : LocalDefId ,
197
212
) -> Ty < ' _ > {
@@ -208,27 +223,50 @@ pub(super) fn find_opaque_ty_constraints_for_rpit(
208
223
Node :: TraitItem ( it) => intravisit:: walk_trait_item ( & mut locator, it) ,
209
224
other => bug ! ( "{:?} is not a valid scope for an opaque type item" , other) ,
210
225
}
211
- }
212
226
213
- concrete. map ( |concrete| concrete. ty ) . unwrap_or_else ( || {
214
- let table = tcx. typeck ( owner_def_id) ;
215
- if let Some ( guar) = table. tainted_by_errors {
227
+ concrete. ty
228
+ } else {
229
+ let tables = tcx. typeck ( owner_def_id) ;
230
+ if let Some ( guar) = tables. tainted_by_errors {
216
231
// Some error in the
217
232
// owner fn prevented us from populating
218
233
// the `concrete_opaque_types` table.
219
234
tcx. ty_error ( guar)
220
235
} else {
221
- table. concrete_opaque_types . get ( & def_id) . map ( |ty| ty. ty ) . unwrap_or_else ( || {
236
+ // Fall back to the RPIT we inferred during HIR typeck
237
+ let mut opaque_ty: Option < ty:: OpaqueHiddenType < ' tcx > > = None ;
238
+ for ( & opaque_type_key, & hidden_type) in & tables. concrete_opaque_types {
239
+ if opaque_type_key. def_id != def_id {
240
+ continue ;
241
+ }
242
+ let concrete_type =
243
+ tcx. erase_regions ( hidden_type. remap_generic_params_to_declaration_params (
244
+ opaque_type_key,
245
+ tcx,
246
+ true ,
247
+ ) ) ;
248
+ if let Some ( prev) = & mut opaque_ty {
249
+ if concrete_type. ty != prev. ty && !( concrete_type, prev. ty ) . references_error ( ) {
250
+ prev. report_mismatch ( & concrete_type, def_id, tcx) . emit ( ) ;
251
+ }
252
+ } else {
253
+ opaque_ty = Some ( concrete_type) ;
254
+ }
255
+ }
256
+
257
+ if let Some ( opaque_ty) = opaque_ty {
258
+ opaque_ty. ty
259
+ } else {
222
260
// We failed to resolve the opaque type or it
223
261
// resolves to itself. We interpret this as the
224
262
// no values of the hidden type ever being constructed,
225
263
// so we can just make the hidden type be `!`.
226
264
// For backwards compatibility reasons, we fall back to
227
265
// `()` until we the diverging default is changed.
228
266
tcx. mk_diverging_default ( )
229
- } )
267
+ }
230
268
}
231
- } )
269
+ }
232
270
}
233
271
234
272
struct RpitConstraintChecker < ' tcx > {
0 commit comments