Skip to content

Commit 1688719

Browse files
spastorinooli-obk
authored andcommitted
Promote Refs to constants instead of static
1 parent a59abfa commit 1688719

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+447
-223
lines changed

src/librustc/mir/interpret/queries.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,16 @@ impl<'tcx> TyCtxt<'tcx> {
3636
param_env: ty::ParamEnv<'tcx>,
3737
def_id: DefId,
3838
substs: SubstsRef<'tcx>,
39+
promoted: Option<mir::Promoted>,
3940
span: Option<Span>,
4041
) -> ConstEvalResult<'tcx> {
4142
let instance = ty::Instance::resolve(self, param_env, def_id, substs);
4243
if let Some(instance) = instance {
43-
self.const_eval_instance(param_env, instance, span)
44+
if let Some(promoted) = promoted {
45+
self.const_eval_promoted(instance, promoted)
46+
} else {
47+
self.const_eval_instance(param_env, instance, span)
48+
}
4449
} else {
4550
Err(ErrorHandled::TooGeneric)
4651
}

src/librustc/mir/mod.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,16 @@ pub struct Body<'tcx> {
166166

167167
/// A span representing this MIR, for error reporting.
168168
pub span: Span,
169+
170+
/// The user may be writing e.g. &[(SOME_CELL, 42)][i].1 and this would get promoted, because
171+
/// we'd statically know that no thing with interior mutability will ever be available to the
172+
/// user without some serious unsafe code. Now this means that our promoted is actually
173+
/// &[(SOME_CELL, 42)] and the MIR using it will do the &promoted[i].1 projection because the
174+
/// index may be a runtime value. Such a promoted value is illegal because it has reachable
175+
/// interior mutability. This flag just makes this situation very obvious where the previous
176+
/// implementation without the flag hid this situation silently.
177+
/// FIXME(oli-obk): rewrite the promoted during promotion to eliminate the cell components.
178+
pub ignore_interior_mut_in_const_validation: bool,
169179
}
170180

171181
impl<'tcx> Body<'tcx> {
@@ -202,6 +212,7 @@ impl<'tcx> Body<'tcx> {
202212
spread_arg: None,
203213
var_debug_info,
204214
span,
215+
ignore_interior_mut_in_const_validation: false,
205216
control_flow_destroyed,
206217
}
207218
}

src/librustc/traits/fulfill.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
515515
obligation.param_env,
516516
def_id,
517517
substs,
518+
None,
518519
Some(obligation.cause.span),
519520
) {
520521
Ok(_) => ProcessResult::Changed(vec![]),

src/librustc/traits/select.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -802,8 +802,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
802802

803803
ty::Predicate::ConstEvaluatable(def_id, substs) => {
804804
if !(obligation.param_env, substs).has_local_value() {
805-
match self.tcx().const_eval_resolve(obligation.param_env, def_id, substs, None)
806-
{
805+
match self.tcx().const_eval_resolve(
806+
obligation.param_env,
807+
def_id,
808+
substs,
809+
None,
810+
None,
811+
) {
807812
Ok(_) => Ok(EvaluatedToOk),
808813
Err(_) => Ok(EvaluatedToErr),
809814
}

src/librustc/traits/wf.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
359359
/// Pushes the obligations required for an array length to be WF
360360
/// into `self.out`.
361361
fn compute_array_len(&mut self, constant: ty::Const<'tcx>) {
362-
if let ty::ConstKind::Unevaluated(def_id, substs) = constant.val {
362+
if let ty::ConstKind::Unevaluated(def_id, substs, promoted) = constant.val {
363+
assert!(promoted.is_none());
364+
363365
let obligations = self.nominal_obligations(def_id, substs);
364366
self.out.extend(obligations);
365367

src/librustc/ty/flags.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ impl FlagComputation {
219219
fn add_const(&mut self, c: &ty::Const<'_>) {
220220
self.add_ty(c.ty);
221221
match c.val {
222-
ty::ConstKind::Unevaluated(_, substs) => {
222+
ty::ConstKind::Unevaluated(_, substs, _) => {
223223
self.add_substs(substs);
224224
self.add_flags(TypeFlags::HAS_PROJECTION);
225225
}

src/librustc/ty/print/pretty.rs

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -841,23 +841,31 @@ pub trait PrettyPrinter<'tcx>:
841841

842842
match (ct.val, &ct.ty.kind) {
843843
(_, ty::FnDef(did, substs)) => p!(print_value_path(*did, substs)),
844-
(ty::ConstKind::Unevaluated(did, substs), _) => match self.tcx().def_kind(did) {
845-
Some(DefKind::Static) | Some(DefKind::Const) | Some(DefKind::AssocConst) => {
846-
p!(print_value_path(did, substs))
847-
}
848-
_ => {
849-
if did.is_local() {
850-
let span = self.tcx().def_span(did);
851-
if let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span) {
852-
p!(write("{}", snip))
853-
} else {
854-
p!(write("_: "), print(ct.ty))
844+
(ty::ConstKind::Unevaluated(did, substs, promoted), _) => {
845+
if let Some(promoted) = promoted {
846+
p!(print_value_path(did, substs));
847+
p!(write("::{:?}", promoted));
848+
} else {
849+
match self.tcx().def_kind(did) {
850+
Some(DefKind::Static)
851+
| Some(DefKind::Const)
852+
| Some(DefKind::AssocConst) => p!(print_value_path(did, substs)),
853+
_ => {
854+
if did.is_local() {
855+
let span = self.tcx().def_span(did);
856+
if let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span)
857+
{
858+
p!(write("{}", snip))
859+
} else {
860+
p!(write("_: "), print(ct.ty))
861+
}
862+
} else {
863+
p!(write("_: "), print(ct.ty))
864+
}
855865
}
856-
} else {
857-
p!(write("_: "), print(ct.ty))
858866
}
859867
}
860-
},
868+
}
861869
(ty::ConstKind::Infer(..), _) => p!(write("_: "), print(ct.ty)),
862870
(ty::ConstKind::Param(ParamConst { name, .. }), _) => p!(write("{}", name)),
863871
(ty::ConstKind::Value(value), _) => return self.pretty_print_const_value(value, ct.ty),

src/librustc/ty/relate.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -568,12 +568,12 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
568568

569569
// FIXME(const_generics): this is wrong, as it is a projection
570570
(
571-
ty::ConstKind::Unevaluated(a_def_id, a_substs),
572-
ty::ConstKind::Unevaluated(b_def_id, b_substs),
573-
) if a_def_id == b_def_id => {
571+
ty::ConstKind::Unevaluated(a_def_id, a_substs, a_promoted),
572+
ty::ConstKind::Unevaluated(b_def_id, b_substs, b_promoted),
573+
) if a_def_id == b_def_id && a_promoted == b_promoted => {
574574
let substs =
575575
relation.relate_with_variance(ty::Variance::Invariant, &a_substs, &b_substs)?;
576-
Ok(ty::ConstKind::Unevaluated(a_def_id, &substs))
576+
Ok(ty::ConstKind::Unevaluated(a_def_id, &substs, a_promoted))
577577
}
578578
_ => Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))),
579579
};

src/librustc/ty/structural_impls.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,8 +1037,8 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> {
10371037
match *self {
10381038
ty::ConstKind::Infer(ic) => ty::ConstKind::Infer(ic.fold_with(folder)),
10391039
ty::ConstKind::Param(p) => ty::ConstKind::Param(p.fold_with(folder)),
1040-
ty::ConstKind::Unevaluated(did, substs) => {
1041-
ty::ConstKind::Unevaluated(did, substs.fold_with(folder))
1040+
ty::ConstKind::Unevaluated(did, substs, promoted) => {
1041+
ty::ConstKind::Unevaluated(did, substs.fold_with(folder), promoted)
10421042
}
10431043
ty::ConstKind::Value(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(..) => {
10441044
*self
@@ -1050,7 +1050,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> {
10501050
match *self {
10511051
ty::ConstKind::Infer(ic) => ic.visit_with(visitor),
10521052
ty::ConstKind::Param(p) => p.visit_with(visitor),
1053-
ty::ConstKind::Unevaluated(_, substs) => substs.visit_with(visitor),
1053+
ty::ConstKind::Unevaluated(_, substs, _) => substs.visit_with(visitor),
10541054
ty::ConstKind::Value(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => {
10551055
false
10561056
}

src/librustc/ty/sty.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use crate::infer::canonical::Canonical;
99
use crate::middle::region;
1010
use crate::mir::interpret::ConstValue;
1111
use crate::mir::interpret::Scalar;
12+
use crate::mir::Promoted;
1213
use crate::ty::layout::VariantIdx;
1314
use crate::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef};
1415
use crate::ty::{self, AdtDef, DefIdTree, Discr, Ty, TyCtxt, TypeFlags, TypeFoldable};
@@ -2375,7 +2376,7 @@ impl<'tcx> Const<'tcx> {
23752376

23762377
#[inline]
23772378
pub fn eval(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> &Const<'tcx> {
2378-
let try_const_eval = |did, param_env: ParamEnv<'tcx>, substs| {
2379+
let try_const_eval = |did, param_env: ParamEnv<'tcx>, substs, promoted| {
23792380
let param_env_and_substs = param_env.with_reveal_all().and(substs);
23802381

23812382
// Avoid querying `tcx.const_eval(...)` with any e.g. inference vars.
@@ -2387,11 +2388,11 @@ impl<'tcx> Const<'tcx> {
23872388

23882389
// try to resolve e.g. associated constants to their definition on an impl, and then
23892390
// evaluate the const.
2390-
tcx.const_eval_resolve(param_env, did, substs, None).ok()
2391+
tcx.const_eval_resolve(param_env, did, substs, promoted, None).ok()
23912392
};
23922393

23932394
match self.val {
2394-
ConstKind::Unevaluated(did, substs) => {
2395+
ConstKind::Unevaluated(did, substs, promoted) => {
23952396
// HACK(eddyb) when substs contain e.g. inference variables,
23962397
// attempt using identity substs instead, that will succeed
23972398
// when the expression doesn't depend on any parameters.
@@ -2401,12 +2402,12 @@ impl<'tcx> Const<'tcx> {
24012402
let identity_substs = InternalSubsts::identity_for_item(tcx, did);
24022403
// The `ParamEnv` needs to match the `identity_substs`.
24032404
let identity_param_env = tcx.param_env(did);
2404-
match try_const_eval(did, identity_param_env, identity_substs) {
2405+
match try_const_eval(did, identity_param_env, identity_substs, promoted) {
24052406
Some(ct) => ct.subst(tcx, substs),
24062407
None => self,
24072408
}
24082409
} else {
2409-
try_const_eval(did, param_env, substs).unwrap_or(self)
2410+
try_const_eval(did, param_env, substs, promoted).unwrap_or(self)
24102411
}
24112412
}
24122413
_ => self,
@@ -2470,7 +2471,7 @@ pub enum ConstKind<'tcx> {
24702471

24712472
/// Used in the HIR by using `Unevaluated` everywhere and later normalizing to one of the other
24722473
/// variants when the code is monomorphic enough for that.
2473-
Unevaluated(DefId, SubstsRef<'tcx>),
2474+
Unevaluated(DefId, SubstsRef<'tcx>, Option<Promoted>),
24742475

24752476
/// Used to hold computed value.
24762477
Value(ConstValue<'tcx>),

0 commit comments

Comments
 (0)