2
2
3
3
use rustc_data_structures:: fx:: FxHashSet ;
4
4
use rustc_index:: bit_set:: BitSet ;
5
+ use rustc_infer:: infer:: DefiningAnchor ;
5
6
use rustc_infer:: infer:: TyCtxtInferExt ;
6
7
use rustc_middle:: mir:: interpret:: Scalar ;
7
8
use rustc_middle:: mir:: visit:: NonUseContext :: VarDebugInfo ;
@@ -11,13 +12,14 @@ use rustc_middle::mir::{
11
12
MirPass , MirPhase , Operand , Place , PlaceElem , PlaceRef , ProjectionElem , RuntimePhase , Rvalue ,
12
13
SourceScope , Statement , StatementKind , Terminator , TerminatorKind , UnOp , START_BLOCK ,
13
14
} ;
14
- use rustc_middle:: ty :: fold :: BottomUpFolder ;
15
+ use rustc_middle:: traits :: ObligationCause ;
15
16
use rustc_middle:: ty:: subst:: Subst ;
16
- use rustc_middle:: ty:: { self , InstanceDef , ParamEnv , Ty , TyCtxt , TypeFoldable , TypeVisitable } ;
17
+ use rustc_middle:: ty:: { self , InstanceDef , ParamEnv , Ty , TyCtxt , TypeVisitable } ;
17
18
use rustc_mir_dataflow:: impls:: MaybeStorageLive ;
18
19
use rustc_mir_dataflow:: storage:: always_storage_live_locals;
19
20
use rustc_mir_dataflow:: { Analysis , ResultsCursor } ;
20
21
use rustc_target:: abi:: { Size , VariantIdx } ;
22
+ use rustc_trait_selection:: traits:: ObligationCtxt ;
21
23
22
24
#[ derive( Copy , Clone , Debug ) ]
23
25
enum EdgeKind {
@@ -87,24 +89,36 @@ pub fn equal_up_to_regions<'tcx>(
87
89
return true ;
88
90
}
89
91
90
- // Normalize lifetimes away on both sides, then compare.
91
- let normalize = |ty : Ty < ' tcx > | {
92
- let ty = ty. fold_with ( & mut BottomUpFolder {
93
- tcx,
94
- // FIXME: We erase all late-bound lifetimes, but this is not fully correct.
95
- // If you have a type like `<for<'a> fn(&'a u32) as SomeTrait>::Assoc`,
96
- // this is not necessarily equivalent to `<fn(&'static u32) as SomeTrait>::Assoc`,
97
- // since one may have an `impl SomeTrait for fn(&32)` and
98
- // `impl SomeTrait for fn(&'static u32)` at the same time which
99
- // specify distinct values for Assoc. (See also #56105)
100
- lt_op : |_| tcx. lifetimes . re_erased ,
101
- // Leave consts and types unchanged.
102
- ct_op : |ct| ct,
103
- ty_op : |ty| ty,
104
- } ) ;
105
- tcx. try_normalize_erasing_regions ( param_env, ty) . unwrap_or ( ty)
106
- } ;
107
- tcx. infer_ctxt ( ) . enter ( |infcx| infcx. can_eq ( param_env, normalize ( src) , normalize ( dest) ) . is_ok ( ) )
92
+ may_subtype_ignoring_regions ( tcx, param_env, src, dest)
93
+ || may_subtype_ignoring_regions ( tcx, param_env, dest, src)
94
+ }
95
+
96
+ fn may_subtype_ignoring_regions < ' tcx > (
97
+ tcx : TyCtxt < ' tcx > ,
98
+ param_env : ParamEnv < ' tcx > ,
99
+ src : Ty < ' tcx > ,
100
+ dest : Ty < ' tcx > ,
101
+ ) -> bool {
102
+ let mut builder =
103
+ tcx. infer_ctxt ( ) . ignoring_regions ( ) . with_opaque_type_inference ( DefiningAnchor :: Bubble ) ;
104
+ builder. enter ( |infcx| {
105
+ let ocx = ObligationCtxt :: new ( & infcx) ;
106
+ let cause = ObligationCause :: dummy ( ) ;
107
+ let src = ocx. normalize ( cause. clone ( ) , param_env, src) ;
108
+ let dest = ocx. normalize ( cause. clone ( ) , param_env, dest) ;
109
+ let Ok ( infer_ok) = infcx. at ( & cause, param_env) . eq ( src, dest) else {
110
+ return false ;
111
+ } ;
112
+ let ( ) = ocx. register_infer_ok_obligations ( infer_ok) ;
113
+ let errors = ocx. select_all_or_error ( ) ;
114
+ // With `Reveal::All`, opaque types get normalized away, with `Reveal::UserFacing`
115
+ // we would get unification errors because we're unable to look into opaque types,
116
+ // even if they're constrained in our current function.
117
+ //
118
+ // It seems very unlikely that this hides any bugs.
119
+ let _ = infcx. inner . borrow_mut ( ) . opaque_type_storage . take_opaque_types ( ) ;
120
+ errors. is_empty ( )
121
+ } )
108
122
}
109
123
110
124
struct TypeChecker < ' a , ' tcx > {
@@ -187,16 +201,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
187
201
// all normal lifetimes are erased, higher-ranked types with their
188
202
// late-bound lifetimes are still around and can lead to type
189
203
// differences. So we compare ignoring lifetimes.
190
-
191
- // First, try with reveal_all. This might not work in some cases, as the predicates
192
- // can be cleared in reveal_all mode. We try the reveal first anyways as it is used
193
- // by some other passes like inlining as well.
194
- let param_env = self . param_env . with_reveal_all_normalized ( self . tcx ) ;
195
- if equal_up_to_regions ( self . tcx , param_env, src, dest) {
196
- return true ;
197
- }
198
-
199
- // If this fails, we can try it without the reveal.
200
204
equal_up_to_regions ( self . tcx , self . param_env , src, dest)
201
205
}
202
206
}
@@ -283,7 +287,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
283
287
this. fail (
284
288
location,
285
289
format ! (
286
- "Field projection `{:?}.{:?}` specified type `{:?}`, but actual type is {:?}" ,
290
+ "Field projection `{:?}.{:?}` specified type `{:?}`, but actual type is ` {:?}` " ,
287
291
parent, f, ty, f_ty
288
292
)
289
293
)
0 commit comments