Skip to content

Commit 012dc3e

Browse files
committed
stop upgrading param envs to Reveal::All
1 parent 406e03f commit 012dc3e

30 files changed

+133
-157
lines changed

compiler/rustc_const_eval/src/transform/validate.rs

Lines changed: 35 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
use rustc_data_structures::fx::FxHashSet;
44
use rustc_index::bit_set::BitSet;
5+
use rustc_infer::infer::DefiningAnchor;
56
use rustc_infer::infer::TyCtxtInferExt;
67
use rustc_middle::mir::interpret::Scalar;
78
use rustc_middle::mir::visit::NonUseContext::VarDebugInfo;
@@ -11,13 +12,14 @@ use rustc_middle::mir::{
1112
MirPass, MirPhase, Operand, Place, PlaceElem, PlaceRef, ProjectionElem, RuntimePhase, Rvalue,
1213
SourceScope, Statement, StatementKind, Terminator, TerminatorKind, UnOp, START_BLOCK,
1314
};
14-
use rustc_middle::ty::fold::BottomUpFolder;
15+
use rustc_middle::traits::ObligationCause;
1516
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};
1718
use rustc_mir_dataflow::impls::MaybeStorageLive;
1819
use rustc_mir_dataflow::storage::always_storage_live_locals;
1920
use rustc_mir_dataflow::{Analysis, ResultsCursor};
2021
use rustc_target::abi::{Size, VariantIdx};
22+
use rustc_trait_selection::traits::ObligationCtxt;
2123

2224
#[derive(Copy, Clone, Debug)]
2325
enum EdgeKind {
@@ -87,24 +89,36 @@ pub fn equal_up_to_regions<'tcx>(
8789
return true;
8890
}
8991

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+
})
108122
}
109123

110124
struct TypeChecker<'a, 'tcx> {
@@ -187,16 +201,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
187201
// all normal lifetimes are erased, higher-ranked types with their
188202
// late-bound lifetimes are still around and can lead to type
189203
// 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.
200204
equal_up_to_regions(self.tcx, self.param_env, src, dest)
201205
}
202206
}
@@ -283,7 +287,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
283287
this.fail(
284288
location,
285289
format!(
286-
"Field projection `{:?}.{:?}` specified type `{:?}`, but actual type is {:?}",
290+
"Field projection `{:?}.{:?}` specified type `{:?}`, but actual type is `{:?}`",
287291
parent, f, ty, f_ty
288292
)
289293
)

compiler/rustc_middle/src/mir/interpret/queries.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ impl<'tcx> TyCtxt<'tcx> {
2020
let substs = InternalSubsts::identity_for_item(self, def_id);
2121
let instance = ty::Instance::new(def_id, substs);
2222
let cid = GlobalId { instance, promoted: None };
23-
let param_env = self.param_env(def_id).with_reveal_all_normalized(self);
23+
let param_env = self.param_env_reveal_all_normalized(def_id);
2424
self.const_eval_global_id(param_env, cid, None)
2525
}
2626
/// Resolves and evaluates a constant.
@@ -184,8 +184,7 @@ impl<'tcx> TyCtxtEnsure<'tcx> {
184184
let substs = InternalSubsts::identity_for_item(self.tcx, def_id);
185185
let instance = ty::Instance::new(def_id, substs);
186186
let cid = GlobalId { instance, promoted: None };
187-
let param_env =
188-
self.tcx.param_env(def_id).with_reveal_all_normalized(self.tcx).with_const();
187+
let param_env = self.tcx.param_env_reveal_all_normalized(def_id).with_const();
189188
// Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should
190189
// improve caching of queries.
191190
let inputs = self.tcx.erase_regions(param_env.and(cid));

compiler/rustc_middle/src/mir/interpret/value.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ impl<'tcx> ConstValue<'tcx> {
100100
param_env: ParamEnv<'tcx>,
101101
ty: Ty<'tcx>,
102102
) -> Option<u128> {
103-
let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
103+
let size = tcx.layout_of(param_env.and(ty)).ok()?.size;
104104
self.try_to_bits(size)
105105
}
106106

compiler/rustc_middle/src/mir/mod.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2190,8 +2190,7 @@ impl<'tcx> ConstantKind<'tcx> {
21902190
Self::Ty(ct) => ct.try_eval_bits(tcx, param_env, ty),
21912191
Self::Val(val, t) => {
21922192
assert_eq!(*t, ty);
2193-
let size =
2194-
tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
2193+
let size = tcx.layout_of(param_env.and(ty)).ok()?.size;
21952194
val.try_to_bits(size)
21962195
}
21972196
}

compiler/rustc_middle/src/query/mod.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1236,8 +1236,6 @@ rustc_queries! {
12361236
}
12371237

12381238
/// Like `param_env`, but returns the `ParamEnv` in `Reveal::All` mode.
1239-
/// Prefer this over `tcx.param_env(def_id).with_reveal_all_normalized(tcx)`,
1240-
/// as this method is more efficient.
12411239
query param_env_reveal_all_normalized(def_id: DefId) -> ty::ParamEnv<'tcx> {
12421240
desc { |tcx| "computing revealed normalized predicates of `{}`", tcx.def_path_str(def_id) }
12431241
}

compiler/rustc_middle/src/traits/mod.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,17 @@ pub enum Reveal {
7070
/// Also, `impl Trait` is normalized to the concrete type,
7171
/// which has to be already collected by type-checking.
7272
///
73-
/// NOTE: as `impl Trait`'s concrete type should *never*
74-
/// be observable directly by the user, `Reveal::All`
75-
/// should not be used by checks which may expose
76-
/// type equality or type contents to the user.
77-
/// There are some exceptions, e.g., around auto traits and
78-
/// transmute-checking, which expose some details, but
79-
/// not the whole concrete type of the `impl Trait`.
73+
/// **This should not be used at any point before borrowck**
74+
///
75+
/// The concrete type of an opaque type should *never*
76+
/// be observable directly by the user and doing so can cause
77+
/// cycles if done before borrowck. Therefore, `Reveal::All`
78+
/// should not be used by checks which may expose type equality
79+
/// or type contents to the user.
80+
///
81+
/// There are some places where we do observe some details about
82+
/// the concrete type of opaque types, e.g., around auto traits and
83+
/// transmute-checking, but these shouldn't rely on `Reveal::All`.
8084
All,
8185
}
8286

compiler/rustc_middle/src/ty/consts.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ impl<'tcx> Const<'tcx> {
250250
ty: Ty<'tcx>,
251251
) -> Option<u128> {
252252
assert_eq!(self.ty(), ty);
253-
let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
253+
let size = tcx.layout_of(param_env.and(ty)).ok()?.size;
254254
// if `ty` does not depend on generic parameters, use an empty param_env
255255
self.kind().eval(tcx, param_env).try_to_bits(size)
256256
}

compiler/rustc_middle/src/ty/consts/kind.rs

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -183,16 +183,7 @@ impl<'tcx> ConstKind<'tcx> {
183183
if let ConstKind::Unevaluated(unevaluated) = self {
184184
use crate::mir::interpret::ErrorHandled;
185185

186-
// HACK(eddyb) this erases lifetimes even though `const_eval_resolve`
187-
// also does later, but we want to do it before checking for
188-
// inference variables.
189-
// Note that we erase regions *before* calling `with_reveal_all_normalized`,
190-
// so that we don't try to invoke this query with
191-
// any region variables.
192-
let param_env_and = tcx
193-
.erase_regions(param_env)
194-
.with_reveal_all_normalized(tcx)
195-
.and(tcx.erase_regions(unevaluated));
186+
let param_env_and = tcx.erase_regions(param_env).and(tcx.erase_regions(unevaluated));
196187

197188
// HACK(eddyb) when the query key would contain inference variables,
198189
// attempt using identity substs and `ParamEnv` instead, that will succeed

compiler/rustc_middle/src/ty/layout.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,6 @@ fn layout_of<'tcx>(
232232
let (param_env, ty) = query.into_parts();
233233
debug!(?ty);
234234

235-
let param_env = param_env.with_reveal_all_normalized(tcx);
236235
let unnormalized_ty = ty;
237236

238237
// FIXME: We might want to have two different versions of `layout_of`:

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1522,27 +1522,6 @@ impl<'tcx> ParamEnv<'tcx> {
15221522
*self = self.with_constness(constness.and(self.constness()))
15231523
}
15241524

1525-
/// Returns a new parameter environment with the same clauses, but
1526-
/// which "reveals" the true results of projections in all cases
1527-
/// (even for associated types that are specializable). This is
1528-
/// the desired behavior during codegen and certain other special
1529-
/// contexts; normally though we want to use `Reveal::UserFacing`,
1530-
/// which is the default.
1531-
/// All opaque types in the caller_bounds of the `ParamEnv`
1532-
/// will be normalized to their underlying types.
1533-
/// See PR #65989 and issue #65918 for more details
1534-
pub fn with_reveal_all_normalized(self, tcx: TyCtxt<'tcx>) -> Self {
1535-
if self.packed.tag().reveal == traits::Reveal::All {
1536-
return self;
1537-
}
1538-
1539-
ParamEnv::new(
1540-
tcx.normalize_opaque_types(self.caller_bounds()),
1541-
Reveal::All,
1542-
self.constness(),
1543-
)
1544-
}
1545-
15461525
/// Returns this same environment but with no caller bounds.
15471526
#[inline]
15481527
pub fn without_caller_bounds(self) -> Self {

0 commit comments

Comments
 (0)