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 } ;
@@ -59,7 +60,20 @@ pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: Local
5960 }
6061 }
6162
62- let Some ( hidden) = locator. found else {
63+ if let Some ( hidden) = locator. found {
64+ // Only check against typeck if we didn't already error
65+ if !hidden. ty . references_error ( ) {
66+ for concrete_type in locator. typeck_types {
67+ if concrete_type. ty != tcx. erase_regions ( hidden. ty )
68+ && !( concrete_type, hidden) . references_error ( )
69+ {
70+ hidden. report_mismatch ( & concrete_type, def_id, tcx) . emit ( ) ;
71+ }
72+ }
73+ }
74+
75+ hidden. ty
76+ } else {
6377 let reported = tcx. sess . emit_err ( UnconstrainedOpaqueType {
6478 span : tcx. def_span ( def_id) ,
6579 name : tcx. item_name ( tcx. local_parent ( def_id) . to_def_id ( ) ) ,
@@ -70,21 +84,8 @@ pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: Local
7084 _ => "item" ,
7185 } ,
7286 } ) ;
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- }
87+ tcx. ty_error ( reported)
8588 }
86-
87- hidden. ty
8889}
8990
9091struct TaitConstraintLocator < ' tcx > {
@@ -130,13 +131,28 @@ impl TaitConstraintLocator<'_> {
130131 self . found = Some ( ty:: OpaqueHiddenType { span : DUMMY_SP , ty : self . tcx . ty_error ( guar) } ) ;
131132 return ;
132133 }
133- let Some ( & typeck_hidden_ty) = tables. concrete_opaque_types . get ( & self . def_id ) else {
134+
135+ let mut constrained = false ;
136+ for ( & opaque_type_key, & hidden_type) in & tables. concrete_opaque_types {
137+ if opaque_type_key. def_id != self . def_id {
138+ continue ;
139+ }
140+ constrained = true ;
141+ let concrete_type =
142+ self . tcx . erase_regions ( hidden_type. remap_generic_params_to_declaration_params (
143+ opaque_type_key,
144+ self . tcx ,
145+ true ,
146+ ) ) ;
147+ if self . typeck_types . iter ( ) . all ( |prev| prev. ty != concrete_type. ty ) {
148+ self . typeck_types . push ( concrete_type) ;
149+ }
150+ }
151+
152+ if !constrained {
134153 debug ! ( "no constraints in typeck results" ) ;
135154 return ;
136155 } ;
137- if self . typeck_types . iter ( ) . all ( |prev| prev. ty != typeck_hidden_ty. ty ) {
138- self . typeck_types . push ( typeck_hidden_ty) ;
139- }
140156
141157 // Use borrowck to get the type with unerased regions.
142158 let concrete_opaque_types = & self . tcx . mir_borrowck ( item_def_id) . concrete_opaque_types ;
@@ -190,45 +206,74 @@ impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
190206 }
191207}
192208
193- pub ( super ) fn find_opaque_ty_constraints_for_rpit (
194- tcx : TyCtxt < ' _ > ,
209+ pub ( super ) fn find_opaque_ty_constraints_for_rpit < ' tcx > (
210+ tcx : TyCtxt < ' tcx > ,
195211 def_id : LocalDefId ,
196212 owner_def_id : LocalDefId ,
197213) -> Ty < ' _ > {
198- let concrete = tcx. mir_borrowck ( owner_def_id) . concrete_opaque_types . get ( & def_id) . copied ( ) ;
214+ let tables = tcx. typeck ( owner_def_id) ;
215+
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+ }
199242
200- if let Some ( concrete) = concrete {
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 {
201245 let scope = tcx. hir ( ) . local_def_id_to_hir_id ( owner_def_id) ;
202246 debug ! ( ?scope) ;
203- let mut locator = RpitConstraintChecker { def_id, tcx, found : concrete } ;
247+ let mut locator = RpitConstraintChecker { def_id, tcx, found : mir_opaque_ty } ;
204248
205249 match tcx. hir ( ) . get ( scope) {
206250 Node :: Item ( it) => intravisit:: walk_item ( & mut locator, it) ,
207251 Node :: ImplItem ( it) => intravisit:: walk_impl_item ( & mut locator, it) ,
208252 Node :: TraitItem ( it) => intravisit:: walk_trait_item ( & mut locator, it) ,
209253 other => bug ! ( "{:?} is not a valid scope for an opaque type item" , other) ,
210254 }
211- }
212255
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 {
216- // Some error in the
217- // owner fn prevented us from populating
256+ mir_opaque_ty. ty
257+ } else {
258+ if let Some ( guar) = tables. tainted_by_errors {
259+ // Some error in the owner fn prevented us from populating
218260 // the `concrete_opaque_types` table.
219261 tcx. ty_error ( guar)
220262 } else {
221- table. concrete_opaque_types . get ( & def_id) . map ( |ty| ty. ty ) . unwrap_or_else ( || {
263+ // Fall back to the RPIT we inferred during HIR typeck
264+ if let Some ( hir_opaque_ty) = hir_opaque_ty {
265+ hir_opaque_ty. ty
266+ } else {
222267 // We failed to resolve the opaque type or it
223268 // resolves to itself. We interpret this as the
224269 // no values of the hidden type ever being constructed,
225270 // so we can just make the hidden type be `!`.
226271 // For backwards compatibility reasons, we fall back to
227272 // `()` until we the diverging default is changed.
228273 tcx. mk_diverging_default ( )
229- } )
274+ }
230275 }
231- } )
276+ }
232277}
233278
234279struct RpitConstraintChecker < ' tcx > {
0 commit comments