1+ use rustc_errors:: StashKey ;
12use rustc_hir:: def_id:: LocalDefId ;
23use rustc_hir:: intravisit:: { self , Visitor } ;
34use rustc_hir:: { self as hir, Expr , ImplItem , Item , Node , TraitItem } ;
@@ -210,12 +211,40 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>(
210211 def_id : LocalDefId ,
211212 owner_def_id : LocalDefId ,
212213) -> Ty < ' _ > {
213- let concrete = tcx. mir_borrowck ( owner_def_id) . concrete_opaque_types . get ( & def_id ) . copied ( ) ;
214+ let tables = tcx. typeck ( owner_def_id) ;
214215
215- if let Some ( concrete) = concrete {
216+ // Check that all of the opaques we inferred during HIR are compatible.
217+ // FIXME: We explicitly don't check that the types inferred during HIR
218+ // typeck are compatible with the one that we infer during borrowck,
219+ // because that one actually sometimes has consts evaluated eagerly so
220+ // using strict type equality will fail.
221+ let mut hir_opaque_ty: Option < ty:: OpaqueHiddenType < ' tcx > > = None ;
222+ if tables. tainted_by_errors . is_none ( ) {
223+ for ( & opaque_type_key, & hidden_type) in & tables. concrete_opaque_types {
224+ if opaque_type_key. def_id != def_id {
225+ continue ;
226+ }
227+ let concrete_type = tcx. erase_regions (
228+ hidden_type. remap_generic_params_to_declaration_params ( opaque_type_key, tcx, true ) ,
229+ ) ;
230+ if let Some ( prev) = & mut hir_opaque_ty {
231+ if concrete_type. ty != prev. ty && !( concrete_type, prev. ty ) . references_error ( ) {
232+ prev. report_mismatch ( & concrete_type, def_id, tcx) . stash (
233+ tcx. def_span ( opaque_type_key. def_id ) ,
234+ StashKey :: OpaqueHiddenTypeMismatch ,
235+ ) ;
236+ }
237+ } else {
238+ hir_opaque_ty = Some ( concrete_type) ;
239+ }
240+ }
241+ }
242+
243+ let mir_opaque_ty = tcx. mir_borrowck ( owner_def_id) . concrete_opaque_types . get ( & def_id) . copied ( ) ;
244+ if let Some ( mir_opaque_ty) = mir_opaque_ty {
216245 let scope = tcx. hir ( ) . local_def_id_to_hir_id ( owner_def_id) ;
217246 debug ! ( ?scope) ;
218- let mut locator = RpitConstraintChecker { def_id, tcx, found : concrete } ;
247+ let mut locator = RpitConstraintChecker { def_id, tcx, found : mir_opaque_ty } ;
219248
220249 match tcx. hir ( ) . get ( scope) {
221250 Node :: Item ( it) => intravisit:: walk_item ( & mut locator, it) ,
@@ -224,38 +253,16 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>(
224253 other => bug ! ( "{:?} is not a valid scope for an opaque type item" , other) ,
225254 }
226255
227- concrete . ty
256+ mir_opaque_ty . ty
228257 } else {
229- let tables = tcx. typeck ( owner_def_id) ;
230258 if let Some ( guar) = tables. tainted_by_errors {
231- // Some error in the
232- // owner fn prevented us from populating
259+ // Some error in the owner fn prevented us from populating
233260 // the `concrete_opaque_types` table.
234261 tcx. ty_error ( guar)
235262 } else {
236263 // 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
264+ if let Some ( hir_opaque_ty) = hir_opaque_ty {
265+ hir_opaque_ty. ty
259266 } else {
260267 // We failed to resolve the opaque type or it
261268 // resolves to itself. We interpret this as the
0 commit comments