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

+35-31
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

+2-3
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

+1-1
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

+1-2
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

-2
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

+11-7
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

+1-1
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

+1-10
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

-1
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

-21
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 {

compiler/rustc_mir_build/src/thir/pattern/mod.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -473,11 +473,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
473473
_ => return pat_from_kind(self.lower_variant_or_leaf(res, id, span, ty, vec![])),
474474
};
475475

476-
// Use `Reveal::All` here because patterns are always monomorphic even if their function
477-
// isn't.
478-
let param_env_reveal_all = self.param_env.with_reveal_all_normalized(self.tcx);
479476
let substs = self.typeck_results.node_substs(id);
480-
let instance = match ty::Instance::resolve(self.tcx, param_env_reveal_all, def_id, substs) {
477+
let instance = match ty::Instance::resolve(self.tcx, self.param_env, def_id, substs) {
481478
Ok(Some(i)) => i,
482479
Ok(None) => {
483480
// It should be assoc consts if there's no error but we cannot resolve it.
@@ -500,7 +497,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
500497
let mir_structural_match_violation = self.tcx.mir_const_qualif(instance.def_id()).custom_eq;
501498
debug!("mir_structural_match_violation({:?}) -> {}", qpath, mir_structural_match_violation);
502499

503-
match self.tcx.const_eval_instance(param_env_reveal_all, instance, Some(span)) {
500+
match self.tcx.const_eval_instance(self.param_env, instance, Some(span)) {
504501
Ok(literal) => {
505502
let const_ = mir::ConstantKind::Val(literal, ty);
506503
let pattern = self.const_to_pat(const_, id, span, mir_structural_match_violation);

compiler/rustc_passes/src/layout_test.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ pub fn test_layout(tcx: TyCtxt<'_>) {
2525

2626
fn dump_layout_of<'tcx>(tcx: TyCtxt<'tcx>, item_def_id: LocalDefId, attr: &Attribute) {
2727
let tcx = tcx;
28-
let param_env = tcx.param_env(item_def_id);
28+
let param_env = tcx.param_env_reveal_all_normalized(item_def_id);
2929
let ty = tcx.type_of(item_def_id);
3030
match tcx.layout_of(param_env.and(ty)) {
3131
Ok(ty_layout) => {
@@ -66,10 +66,7 @@ fn dump_layout_of<'tcx>(tcx: TyCtxt<'tcx>, item_def_id: LocalDefId, attr: &Attri
6666
}
6767

6868
sym::debug => {
69-
let normalized_ty = tcx.normalize_erasing_regions(
70-
param_env.with_reveal_all_normalized(tcx),
71-
ty,
72-
);
69+
let normalized_ty = tcx.normalize_erasing_regions(param_env, ty);
7370
tcx.sess.span_err(
7471
tcx.def_span(item_def_id.to_def_id()),
7572
&format!("layout_of({:?}) = {:#?}", normalized_ty, *ty_layout),

compiler/rustc_ty_utils/src/instance.rs

-1
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,6 @@ fn resolve_associated_item<'tcx>(
243243
});
244244

245245
let substs = tcx.infer_ctxt().enter(|infcx| {
246-
let param_env = param_env.with_reveal_all_normalized(tcx);
247246
let substs = rcvr_substs.rebase_onto(tcx, trait_def_id, impl_data.substs);
248247
let substs = translate_substs(
249248
&infcx,

compiler/rustc_ty_utils/src/ty.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,12 @@ fn well_formed_types_in_env<'tcx>(
335335
}
336336

337337
fn param_env_reveal_all_normalized(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
338-
tcx.param_env(def_id).with_reveal_all_normalized(tcx)
338+
let param_env = tcx.param_env(def_id);
339+
ty::ParamEnv::new(
340+
tcx.normalize_opaque_types(param_env.caller_bounds()),
341+
traits::Reveal::All,
342+
param_env.constness(),
343+
)
339344
}
340345

341346
fn instance_def_size_estimate<'tcx>(

src/test/ui/const-generics/issues/issue-83765.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ note: ...which requires checking if `TensorDimension` fulfills its obligations..
1010
LL | trait TensorDimension {
1111
| ^^^^^^^^^^^^^^^^^^^^^
1212
= note: ...which again requires resolving instance `<LazyUpdim<T, { T::DIM }, DIM> as TensorDimension>::DIM`, completing the cycle
13-
note: cycle used when checking if `TensorDimension` fulfills its obligations
14-
--> $DIR/issue-83765.rs:4:1
13+
note: cycle used when const-evaluating + checking `TensorSize::size::{constant#0}`
14+
--> $DIR/issue-83765.rs:16:31
1515
|
16-
LL | trait TensorDimension {
17-
| ^^^^^^^^^^^^^^^^^^^^^
16+
LL | fn size(&self) -> [usize; Self::DIM];
17+
| ^^^^^^^^^
1818

1919
error: aborting due to previous error
2020

src/test/ui/consts/const-size_of-cycle.stderr

-5
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,6 @@ LL | bytes: [u8; std::mem::size_of::<Foo>()]
77
note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`...
88
--> $DIR/const-size_of-cycle.rs:4:17
99
|
10-
LL | bytes: [u8; std::mem::size_of::<Foo>()]
11-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
12-
note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`...
13-
--> $DIR/const-size_of-cycle.rs:4:17
14-
|
1510
LL | bytes: [u8; std::mem::size_of::<Foo>()]
1611
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
1712
= note: ...which requires computing layout of `Foo`...

src/test/ui/consts/issue-44415.stderr

-5
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,6 @@ LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
77
note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`...
88
--> $DIR/issue-44415.rs:6:17
99
|
10-
LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
11-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12-
note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`...
13-
--> $DIR/issue-44415.rs:6:17
14-
|
1510
LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
1611
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1712
= note: ...which requires computing layout of `Foo`...

src/test/ui/pattern/non-structural-match-types.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ fn main() {
99
const { || {} } => {}, //~ ERROR cannot be used in patterns
1010
}
1111
match loop {} {
12-
const { async {} } => {}, //~ ERROR cannot be used in patterns
12+
const { async {} } => {},
13+
//~^ ERROR constant pattern depends on a generic parameter
14+
//~| ERROR constant pattern depends on a generic parameter
1315
}
1416
}

src/test/ui/pattern/non-structural-match-types.stderr

+8-2
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,17 @@ error: `[closure@$DIR/non-structural-match-types.rs:9:17: 9:19]` cannot be used
44
LL | const { || {} } => {},
55
| ^^^^^^^^^^^^^^^
66

7-
error: `impl Future<Output = ()>` cannot be used in patterns
7+
error: constant pattern depends on a generic parameter
88
--> $DIR/non-structural-match-types.rs:12:9
99
|
1010
LL | const { async {} } => {},
1111
| ^^^^^^^^^^^^^^^^^^
1212

13-
error: aborting due to 2 previous errors
13+
error: constant pattern depends on a generic parameter
14+
--> $DIR/non-structural-match-types.rs:12:9
15+
|
16+
LL | const { async {} } => {},
17+
| ^^^^^^^^^^^^^^^^^^
18+
19+
error: aborting due to 3 previous errors
1420

src/test/ui/recursion/issue-26548-recursion-via-normalize.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
//~ ERROR cycle detected when computing layout of `core::option::Option<S>`
1+
//~ ERROR cycle detected when computing layout of `core::option::Option<<S as Mirror>::It>`
2+
//~| NOTE ...which requires computing layout of `core::option::Option<S>`...
23
//~| NOTE ...which requires computing layout of `S`...
3-
//~| NOTE ...which requires computing layout of `core::option::Option<<S as Mirror>::It>`...
4-
//~| NOTE ...which again requires computing layout of `core::option::Option<S>`, completing the cycle
5-
//~| NOTE cycle used when computing layout of `core::option::Option<<S as Mirror>::It>`
4+
//~| NOTE ...which again requires computing layout of `core::option::Option<<S as Mirror>::It>`, completing the cycle
65

76
trait Mirror {
7+
//~^ NOTE cycle used when checking deathness of variables in top-level module
88
type It: ?Sized;
99
}
1010
impl<T: ?Sized> Mirror for T {

0 commit comments

Comments
 (0)