Created
December 28, 2019 15:20
-
-
Save spastorino/31917c9f06a578b2ed40a9b5bb781e29 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
commit a2263d3bcd577949208df9cffcc985e6d0196e84 | |
Author: Santiago Pastorino <spastorino@gmail.com> | |
Date: Fri Nov 22 17:26:09 2019 -0300 | |
Promote `Ref`s to constants instead of static | |
diff --git a/src/librustc/mir/interpret/queries.rs b/src/librustc/mir/interpret/queries.rs | |
index e6caa146a62..e219e0b7eef 100644 | |
--- a/src/librustc/mir/interpret/queries.rs | |
+++ b/src/librustc/mir/interpret/queries.rs | |
@@ -36,11 +36,16 @@ impl<'tcx> TyCtxt<'tcx> { | |
param_env: ty::ParamEnv<'tcx>, | |
def_id: DefId, | |
substs: SubstsRef<'tcx>, | |
+ promoted: Option<mir::Promoted>, | |
span: Option<Span>, | |
) -> ConstEvalResult<'tcx> { | |
let instance = ty::Instance::resolve(self, param_env, def_id, substs); | |
if let Some(instance) = instance { | |
- self.const_eval_instance(param_env, instance, span) | |
+ if let Some(promoted) = promoted { | |
+ self.const_eval_promoted(instance, promoted) | |
+ } else { | |
+ self.const_eval_instance(param_env, instance, span) | |
+ } | |
} else { | |
Err(ErrorHandled::TooGeneric) | |
} | |
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs | |
index dc74ff1e98d..3fb14d43891 100644 | |
--- a/src/librustc/mir/mod.rs | |
+++ b/src/librustc/mir/mod.rs | |
@@ -165,6 +165,16 @@ pub struct Body<'tcx> { | |
/// A span representing this MIR, for error reporting. | |
pub span: Span, | |
+ | |
+ /// The user may be writing e.g. &[(SOME_CELL, 42)][i].1 and this would get promoted, because | |
+ /// we'd statically know that no thing with interior mutability will ever be available to the | |
+ /// user without some serious unsafe code. Now this means that our promoted is actually | |
+ /// &[(SOME_CELL, 42)] and the MIR using it will do the &promoted[i].1 projection because the | |
+ /// index may be a runtime value. Such a promoted value is illegal because it has reachable | |
+ /// interior mutability. This flag just makes this situation very obvious where the previous | |
+ /// implementation without the flag hid this situation silently. | |
+ /// FIXME(oli-obk): rewrite the promoted during promotion to eliminate the cell components. | |
+ pub ignore_interior_mut_in_const_validation: bool, | |
} | |
impl<'tcx> Body<'tcx> { | |
@@ -201,6 +211,7 @@ impl<'tcx> Body<'tcx> { | |
spread_arg: None, | |
var_debug_info, | |
span, | |
+ ignore_interior_mut_in_const_validation: false, | |
control_flow_destroyed, | |
} | |
} | |
diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs | |
index 614375287ba..76ca3eaca55 100644 | |
--- a/src/librustc/traits/fulfill.rs | |
+++ b/src/librustc/traits/fulfill.rs | |
@@ -514,6 +514,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> { | |
obligation.param_env, | |
def_id, | |
substs, | |
+ None, | |
Some(obligation.cause.span), | |
) { | |
Ok(_) => ProcessResult::Changed(vec![]), | |
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs | |
index f11fcc4ebae..a4f61fd9702 100644 | |
--- a/src/librustc/traits/select.rs | |
+++ b/src/librustc/traits/select.rs | |
@@ -800,8 +800,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | |
ty::Predicate::ConstEvaluatable(def_id, substs) => { | |
if !(obligation.param_env, substs).has_local_value() { | |
- match self.tcx().const_eval_resolve(obligation.param_env, def_id, substs, None) | |
- { | |
+ match self.tcx().const_eval_resolve( | |
+ obligation.param_env, | |
+ def_id, | |
+ substs, | |
+ None, | |
+ None, | |
+ ) { | |
Ok(_) => Ok(EvaluatedToOk), | |
Err(_) => Ok(EvaluatedToErr), | |
} | |
diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs | |
index b9aa12b4665..4a4280ba7dc 100644 | |
--- a/src/librustc/ty/flags.rs | |
+++ b/src/librustc/ty/flags.rs | |
@@ -219,7 +219,7 @@ impl FlagComputation { | |
fn add_const(&mut self, c: &ty::Const<'_>) { | |
self.add_ty(c.ty); | |
match c.val { | |
- ty::ConstKind::Unevaluated(_, substs) => { | |
+ ty::ConstKind::Unevaluated(_, substs, _) => { | |
self.add_substs(substs); | |
self.add_flags(TypeFlags::HAS_PROJECTION); | |
} | |
diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs | |
index 9bd7701da1f..3175b58221f 100644 | |
--- a/src/librustc/ty/print/pretty.rs | |
+++ b/src/librustc/ty/print/pretty.rs | |
@@ -841,23 +841,31 @@ pub trait PrettyPrinter<'tcx>: | |
match (ct.val, &ct.ty.kind) { | |
(_, ty::FnDef(did, substs)) => p!(print_value_path(*did, substs)), | |
- (ty::ConstKind::Unevaluated(did, substs), _) => match self.tcx().def_kind(did) { | |
- Some(DefKind::Static) | Some(DefKind::Const) | Some(DefKind::AssocConst) => { | |
- p!(print_value_path(did, substs)) | |
- } | |
- _ => { | |
- if did.is_local() { | |
- let span = self.tcx().def_span(did); | |
- if let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span) { | |
- p!(write("{}", snip)) | |
- } else { | |
- p!(write("_: "), print(ct.ty)) | |
+ (ty::ConstKind::Unevaluated(did, substs, promoted), _) => { | |
+ if let Some(promoted) = promoted { | |
+ p!(print_value_path(did, substs)); | |
+ p!(write("::{:?}", promoted)); | |
+ } else { | |
+ match self.tcx().def_kind(did) { | |
+ Some(DefKind::Static) | |
+ | Some(DefKind::Const) | |
+ | Some(DefKind::AssocConst) => p!(print_value_path(did, substs)), | |
+ _ => { | |
+ if did.is_local() { | |
+ let span = self.tcx().def_span(did); | |
+ if let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span) | |
+ { | |
+ p!(write("{}", snip)) | |
+ } else { | |
+ p!(write("_: "), print(ct.ty)) | |
+ } | |
+ } else { | |
+ p!(write("_: "), print(ct.ty)) | |
+ } | |
} | |
- } else { | |
- p!(write("_: "), print(ct.ty)) | |
} | |
} | |
- }, | |
+ } | |
(ty::ConstKind::Infer(..), _) => p!(write("_: "), print(ct.ty)), | |
(ty::ConstKind::Param(ParamConst { name, .. }), _) => p!(write("{}", name)), | |
(ty::ConstKind::Value(value), _) => return self.pretty_print_const_value(value, ct.ty), | |
diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs | |
index 120f05ba7d9..b780c8dc1f6 100644 | |
--- a/src/librustc/ty/relate.rs | |
+++ b/src/librustc/ty/relate.rs | |
@@ -568,12 +568,12 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>( | |
// FIXME(const_generics): this is wrong, as it is a projection | |
( | |
- ty::ConstKind::Unevaluated(a_def_id, a_substs), | |
- ty::ConstKind::Unevaluated(b_def_id, b_substs), | |
- ) if a_def_id == b_def_id => { | |
+ ty::ConstKind::Unevaluated(a_def_id, a_substs, a_promoted), | |
+ ty::ConstKind::Unevaluated(b_def_id, b_substs, b_promoted), | |
+ ) if a_def_id == b_def_id && a_promoted == b_promoted => { | |
let substs = | |
relation.relate_with_variance(ty::Variance::Invariant, &a_substs, &b_substs)?; | |
- Ok(ty::ConstKind::Unevaluated(a_def_id, &substs)) | |
+ Ok(ty::ConstKind::Unevaluated(a_def_id, &substs, a_promoted)) | |
} | |
_ => Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))), | |
}; | |
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs | |
index 61ee7288a9b..76fb7ce1061 100644 | |
--- a/src/librustc/ty/structural_impls.rs | |
+++ b/src/librustc/ty/structural_impls.rs | |
@@ -1044,8 +1044,8 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> { | |
match *self { | |
ty::ConstKind::Infer(ic) => ty::ConstKind::Infer(ic.fold_with(folder)), | |
ty::ConstKind::Param(p) => ty::ConstKind::Param(p.fold_with(folder)), | |
- ty::ConstKind::Unevaluated(did, substs) => { | |
- ty::ConstKind::Unevaluated(did, substs.fold_with(folder)) | |
+ ty::ConstKind::Unevaluated(did, substs, promoted) => { | |
+ ty::ConstKind::Unevaluated(did, substs.fold_with(folder), promoted) | |
} | |
ty::ConstKind::Value(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(..) => { | |
*self | |
@@ -1057,7 +1057,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> { | |
match *self { | |
ty::ConstKind::Infer(ic) => ic.visit_with(visitor), | |
ty::ConstKind::Param(p) => p.visit_with(visitor), | |
- ty::ConstKind::Unevaluated(_, substs) => substs.visit_with(visitor), | |
+ ty::ConstKind::Unevaluated(_, substs, _) => substs.visit_with(visitor), | |
ty::ConstKind::Value(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => { | |
false | |
} | |
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs | |
index c17fff29810..278aec5c441 100644 | |
--- a/src/librustc/ty/sty.rs | |
+++ b/src/librustc/ty/sty.rs | |
@@ -11,6 +11,7 @@ use crate::infer::canonical::Canonical; | |
use crate::middle::region; | |
use crate::mir::interpret::ConstValue; | |
use crate::mir::interpret::Scalar; | |
+use crate::mir::Promoted; | |
use crate::ty::layout::VariantIdx; | |
use crate::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef}; | |
use crate::ty::{self, AdtDef, DefIdTree, Discr, Ty, TyCtxt, TypeFlags, TypeFoldable}; | |
@@ -2376,7 +2377,7 @@ impl<'tcx> Const<'tcx> { | |
#[inline] | |
pub fn eval(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> &Const<'tcx> { | |
- let try_const_eval = |did, param_env: ParamEnv<'tcx>, substs| { | |
+ let try_const_eval = |did, param_env: ParamEnv<'tcx>, substs, promoted| { | |
let param_env_and_substs = param_env.with_reveal_all().and(substs); | |
// Avoid querying `tcx.const_eval(...)` with any e.g. inference vars. | |
@@ -2388,11 +2389,11 @@ impl<'tcx> Const<'tcx> { | |
// try to resolve e.g. associated constants to their definition on an impl, and then | |
// evaluate the const. | |
- tcx.const_eval_resolve(param_env, did, substs, None).ok() | |
+ tcx.const_eval_resolve(param_env, did, substs, promoted, None).ok() | |
}; | |
match self.val { | |
- ConstKind::Unevaluated(did, substs) => { | |
+ ConstKind::Unevaluated(did, substs, promoted) => { | |
// HACK(eddyb) when substs contain e.g. inference variables, | |
// attempt using identity substs instead, that will succeed | |
// when the expression doesn't depend on any parameters. | |
@@ -2402,12 +2403,12 @@ impl<'tcx> Const<'tcx> { | |
let identity_substs = InternalSubsts::identity_for_item(tcx, did); | |
// The `ParamEnv` needs to match the `identity_substs`. | |
let identity_param_env = tcx.param_env(did); | |
- match try_const_eval(did, identity_param_env, identity_substs) { | |
+ match try_const_eval(did, identity_param_env, identity_substs, promoted) { | |
Some(ct) => ct.subst(tcx, substs), | |
None => self, | |
} | |
} else { | |
- try_const_eval(did, param_env, substs).unwrap_or(self) | |
+ try_const_eval(did, param_env, substs, promoted).unwrap_or(self) | |
} | |
} | |
_ => self, | |
@@ -2471,7 +2472,7 @@ pub enum ConstKind<'tcx> { | |
/// Used in the HIR by using `Unevaluated` everywhere and later normalizing to one of the other | |
/// variants when the code is monomorphic enough for that. | |
- Unevaluated(DefId, SubstsRef<'tcx>), | |
+ Unevaluated(DefId, SubstsRef<'tcx>, Option<Promoted>), | |
/// Used to hold computed value. | |
Value(ConstValue<'tcx>), | |
diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs | |
index 9e0dd8e067a..da08fbcf144 100644 | |
--- a/src/librustc/ty/walk.rs | |
+++ b/src/librustc/ty/walk.rs | |
@@ -81,7 +81,8 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) { | |
| ty::Bound(..) | |
| ty::Foreign(..) => {} | |
ty::Array(ty, len) => { | |
- if let ty::ConstKind::Unevaluated(_, substs) = len.val { | |
+ if let ty::ConstKind::Unevaluated(_, substs, promoted) = len.val { | |
+ assert!(promoted.is_none()); | |
stack.extend(substs.types().rev()); | |
} | |
stack.push(len.ty); | |
diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs | |
index 900c425fac2..3bfcb6bdacf 100644 | |
--- a/src/librustc/ty/wf.rs | |
+++ b/src/librustc/ty/wf.rs | |
@@ -358,7 +358,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { | |
/// Pushes the obligations required for an array length to be WF | |
/// into `self.out`. | |
fn compute_array_len(&mut self, constant: ty::Const<'tcx>) { | |
- if let ty::ConstKind::Unevaluated(def_id, substs) = constant.val { | |
+ if let ty::ConstKind::Unevaluated(def_id, substs, promoted) = constant.val { | |
+ assert!(promoted.is_none()); | |
+ | |
let obligations = self.nominal_obligations(def_id, substs); | |
self.out.extend(obligations); | |
diff --git a/src/librustc_codegen_ssa/mir/constant.rs b/src/librustc_codegen_ssa/mir/constant.rs | |
index 2a4329cdb06..10d4177fe74 100644 | |
--- a/src/librustc_codegen_ssa/mir/constant.rs | |
+++ b/src/librustc_codegen_ssa/mir/constant.rs | |
@@ -20,7 +20,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { | |
// use `get_static` to get at their id. | |
// FIXME(oli-obk): can we unify this somehow, maybe by making const eval of statics | |
// always produce `&STATIC`. This may also simplify how const eval works with statics. | |
- ty::ConstKind::Unevaluated(def_id, substs) if self.cx.tcx().is_static(def_id) => { | |
+ ty::ConstKind::Unevaluated(def_id, substs, promoted) | |
+ if self.cx.tcx().is_static(def_id) => | |
+ { | |
+ assert!(promoted.is_none()); | |
assert!(substs.is_empty(), "we don't support generic statics yet"); | |
let static_ = bx.get_static(def_id); | |
// we treat operands referring to statics as if they were `&STATIC` instead | |
@@ -40,11 +43,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { | |
constant: &mir::Constant<'tcx>, | |
) -> Result<&'tcx ty::Const<'tcx>, ErrorHandled> { | |
match constant.literal.val { | |
- ty::ConstKind::Unevaluated(def_id, substs) => { | |
+ ty::ConstKind::Unevaluated(def_id, substs, promoted) => { | |
let substs = self.monomorphize(&substs); | |
self.cx | |
.tcx() | |
- .const_eval_resolve(ty::ParamEnv::reveal_all(), def_id, substs, None) | |
+ .const_eval_resolve(ty::ParamEnv::reveal_all(), def_id, substs, promoted, None) | |
.map_err(|err| { | |
self.cx | |
.tcx() | |
diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs | |
index db7db03bde0..254af9094b0 100644 | |
--- a/src/librustc_mir/borrow_check/type_check/mod.rs | |
+++ b/src/librustc_mir/borrow_check/type_check/mod.rs | |
@@ -309,17 +309,54 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { | |
); | |
} | |
} else { | |
- if let ty::ConstKind::Unevaluated(def_id, substs) = constant.literal.val { | |
- if let Err(terr) = self.cx.fully_perform_op( | |
- location.to_locations(), | |
- ConstraintCategory::Boring, | |
- self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new( | |
- constant.literal.ty, | |
- def_id, | |
- UserSubsts { substs, user_self_ty: None }, | |
- )), | |
- ) { | |
- span_mirbug!(self, constant, "bad constant type {:?} ({:?})", constant, terr); | |
+ if let ty::ConstKind::Unevaluated(def_id, substs, promoted) = constant.literal.val { | |
+ if let Some(promoted) = promoted { | |
+ let check_err = |verifier: &mut TypeVerifier<'a, 'b, 'tcx>, | |
+ promoted: &ReadOnlyBodyAndCache<'_, 'tcx>, | |
+ ty, | |
+ san_ty| { | |
+ if let Err(terr) = verifier.cx.eq_types( | |
+ san_ty, | |
+ ty, | |
+ location.to_locations(), | |
+ ConstraintCategory::Boring, | |
+ ) { | |
+ span_mirbug!( | |
+ verifier, | |
+ promoted, | |
+ "bad promoted type ({:?}: {:?}): {:?}", | |
+ ty, | |
+ san_ty, | |
+ terr | |
+ ); | |
+ }; | |
+ }; | |
+ | |
+ if !self.errors_reported { | |
+ let promoted_body = self.promoted[promoted]; | |
+ self.sanitize_promoted(promoted_body, location); | |
+ | |
+ let promoted_ty = promoted_body.return_ty(); | |
+ check_err(self, &promoted_body, ty, promoted_ty); | |
+ } | |
+ } else { | |
+ if let Err(terr) = self.cx.fully_perform_op( | |
+ location.to_locations(), | |
+ ConstraintCategory::Boring, | |
+ self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new( | |
+ constant.literal.ty, | |
+ def_id, | |
+ UserSubsts { substs, user_self_ty: None }, | |
+ )), | |
+ ) { | |
+ span_mirbug!( | |
+ self, | |
+ constant, | |
+ "bad constant type {:?} ({:?})", | |
+ constant, | |
+ terr | |
+ ); | |
+ } | |
} | |
} | |
if let ty::FnDef(def_id, substs) = constant.literal.ty.kind { | |
diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs | |
index 63e63f304d2..56bb5ef3b40 100644 | |
--- a/src/librustc_mir/const_eval.rs | |
+++ b/src/librustc_mir/const_eval.rs | |
@@ -51,7 +51,7 @@ pub(crate) fn const_caller_location<'tcx>( | |
let loc_ty = tcx.caller_location_ty(); | |
let loc_place = ecx.alloc_caller_location(file, line, col); | |
- intern_const_alloc_recursive(&mut ecx, None, loc_place).unwrap(); | |
+ intern_const_alloc_recursive(&mut ecx, None, loc_place, false).unwrap(); | |
let loc_const = ty::Const { | |
ty: loc_ty, | |
val: ty::ConstKind::Value(ConstValue::Scalar(loc_place.ptr.into())), | |
diff --git a/src/librustc_mir/const_eval/eval_queries.rs b/src/librustc_mir/const_eval/eval_queries.rs | |
index 745b6aabfa6..16fa48ba79c 100644 | |
--- a/src/librustc_mir/const_eval/eval_queries.rs | |
+++ b/src/librustc_mir/const_eval/eval_queries.rs | |
@@ -56,7 +56,12 @@ fn eval_body_using_ecx<'mir, 'tcx>( | |
ecx.run()?; | |
// Intern the result | |
- intern_const_alloc_recursive(ecx, tcx.static_mutability(cid.instance.def_id()), ret)?; | |
+ intern_const_alloc_recursive( | |
+ ecx, | |
+ tcx.static_mutability(cid.instance.def_id()), | |
+ ret, | |
+ body.ignore_interior_mut_in_const_validation, | |
+ )?; | |
debug!("eval_body_using_ecx done: {:?}", *ret); | |
Ok(ret) | |
@@ -168,9 +173,14 @@ fn validate_and_turn_into_const<'tcx>( | |
let ecx = mk_eval_cx(tcx, tcx.def_span(key.value.instance.def_id()), key.param_env, is_static); | |
let val = (|| { | |
let mplace = ecx.raw_const_to_mplace(constant)?; | |
- let mut ref_tracking = RefTracking::new(mplace); | |
- while let Some((mplace, path)) = ref_tracking.todo.pop() { | |
- ecx.validate_operand(mplace.into(), path, Some(&mut ref_tracking))?; | |
+ | |
+ // FIXME do not validate promoteds until a decision on | |
+ // https://github.com/rust-lang/rust/issues/67465 is made | |
+ if cid.promoted.is_none() { | |
+ let mut ref_tracking = RefTracking::new(mplace); | |
+ while let Some((mplace, path)) = ref_tracking.todo.pop() { | |
+ ecx.validate_operand(mplace.into(), path, Some(&mut ref_tracking))?; | |
+ } | |
} | |
// Now that we validated, turn this into a proper constant. | |
// Statics/promoteds are always `ByRef`, for the rest `op_to_const` decides | |
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs | |
index 124b788fe8d..34be71fdf3c 100644 | |
--- a/src/librustc_mir/hair/cx/expr.rs | |
+++ b/src/librustc_mir/hair/cx/expr.rs | |
@@ -411,15 +411,18 @@ fn make_mirror_unadjusted<'a, 'tcx>( | |
let def_id = cx.tcx.hir().local_def_id(count.hir_id); | |
let substs = InternalSubsts::identity_for_item(cx.tcx, def_id); | |
let span = cx.tcx.def_span(def_id); | |
- let count = match cx.tcx.const_eval_resolve(cx.param_env, def_id, substs, Some(span)) { | |
- Ok(cv) => cv.eval_usize(cx.tcx, cx.param_env), | |
- Err(ErrorHandled::Reported) => 0, | |
- Err(ErrorHandled::TooGeneric) => { | |
- let span = cx.tcx.def_span(def_id); | |
- cx.tcx.sess.span_err(span, "array lengths can't depend on generic parameters"); | |
- 0 | |
- } | |
- }; | |
+ let count = | |
+ match cx.tcx.const_eval_resolve(cx.param_env, def_id, substs, None, Some(span)) { | |
+ Ok(cv) => cv.eval_usize(cx.tcx, cx.param_env), | |
+ Err(ErrorHandled::Reported) => 0, | |
+ Err(ErrorHandled::TooGeneric) => { | |
+ let span = cx.tcx.def_span(def_id); | |
+ cx.tcx | |
+ .sess | |
+ .span_err(span, "array lengths can't depend on generic parameters"); | |
+ 0 | |
+ } | |
+ }; | |
ExprKind::Repeat { value: v.to_ref(), count } | |
} | |
@@ -523,7 +526,7 @@ fn make_mirror_unadjusted<'a, 'tcx>( | |
// and not the beginning of discriminants (which is always `0`) | |
let substs = InternalSubsts::identity_for_item(cx.tcx(), did); | |
let lhs = mk_const(cx.tcx().mk_const(ty::Const { | |
- val: ty::ConstKind::Unevaluated(did, substs), | |
+ val: ty::ConstKind::Unevaluated(did, substs, None), | |
ty: var_ty, | |
})); | |
let bin = ExprKind::Binary { op: BinOp::Add, lhs, rhs: offset }; | |
@@ -719,7 +722,7 @@ fn convert_path_expr<'a, 'tcx>( | |
debug!("convert_path_expr: (const) user_ty={:?}", user_ty); | |
ExprKind::Literal { | |
literal: cx.tcx.mk_const(ty::Const { | |
- val: ty::ConstKind::Unevaluated(def_id, substs), | |
+ val: ty::ConstKind::Unevaluated(def_id, substs, None), | |
ty: cx.tables().node_type(expr.hir_id), | |
}), | |
user_ty, | |
diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs | |
index 6dd3c0f80da..c03ca245a6e 100644 | |
--- a/src/librustc_mir/hair/pattern/mod.rs | |
+++ b/src/librustc_mir/hair/pattern/mod.rs | |
@@ -742,7 +742,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { | |
let kind = match res { | |
Res::Def(DefKind::Const, def_id) | Res::Def(DefKind::AssocConst, def_id) => { | |
let substs = self.tables.node_substs(id); | |
- match self.tcx.const_eval_resolve(self.param_env, def_id, substs, Some(span)) { | |
+ match self.tcx.const_eval_resolve(self.param_env, def_id, substs, None, Some(span)) | |
+ { | |
Ok(value) => { | |
let pattern = self.const_to_pat(value, id, span); | |
if !is_associated_const { | |
diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs | |
index dffc8e8256c..335c96ce538 100644 | |
--- a/src/librustc_mir/interpret/intern.rs | |
+++ b/src/librustc_mir/interpret/intern.rs | |
@@ -41,6 +41,11 @@ struct InternVisitor<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>> { | |
/// despite the nested mutable reference! | |
/// The field gets updated when an `UnsafeCell` is encountered. | |
mutability: Mutability, | |
+ | |
+ /// This flag is to avoid triggering UnsafeCells are not allowed behind references in constants | |
+ /// for promoteds. | |
+ /// It's a copy of `mir::Body`'s ignore_interior_mut_in_const_validation field | |
+ ignore_interior_mut_in_const_validation: bool, | |
} | |
#[derive(Copy, Clone, Debug, PartialEq, Hash, Eq)] | |
@@ -164,14 +169,16 @@ impl<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx | |
// References we encounter inside here are interned as pointing to mutable | |
// allocations. | |
let old = std::mem::replace(&mut self.mutability, Mutability::Mut); | |
- assert_ne!( | |
- self.mode, | |
- InternMode::Const, | |
- "UnsafeCells are not allowed behind references in constants. This should have \ | |
- been prevented statically by const qualification. If this were allowed one \ | |
- would be able to change a constant at one use site and other use sites could \ | |
- observe that mutation.", | |
- ); | |
+ if !self.ignore_interior_mut_in_const_validation { | |
+ assert_ne!( | |
+ self.mode, | |
+ InternMode::Const, | |
+ "UnsafeCells are not allowed behind references in constants. This should \ | |
+ have been prevented statically by const qualification. If this were \ | |
+ allowed one would be able to change a constant at one use site and other \ | |
+ use sites could observe that mutation.", | |
+ ); | |
+ } | |
let walked = self.walk_aggregate(mplace, fields); | |
self.mutability = old; | |
return walked; | |
@@ -265,6 +272,7 @@ pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>( | |
// The `mutability` of the place, ignoring the type. | |
place_mut: Option<hir::Mutability>, | |
ret: MPlaceTy<'tcx>, | |
+ ignore_interior_mut_in_const_validation: bool, | |
) -> InterpResult<'tcx> { | |
let tcx = ecx.tcx; | |
let (base_mutability, base_intern_mode) = match place_mut { | |
@@ -301,6 +309,7 @@ pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>( | |
mode, | |
leftover_allocations, | |
mutability, | |
+ ignore_interior_mut_in_const_validation, | |
} | |
.visit_value(mplace); | |
if let Err(error) = interned { | |
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs | |
index def979b63b5..adca5ea5e3a 100644 | |
--- a/src/librustc_mir/interpret/operand.rs | |
+++ b/src/librustc_mir/interpret/operand.rs | |
@@ -576,7 +576,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { | |
// Early-return cases. | |
let val_val = match val.val { | |
ty::ConstKind::Param(_) => throw_inval!(TooGeneric), | |
- ty::ConstKind::Unevaluated(def_id, substs) => { | |
+ ty::ConstKind::Unevaluated(def_id, substs, promoted) => { | |
let instance = self.resolve(def_id, substs)?; | |
// We use `const_eval` here and `const_eval_raw` elsewhere in mir interpretation. | |
// The reason we use `const_eval_raw` everywhere else is to prevent cycles during | |
@@ -586,7 +586,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { | |
// happening. | |
// FIXME(oli-obk): eliminate all the `const_eval_raw` usages when we get rid of | |
// `StaticKind` once and for all. | |
- return self.const_eval(GlobalId { instance, promoted: None }); | |
+ return self.const_eval(GlobalId { instance, promoted }); | |
} | |
ty::ConstKind::Infer(..) | |
| ty::ConstKind::Bound(..) | |
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs | |
index 0a783337ad1..c06f3b42d08 100644 | |
--- a/src/librustc_mir/monomorphize/collector.rs | |
+++ b/src/librustc_mir/monomorphize/collector.rs | |
@@ -1253,8 +1253,8 @@ fn collect_const<'tcx>( | |
collect_miri(tcx, id, output); | |
} | |
} | |
- ty::ConstKind::Unevaluated(def_id, substs) => { | |
- match tcx.const_eval_resolve(param_env, def_id, substs, None) { | |
+ ty::ConstKind::Unevaluated(def_id, substs, promoted) => { | |
+ match tcx.const_eval_resolve(param_env, def_id, substs, promoted, None) { | |
Ok(val) => collect_const(tcx, val, param_substs, output), | |
Err(ErrorHandled::Reported) => {} | |
Err(ErrorHandled::TooGeneric) => { | |
diff --git a/src/librustc_mir/transform/check_consts/qualifs.rs b/src/librustc_mir/transform/check_consts/qualifs.rs | |
index 746d83b05c6..741fadc117e 100644 | |
--- a/src/librustc_mir/transform/check_consts/qualifs.rs | |
+++ b/src/librustc_mir/transform/check_consts/qualifs.rs | |
@@ -103,7 +103,9 @@ pub trait Qualif { | |
Operand::Constant(ref constant) => { | |
if let Some(static_) = constant.check_static_ptr(cx.tcx) { | |
Self::in_static(cx, static_) | |
- } else if let ty::ConstKind::Unevaluated(def_id, _) = constant.literal.val { | |
+ } else if let ty::ConstKind::Unevaluated(def_id, _, promoted) = constant.literal.val | |
+ { | |
+ assert!(promoted.is_none()); | |
// Don't peek inside trait associated constants. | |
if cx.tcx.trait_of_item(def_id).is_some() { | |
Self::in_any_value_of_ty(cx, constant.literal.ty) | |
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs | |
index a6b30ab5e68..4b42d51b92b 100644 | |
--- a/src/librustc_mir/transform/const_prop.rs | |
+++ b/src/librustc_mir/transform/const_prop.rs | |
@@ -6,6 +6,7 @@ use std::cell::Cell; | |
use rustc::hir::def::DefKind; | |
use rustc::hir::def_id::DefId; | |
+use rustc::hir::HirId; | |
use rustc::mir::interpret::{InterpResult, PanicInfo, Scalar}; | |
use rustc::mir::visit::{ | |
MutVisitor, MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor, | |
@@ -33,6 +34,7 @@ use crate::interpret::{ | |
ScalarMaybeUndef, StackPopCleanup, | |
}; | |
use crate::rustc::ty::subst::Subst; | |
+use crate::rustc::ty::TypeFoldable; | |
use crate::transform::{MirPass, MirSource}; | |
/// The maximum number of bytes that we'll allocate space for a return value. | |
@@ -260,6 +262,7 @@ struct ConstPropagator<'mir, 'tcx> { | |
source_scopes: IndexVec<SourceScope, SourceScopeData>, | |
local_decls: IndexVec<Local, LocalDecl<'tcx>>, | |
ret: Option<OpTy<'tcx, ()>>, | |
+ lint_root: Option<HirId>, | |
} | |
impl<'mir, 'tcx> LayoutOf for ConstPropagator<'mir, 'tcx> { | |
@@ -331,6 +334,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { | |
//FIXME(wesleywiser) we can't steal this because `Visitor::super_visit_body()` needs it | |
local_decls: body.local_decls.clone(), | |
ret: ret.map(Into::into), | |
+ lint_root: None, | |
} | |
} | |
@@ -357,13 +361,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { | |
F: FnOnce(&mut Self) -> InterpResult<'tcx, T>, | |
{ | |
self.ecx.tcx.span = source_info.span; | |
- // FIXME(eddyb) move this to the `Panic(_)` error case, so that | |
- // `f(self)` is always called, and that the only difference when the | |
- // scope's `local_data` is missing, is that the lint isn't emitted. | |
- let lint_root = match &self.source_scopes[source_info.scope].local_data { | |
- ClearCrossCrate::Set(data) => data.lint_root, | |
- ClearCrossCrate::Clear => return None, | |
- }; | |
let r = match f(self) { | |
Ok(val) => Some(val), | |
Err(error) => { | |
@@ -397,7 +394,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { | |
diagnostic.report_as_lint( | |
self.ecx.tcx, | |
"this expression will panic at runtime", | |
- lint_root, | |
+ self.lint_root?, | |
None, | |
); | |
} | |
@@ -411,11 +408,28 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { | |
fn eval_constant(&mut self, c: &Constant<'tcx>) -> Option<Const<'tcx>> { | |
self.ecx.tcx.span = c.span; | |
+ | |
+ // FIXME we need to revisit this for #67176 | |
+ if c.needs_subst() { | |
+ return None; | |
+ } | |
+ | |
match self.ecx.eval_const_to_op(c.literal, None) { | |
Ok(op) => Some(op), | |
Err(error) => { | |
let err = error_to_const_error(&self.ecx, error); | |
- err.report_as_error(self.ecx.tcx, "erroneous constant used"); | |
+ | |
+ if let ty::ConstKind::Unevaluated(_, _, Some(_)) = c.literal.val { | |
+ err.report_as_lint( | |
+ self.ecx.tcx, | |
+ "erroneous constant used", | |
+ self.lint_root?, | |
+ Some(c.span), | |
+ ); | |
+ } else { | |
+ err.report_as_error(self.ecx.tcx, "erroneous constant used"); | |
+ } | |
+ | |
None | |
} | |
} | |
@@ -449,6 +463,11 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { | |
return None; | |
} | |
+ // FIXME we need to revisit this for #67176 | |
+ if rvalue.needs_subst() { | |
+ return None; | |
+ } | |
+ | |
let overflow_check = self.tcx.sess.overflow_checks(); | |
// Perform any special handling for specific Rvalue types. | |
@@ -495,14 +514,10 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { | |
let right_size = r.layout.size; | |
let r_bits = r.to_scalar().and_then(|r| r.to_bits(right_size)); | |
if r_bits.map_or(false, |b| b >= left_bits as u128) { | |
- let lint_root = match &self.source_scopes[source_info.scope].local_data { | |
- ClearCrossCrate::Set(data) => data.lint_root, | |
- ClearCrossCrate::Clear => return None, | |
- }; | |
let dir = if *op == BinOp::Shr { "right" } else { "left" }; | |
self.tcx.lint_hir( | |
::rustc::lint::builtin::EXCEEDING_BITSHIFTS, | |
- lint_root, | |
+ self.lint_root?, | |
span, | |
&format!("attempt to shift {} with overflow", dir), | |
); | |
@@ -659,7 +674,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { | |
ScalarMaybeUndef::Scalar(r), | |
)) => l.is_bits() && r.is_bits(), | |
interpret::Operand::Indirect(_) if mir_opt_level >= 2 => { | |
- intern_const_alloc_recursive(&mut self.ecx, None, op.assert_mem_place()) | |
+ intern_const_alloc_recursive(&mut self.ecx, None, op.assert_mem_place(), false) | |
.expect("failed to intern alloc"); | |
true | |
} | |
@@ -753,6 +768,10 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { | |
fn visit_statement(&mut self, statement: &mut Statement<'tcx>, location: Location) { | |
trace!("visit_statement: {:?}", statement); | |
+ self.lint_root = match &self.source_scopes[statement.source_info.scope].local_data { | |
+ ClearCrossCrate::Set(data) => Some(data.lint_root), | |
+ ClearCrossCrate::Clear => None, | |
+ }; | |
if let StatementKind::Assign(box (ref place, ref mut rval)) = statement.kind { | |
let place_ty: Ty<'tcx> = place.ty(&self.local_decls, self.tcx).ty; | |
if let Ok(place_layout) = self.tcx.layout_of(self.param_env.and(place_ty)) { | |
@@ -804,6 +823,10 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { | |
fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>, location: Location) { | |
self.super_terminator(terminator, location); | |
let source_info = terminator.source_info; | |
+ self.lint_root = match &self.source_scopes[source_info.scope].local_data { | |
+ ClearCrossCrate::Set(data) => Some(data.lint_root), | |
+ ClearCrossCrate::Clear => None, | |
+ }; | |
match &mut terminator.kind { | |
TerminatorKind::Assert { expected, ref msg, ref mut cond, .. } => { | |
if let Some(value) = self.eval_operand(&cond, source_info) { | |
diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs | |
index b52231e55f9..d121ff108d9 100644 | |
--- a/src/librustc_mir/transform/promote_consts.rs | |
+++ b/src/librustc_mir/transform/promote_consts.rs | |
@@ -27,7 +27,7 @@ use rustc_index::vec::{Idx, IndexVec}; | |
use rustc_target::spec::abi::Abi; | |
use std::cell::Cell; | |
-use std::{iter, mem, usize}; | |
+use std::{cmp, iter, mem, usize}; | |
use crate::transform::check_consts::{is_lang_panic_fn, qualifs, ConstKind, Item}; | |
use crate::transform::{MirPass, MirSource}; | |
@@ -760,6 +760,7 @@ struct Promoter<'a, 'tcx> { | |
source: &'a mut BodyAndCache<'tcx>, | |
promoted: BodyAndCache<'tcx>, | |
temps: &'a mut IndexVec<Local, TempState>, | |
+ extra_statements: &'a mut Vec<(Location, Statement<'tcx>)>, | |
/// If true, all nested temps are also kept in the | |
/// source MIR, not moved to the promoted MIR. | |
@@ -902,7 +903,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { | |
candidate: Candidate, | |
next_promoted_id: usize, | |
) -> Option<BodyAndCache<'tcx>> { | |
- let mut operand = { | |
+ let mut rvalue = { | |
let promoted = &mut self.promoted; | |
let promoted_id = Promoted::new(next_promoted_id); | |
let tcx = self.tcx; | |
@@ -926,15 +927,70 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { | |
Candidate::Ref(loc) => { | |
let ref mut statement = blocks[loc.block].statements[loc.statement_index]; | |
match statement.kind { | |
- StatementKind::Assign(box (_, Rvalue::Ref(_, _, ref mut place))) => { | |
+ StatementKind::Assign(box ( | |
+ _, | |
+ Rvalue::Ref(ref mut region, borrow_kind, ref mut place), | |
+ )) => { | |
// Use the underlying local for this (necessarily interior) borrow. | |
let ty = place.base.ty(local_decls).ty; | |
let span = statement.source_info.span; | |
- Operand::Move(Place { | |
- base: mem::replace(&mut place.base, promoted_place(ty, span).base), | |
- projection: List::empty(), | |
- }) | |
+ let ref_ty = tcx.mk_ref( | |
+ tcx.lifetimes.re_static, | |
+ ty::TypeAndMut { ty, mutbl: borrow_kind.to_mutbl_lossy() }, | |
+ ); | |
+ | |
+ promoted.span = span; | |
+ promoted.local_decls[RETURN_PLACE] = | |
+ LocalDecl::new_return_place(ref_ty, span); | |
+ | |
+ *region = tcx.lifetimes.re_static; | |
+ | |
+ let mut projection = vec![PlaceElem::Deref]; | |
+ projection.extend(place.projection); | |
+ place.projection = tcx.intern_place_elems(&projection); | |
+ | |
+ // Create a temp to hold the promoted reference. | |
+ // This is because `*r` requires `r` to be a local, | |
+ // otherwise we would use the `promoted` directly. | |
+ let mut promoted_ref = LocalDecl::new_temp(ref_ty, span); | |
+ promoted_ref.source_info = statement.source_info; | |
+ let promoted_ref = local_decls.push(promoted_ref); | |
+ assert_eq!(self.temps.push(TempState::Unpromotable), promoted_ref); | |
+ | |
+ let promoted_ref_rvalue = | |
+ Rvalue::Use(Operand::Constant(Box::new(Constant { | |
+ span, | |
+ user_ty: None, | |
+ literal: tcx.mk_const(ty::Const { | |
+ ty: ref_ty, | |
+ val: ty::ConstKind::Unevaluated( | |
+ def_id, | |
+ InternalSubsts::identity_for_item(tcx, def_id), | |
+ Some(promoted_id), | |
+ ), | |
+ }), | |
+ }))); | |
+ let promoted_ref_statement = Statement { | |
+ source_info: statement.source_info, | |
+ kind: StatementKind::Assign(Box::new(( | |
+ Place::from(promoted_ref), | |
+ promoted_ref_rvalue, | |
+ ))), | |
+ }; | |
+ self.extra_statements.push((loc, promoted_ref_statement)); | |
+ | |
+ Rvalue::Ref( | |
+ tcx.lifetimes.re_static, | |
+ borrow_kind, | |
+ Place { | |
+ base: mem::replace( | |
+ &mut place.base, | |
+ PlaceBase::Local(promoted_ref), | |
+ ), | |
+ projection: List::empty(), | |
+ }, | |
+ ) | |
} | |
_ => bug!(), | |
} | |
@@ -945,7 +1001,10 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { | |
StatementKind::Assign(box (_, Rvalue::Repeat(ref mut operand, _))) => { | |
let ty = operand.ty(local_decls, self.tcx); | |
let span = statement.source_info.span; | |
- mem::replace(operand, Operand::Copy(promoted_place(ty, span))) | |
+ Rvalue::Use(mem::replace( | |
+ operand, | |
+ Operand::Copy(promoted_place(ty, span)), | |
+ )) | |
} | |
_ => bug!(), | |
} | |
@@ -957,7 +1016,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { | |
let ty = args[index].ty(local_decls, self.tcx); | |
let span = terminator.source_info.span; | |
let operand = Operand::Copy(promoted_place(ty, span)); | |
- mem::replace(&mut args[index], operand) | |
+ Rvalue::Use(mem::replace(&mut args[index], operand)) | |
} | |
// We expected a `TerminatorKind::Call` for which we'd like to promote an | |
// argument. `qualify_consts` saw a `TerminatorKind::Call` here, but | |
@@ -974,13 +1033,13 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { | |
}; | |
assert_eq!(self.new_block(), START_BLOCK); | |
- self.visit_operand( | |
- &mut operand, | |
+ self.visit_rvalue( | |
+ &mut rvalue, | |
Location { block: BasicBlock::new(0), statement_index: usize::MAX }, | |
); | |
let span = self.promoted.span; | |
- self.assign(RETURN_PLACE, Rvalue::Use(operand), span); | |
+ self.assign(RETURN_PLACE, rvalue, span); | |
Some(self.promoted) | |
} | |
} | |
@@ -1019,6 +1078,7 @@ pub fn promote_candidates<'tcx>( | |
let mut promotions = IndexVec::new(); | |
+ let mut extra_statements = vec![]; | |
for candidate in candidates.into_iter().rev() { | |
match candidate { | |
Candidate::Repeat(Location { block, statement_index }) | |
@@ -1042,23 +1102,27 @@ pub fn promote_candidates<'tcx>( | |
let initial_locals = | |
iter::once(LocalDecl::new_return_place(tcx.types.never, body.span)).collect(); | |
+ let mut promoted = Body::new( | |
+ IndexVec::new(), | |
+ // FIXME: maybe try to filter this to avoid blowing up | |
+ // memory usage? | |
+ body.source_scopes.clone(), | |
+ initial_locals, | |
+ IndexVec::new(), | |
+ 0, | |
+ vec![], | |
+ body.span, | |
+ vec![], | |
+ body.generator_kind, | |
+ ); | |
+ promoted.ignore_interior_mut_in_const_validation = true; | |
+ | |
let promoter = Promoter { | |
- promoted: BodyAndCache::new(Body::new( | |
- IndexVec::new(), | |
- // FIXME: maybe try to filter this to avoid blowing up | |
- // memory usage? | |
- body.source_scopes.clone(), | |
- initial_locals, | |
- IndexVec::new(), | |
- 0, | |
- vec![], | |
- body.span, | |
- vec![], | |
- body.generator_kind, | |
- )), | |
+ promoted: BodyAndCache::new(promoted), | |
tcx, | |
source: body, | |
temps: &mut temps, | |
+ extra_statements: &mut extra_statements, | |
keep_original: false, | |
}; | |
@@ -1068,6 +1132,13 @@ pub fn promote_candidates<'tcx>( | |
} | |
} | |
+ // Insert each of `extra_statements` before its indicated location, which | |
+ // has to be done in reverse location order, to not invalidate the rest. | |
+ extra_statements.sort_by_key(|&(loc, _)| cmp::Reverse(loc)); | |
+ for (loc, statement) in extra_statements { | |
+ body[loc.block].statements.insert(loc.statement_index, statement); | |
+ } | |
+ | |
// Eliminate assignments to, and drops of promoted temps. | |
let promoted = |index: Local| temps[index] == TempState::PromotedOut; | |
for block in body.basic_blocks_mut() { | |
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs | |
index 8e0f5d17b9f..2912a02139e 100644 | |
--- a/src/librustc_typeck/astconv.rs | |
+++ b/src/librustc_typeck/astconv.rs | |
@@ -2678,7 +2678,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { | |
let def_id = tcx.hir().local_def_id(ast_const.hir_id); | |
let mut const_ = ty::Const { | |
- val: ty::ConstKind::Unevaluated(def_id, InternalSubsts::identity_for_item(tcx, def_id)), | |
+ val: ty::ConstKind::Unevaluated( | |
+ def_id, | |
+ InternalSubsts::identity_for_item(tcx, def_id), | |
+ None, | |
+ ), | |
ty, | |
}; | |
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs | |
index e52afe501c3..1e26076bdf7 100644 | |
--- a/src/librustdoc/clean/utils.rs | |
+++ b/src/librustdoc/clean/utils.rs | |
@@ -460,12 +460,16 @@ pub fn name_from_pat(p: &hir::Pat) -> String { | |
pub fn print_const(cx: &DocContext<'_>, n: &ty::Const<'_>) -> String { | |
match n.val { | |
- ty::ConstKind::Unevaluated(def_id, _) => { | |
- if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(def_id) { | |
+ ty::ConstKind::Unevaluated(def_id, _, promoted) => { | |
+ let mut s = if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(def_id) { | |
print_const_expr(cx, cx.tcx.hir().body_owned_by(hir_id)) | |
} else { | |
inline::print_inlined_const(cx, def_id) | |
+ }; | |
+ if let Some(promoted) = promoted { | |
+ s.push_str(&format!("{:?}", promoted)) | |
} | |
+ s | |
} | |
_ => { | |
let mut s = n.to_string(); | |
diff --git a/src/test/codegen/consts.rs b/src/test/codegen/consts.rs | |
index 7d65ad1435e..a5478a03791 100644 | |
--- a/src/test/codegen/consts.rs | |
+++ b/src/test/codegen/consts.rs | |
@@ -14,7 +14,7 @@ | |
// This checks the constants from {low,high}_align_const, they share the same | |
// constant, but the alignment differs, so the higher one should be used | |
-// CHECK: [[LOW_HIGH:@[0-9]+]] = {{.*}}, align 4 | |
+// CHECK: [[LOW_HIGH:@[0-9]+]] = {{.*}} getelementptr inbounds (<{ [8 x i8] }>, <{ [8 x i8] }>* @2, i32 0, i32 0, i32 0), {{.*}}, align 8 | |
#[derive(Copy, Clone)] | |
@@ -44,7 +44,7 @@ pub fn inline_enum_const() -> E<i8, i16> { | |
#[no_mangle] | |
pub fn low_align_const() -> E<i16, [i16; 3]> { | |
// Check that low_align_const and high_align_const use the same constant | |
-// CHECK: i8* align 2 getelementptr inbounds (<{ [8 x i8] }>, <{ [8 x i8] }>* [[LOW_HIGH]], i32 0, i32 0, i32 0), | |
+// CHECK: load %"E<i16, [i16; 3]>"*, %"E<i16, [i16; 3]>"** bitcast (<{ i8*, [0 x i8] }>* [[LOW_HIGH]] to %"E<i16, [i16; 3]>"**), align 8 | |
*&E::A(0) | |
} | |
@@ -52,6 +52,6 @@ pub fn low_align_const() -> E<i16, [i16; 3]> { | |
#[no_mangle] | |
pub fn high_align_const() -> E<i16, i32> { | |
// Check that low_align_const and high_align_const use the same constant | |
-// CHECK: i8* align 4 getelementptr inbounds (<{ [8 x i8] }>, <{ [8 x i8] }>* [[LOW_HIGH]], i32 0, i32 0, i32 0), | |
+// CHECK: load %"E<i16, i32>"*, %"E<i16, i32>"** bitcast (<{ i8*, [0 x i8] }>* [[LOW_HIGH]] to %"E<i16, i32>"**), align 8 | |
*&E::A(0) | |
} | |
diff --git a/src/test/mir-opt/const_prop/ref_deref.rs b/src/test/mir-opt/const_prop/ref_deref.rs | |
index d45ffdc8775..6b5101af5fc 100644 | |
--- a/src/test/mir-opt/const_prop/ref_deref.rs | |
+++ b/src/test/mir-opt/const_prop/ref_deref.rs | |
@@ -6,7 +6,8 @@ fn main() { | |
// START rustc.main.ConstProp.before.mir | |
// bb0: { | |
// ... | |
-// _2 = &(promoted[0]: i32); | |
+// _4 = const main::promoted[0]; | |
+// _2 = _4; | |
// _1 = (*_2); | |
// ... | |
//} | |
@@ -14,7 +15,8 @@ fn main() { | |
// START rustc.main.ConstProp.after.mir | |
// bb0: { | |
// ... | |
-// _2 = &(promoted[0]: i32); | |
+// _4 = const main::promoted[0]; | |
+// _2 = _4; | |
// _1 = const 4i32; | |
// ... | |
// } | |
diff --git a/src/test/mir-opt/const_prop/slice_len.rs b/src/test/mir-opt/const_prop/slice_len.rs | |
index d6ff76b34b9..43813e43d36 100644 | |
--- a/src/test/mir-opt/const_prop/slice_len.rs | |
+++ b/src/test/mir-opt/const_prop/slice_len.rs | |
@@ -6,7 +6,8 @@ fn main() { | |
// START rustc.main.ConstProp.before.mir | |
// bb0: { | |
// ... | |
-// _4 = &(promoted[0]: [u32; 3]); | |
+// _9 = const main::promoted[0]; | |
+// _4 = _9; | |
// _3 = _4; | |
// _2 = move _3 as &[u32] (Pointer(Unsize)); | |
// ... | |
@@ -24,7 +25,8 @@ fn main() { | |
// START rustc.main.ConstProp.after.mir | |
// bb0: { | |
// ... | |
-// _4 = &(promoted[0]: [u32; 3]); | |
+// _9 = const main::promoted[0]; | |
+// _4 = _9; | |
// _3 = _4; | |
// _2 = move _3 as &[u32] (Pointer(Unsize)); | |
// ... | |
diff --git a/src/test/mir-opt/inline/inline-retag.rs b/src/test/mir-opt/inline/inline-retag.rs | |
index 6cdbcfdb0ad..7b78fc339f2 100644 | |
--- a/src/test/mir-opt/inline/inline-retag.rs | |
+++ b/src/test/mir-opt/inline/inline-retag.rs | |
@@ -25,11 +25,11 @@ fn foo(x: &i32, y: &i32) -> bool { | |
// ... | |
// Retag(_3); | |
// Retag(_6); | |
-// StorageLive(_9); | |
-// _9 = (*_3); | |
-// StorageLive(_10); | |
-// _10 = (*_6); | |
-// _0 = Eq(move _9, move _10); | |
+// StorageLive(_11); | |
+// _11 = (*_3); | |
+// StorageLive(_12); | |
+// _12 = (*_6); | |
+// _0 = Eq(move _11, move _12); | |
// ... | |
// return; | |
// } | |
diff --git a/src/test/mir-opt/match_false_edges.rs b/src/test/mir-opt/match_false_edges.rs | |
index 648856b5523..2c20c35e4a4 100644 | |
--- a/src/test/mir-opt/match_false_edges.rs | |
+++ b/src/test/mir-opt/match_false_edges.rs | |
@@ -65,7 +65,8 @@ fn main() { | |
// } | |
// bb6: { // binding1 and guard | |
// StorageLive(_6); | |
-// _6 = &(((promoted[0]: std::option::Option<i32>) as Some).0: i32); | |
+// _11 = const full_tested_match::promoted[0]; | |
+// _6 = &(((*_11) as Some).0: i32); | |
// _4 = &shallow _2; | |
// StorageLive(_7); | |
// _7 = const guard() -> [return: bb7, unwind: bb1]; | |
diff --git a/src/test/ui/consts/array-literal-index-oob.rs b/src/test/ui/consts/array-literal-index-oob.rs | |
index 1de6bafd293..af7df5f1ff6 100644 | |
--- a/src/test/ui/consts/array-literal-index-oob.rs | |
+++ b/src/test/ui/consts/array-literal-index-oob.rs | |
@@ -4,4 +4,5 @@ fn main() { | |
&{[1, 2, 3][4]}; | |
//~^ ERROR index out of bounds | |
//~| ERROR reaching this expression at runtime will panic or abort | |
+ //~| ERROR erroneous constant used [const_err] | |
} | |
diff --git a/src/test/ui/consts/array-literal-index-oob.stderr b/src/test/ui/consts/array-literal-index-oob.stderr | |
index f3ef16659dd..8f5de704f6e 100644 | |
--- a/src/test/ui/consts/array-literal-index-oob.stderr | |
+++ b/src/test/ui/consts/array-literal-index-oob.stderr | |
@@ -14,5 +14,11 @@ LL | &{[1, 2, 3][4]}; | |
| | | |
| indexing out of bounds: the len is 3 but the index is 4 | |
-error: aborting due to 2 previous errors | |
+error: erroneous constant used | |
+ --> $DIR/array-literal-index-oob.rs:4:5 | |
+ | | |
+LL | &{[1, 2, 3][4]}; | |
+ | ^^^^^^^^^^^^^^^ referenced constant has errors | |
+ | |
+error: aborting due to 3 previous errors | |
diff --git a/src/test/ui/consts/const-eval/conditional_array_execution.rs b/src/test/ui/consts/const-eval/conditional_array_execution.rs | |
index 96f67c92a5e..2058d2e2184 100644 | |
--- a/src/test/ui/consts/const-eval/conditional_array_execution.rs | |
+++ b/src/test/ui/consts/const-eval/conditional_array_execution.rs | |
@@ -10,4 +10,5 @@ const FOO: u32 = [X - Y, Y - X][(X < Y) as usize]; | |
fn main() { | |
println!("{}", FOO); | |
//~^ ERROR | |
+ //~| WARN erroneous constant used [const_err] | |
} | |
diff --git a/src/test/ui/consts/const-eval/conditional_array_execution.stderr b/src/test/ui/consts/const-eval/conditional_array_execution.stderr | |
index ec18f8f011d..b5f5f84cf38 100644 | |
--- a/src/test/ui/consts/const-eval/conditional_array_execution.stderr | |
+++ b/src/test/ui/consts/const-eval/conditional_array_execution.stderr | |
@@ -18,6 +18,12 @@ error[E0080]: evaluation of constant expression failed | |
LL | println!("{}", FOO); | |
| ^^^ referenced constant has errors | |
+warning: erroneous constant used | |
+ --> $DIR/conditional_array_execution.rs:11:20 | |
+ | | |
+LL | println!("{}", FOO); | |
+ | ^^^ referenced constant has errors | |
+ | |
error: aborting due to previous error | |
For more information about this error, try `rustc --explain E0080`. | |
diff --git a/src/test/ui/consts/const-eval/issue-43197.rs b/src/test/ui/consts/const-eval/issue-43197.rs | |
index 849c81ad449..04de6b11718 100644 | |
--- a/src/test/ui/consts/const-eval/issue-43197.rs | |
+++ b/src/test/ui/consts/const-eval/issue-43197.rs | |
@@ -14,4 +14,6 @@ fn main() { | |
println!("{} {}", X, Y); | |
//~^ ERROR evaluation of constant expression failed | |
//~| ERROR evaluation of constant expression failed | |
+ //~| WARN erroneous constant used [const_err] | |
+ //~| WARN erroneous constant used [const_err] | |
} | |
diff --git a/src/test/ui/consts/const-eval/issue-43197.stderr b/src/test/ui/consts/const-eval/issue-43197.stderr | |
index a1b3a05ed41..ccbb51edf17 100644 | |
--- a/src/test/ui/consts/const-eval/issue-43197.stderr | |
+++ b/src/test/ui/consts/const-eval/issue-43197.stderr | |
@@ -26,12 +26,24 @@ error[E0080]: evaluation of constant expression failed | |
LL | println!("{} {}", X, Y); | |
| ^ referenced constant has errors | |
+warning: erroneous constant used | |
+ --> $DIR/issue-43197.rs:14:23 | |
+ | | |
+LL | println!("{} {}", X, Y); | |
+ | ^ referenced constant has errors | |
+ | |
error[E0080]: evaluation of constant expression failed | |
--> $DIR/issue-43197.rs:14:26 | |
| | |
LL | println!("{} {}", X, Y); | |
| ^ referenced constant has errors | |
+warning: erroneous constant used | |
+ --> $DIR/issue-43197.rs:14:26 | |
+ | | |
+LL | println!("{} {}", X, Y); | |
+ | ^ referenced constant has errors | |
+ | |
error: aborting due to 2 previous errors | |
For more information about this error, try `rustc --explain E0080`. | |
diff --git a/src/test/ui/consts/const-eval/issue-50814.rs b/src/test/ui/consts/const-eval/issue-50814.rs | |
index e589126a942..5c3635e4650 100644 | |
--- a/src/test/ui/consts/const-eval/issue-50814.rs | |
+++ b/src/test/ui/consts/const-eval/issue-50814.rs | |
@@ -12,11 +12,13 @@ impl Unsigned for U8 { | |
struct Sum<A,B>(A,B); | |
impl<A: Unsigned, B: Unsigned> Unsigned for Sum<A,B> { | |
- const MAX: u8 = A::MAX + B::MAX; //~ ERROR any use of this value will cause an error | |
+ const MAX: u8 = A::MAX + B::MAX; | |
+ //~^ ERROR any use of this value will cause an error [const_err] | |
} | |
fn foo<T>(_: T) -> &'static u8 { | |
- &Sum::<U8,U8>::MAX //~ ERROR E0080 | |
+ &Sum::<U8,U8>::MAX | |
+ //~^ ERROR E0080 | |
} | |
fn main() { | |
diff --git a/src/test/ui/consts/const-eval/issue-50814.stderr b/src/test/ui/consts/const-eval/issue-50814.stderr | |
index f8b017e4b53..2e5167a99a2 100644 | |
--- a/src/test/ui/consts/const-eval/issue-50814.stderr | |
+++ b/src/test/ui/consts/const-eval/issue-50814.stderr | |
@@ -9,7 +9,7 @@ LL | const MAX: u8 = A::MAX + B::MAX; | |
= note: `#[deny(const_err)]` on by default | |
error[E0080]: evaluation of constant expression failed | |
- --> $DIR/issue-50814.rs:19:5 | |
+ --> $DIR/issue-50814.rs:20:5 | |
| | |
LL | &Sum::<U8,U8>::MAX | |
| ^----------------- | |
diff --git a/src/test/ui/consts/const-eval/promoted_errors.rs b/src/test/ui/consts/const-eval/promoted_errors.rs | |
index 2eed8ca7d32..c055541d6e4 100644 | |
--- a/src/test/ui/consts/const-eval/promoted_errors.rs | |
+++ b/src/test/ui/consts/const-eval/promoted_errors.rs | |
@@ -10,11 +10,13 @@ fn main() { | |
println!("{}", 1/(1-1)); | |
//~^ ERROR attempt to divide by zero [const_err] | |
//~| ERROR const_err | |
+ //~| ERROR erroneous constant used [const_err] | |
let _x = 1/(1-1); | |
//~^ ERROR const_err | |
println!("{}", 1/(false as u32)); | |
//~^ ERROR attempt to divide by zero [const_err] | |
//~| ERROR const_err | |
+ //~| ERROR erroneous constant used [const_err] | |
let _x = 1/(false as u32); | |
//~^ ERROR const_err | |
} | |
diff --git a/src/test/ui/consts/const-eval/promoted_errors.stderr b/src/test/ui/consts/const-eval/promoted_errors.stderr | |
index 8f17ef05f23..63e4a130ad4 100644 | |
--- a/src/test/ui/consts/const-eval/promoted_errors.stderr | |
+++ b/src/test/ui/consts/const-eval/promoted_errors.stderr | |
@@ -22,29 +22,41 @@ error: reaching this expression at runtime will panic or abort | |
LL | println!("{}", 1/(1-1)); | |
| ^^^^^^^ dividing by zero | |
+error: erroneous constant used | |
+ --> $DIR/promoted_errors.rs:10:20 | |
+ | | |
+LL | println!("{}", 1/(1-1)); | |
+ | ^^^^^^^ referenced constant has errors | |
+ | |
error: attempt to divide by zero | |
- --> $DIR/promoted_errors.rs:13:14 | |
+ --> $DIR/promoted_errors.rs:14:14 | |
| | |
LL | let _x = 1/(1-1); | |
| ^^^^^^^ | |
error: attempt to divide by zero | |
- --> $DIR/promoted_errors.rs:15:20 | |
+ --> $DIR/promoted_errors.rs:16:20 | |
| | |
LL | println!("{}", 1/(false as u32)); | |
| ^^^^^^^^^^^^^^^^ | |
error: reaching this expression at runtime will panic or abort | |
- --> $DIR/promoted_errors.rs:15:20 | |
+ --> $DIR/promoted_errors.rs:16:20 | |
| | |
LL | println!("{}", 1/(false as u32)); | |
| ^^^^^^^^^^^^^^^^ dividing by zero | |
+error: erroneous constant used | |
+ --> $DIR/promoted_errors.rs:16:20 | |
+ | | |
+LL | println!("{}", 1/(false as u32)); | |
+ | ^^^^^^^^^^^^^^^^ referenced constant has errors | |
+ | |
error: attempt to divide by zero | |
- --> $DIR/promoted_errors.rs:18:14 | |
+ --> $DIR/promoted_errors.rs:20:14 | |
| | |
LL | let _x = 1/(false as u32); | |
| ^^^^^^^^^^^^^^^^ | |
-error: aborting due to 7 previous errors | |
+error: aborting due to 9 previous errors | |
diff --git a/src/test/ui/consts/const-eval/promoted_errors2.rs b/src/test/ui/consts/const-eval/promoted_errors2.rs | |
index ae680b4f107..7272e7898d0 100644 | |
--- a/src/test/ui/consts/const-eval/promoted_errors2.rs | |
+++ b/src/test/ui/consts/const-eval/promoted_errors2.rs | |
@@ -11,11 +11,13 @@ fn main() { | |
println!("{}", 1/(1-1)); | |
//~^ ERROR attempt to divide by zero [const_err] | |
//~| ERROR const_err | |
+ //~| ERROR erroneous constant used [const_err] | |
let _x = 1/(1-1); | |
//~^ ERROR const_err | |
println!("{}", 1/(false as u32)); | |
//~^ ERROR attempt to divide by zero [const_err] | |
//~| ERROR const_err | |
+ //~| ERROR erroneous constant used [const_err] | |
let _x = 1/(false as u32); | |
//~^ ERROR const_err | |
} | |
diff --git a/src/test/ui/consts/const-eval/promoted_errors2.stderr b/src/test/ui/consts/const-eval/promoted_errors2.stderr | |
index 60a3cba6e1f..607a6ff8cf1 100644 | |
--- a/src/test/ui/consts/const-eval/promoted_errors2.stderr | |
+++ b/src/test/ui/consts/const-eval/promoted_errors2.stderr | |
@@ -28,29 +28,41 @@ error: reaching this expression at runtime will panic or abort | |
LL | println!("{}", 1/(1-1)); | |
| ^^^^^^^ dividing by zero | |
+error: erroneous constant used | |
+ --> $DIR/promoted_errors2.rs:11:20 | |
+ | | |
+LL | println!("{}", 1/(1-1)); | |
+ | ^^^^^^^ referenced constant has errors | |
+ | |
error: attempt to divide by zero | |
- --> $DIR/promoted_errors2.rs:14:14 | |
+ --> $DIR/promoted_errors2.rs:15:14 | |
| | |
LL | let _x = 1/(1-1); | |
| ^^^^^^^ | |
error: attempt to divide by zero | |
- --> $DIR/promoted_errors2.rs:16:20 | |
+ --> $DIR/promoted_errors2.rs:17:20 | |
| | |
LL | println!("{}", 1/(false as u32)); | |
| ^^^^^^^^^^^^^^^^ | |
error: reaching this expression at runtime will panic or abort | |
- --> $DIR/promoted_errors2.rs:16:20 | |
+ --> $DIR/promoted_errors2.rs:17:20 | |
| | |
LL | println!("{}", 1/(false as u32)); | |
| ^^^^^^^^^^^^^^^^ dividing by zero | |
+error: erroneous constant used | |
+ --> $DIR/promoted_errors2.rs:17:20 | |
+ | | |
+LL | println!("{}", 1/(false as u32)); | |
+ | ^^^^^^^^^^^^^^^^ referenced constant has errors | |
+ | |
error: attempt to divide by zero | |
- --> $DIR/promoted_errors2.rs:19:14 | |
+ --> $DIR/promoted_errors2.rs:21:14 | |
| | |
LL | let _x = 1/(false as u32); | |
| ^^^^^^^^^^^^^^^^ | |
-error: aborting due to 8 previous errors | |
+error: aborting due to 10 previous errors | |
diff --git a/src/test/ui/consts/const-eval/ub-nonnull.stderr b/src/test/ui/consts/const-eval/ub-nonnull.stderr | |
index 80d80a98675..c2446d14040 100644 | |
--- a/src/test/ui/consts/const-eval/ub-nonnull.stderr | |
+++ b/src/test/ui/consts/const-eval/ub-nonnull.stderr | |
@@ -13,7 +13,7 @@ LL | / const OUT_OF_BOUNDS_PTR: NonNull<u8> = { unsafe { | |
LL | | let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle | |
LL | | // Use address-of-element for pointer arithmetic. This could wrap around to NULL! | |
LL | | let out_of_bounds_ptr = &ptr[255]; | |
- | | ^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of allocation 6 which has size 1 | |
+ | | ^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of allocation 8 which has size 1 | |
LL | | mem::transmute(out_of_bounds_ptr) | |
LL | | } }; | |
| |____- | |
diff --git a/src/test/ui/consts/miri_unleashed/non_const_fn.rs b/src/test/ui/consts/miri_unleashed/non_const_fn.rs | |
index 32a713ebaa4..cfb57d21cee 100644 | |
--- a/src/test/ui/consts/miri_unleashed/non_const_fn.rs | |
+++ b/src/test/ui/consts/miri_unleashed/non_const_fn.rs | |
@@ -11,5 +11,7 @@ const C: () = foo(); //~ WARN: skipping const checks | |
//~^ WARN any use of this value will cause an error | |
fn main() { | |
- println!("{:?}", C); //~ ERROR: evaluation of constant expression failed | |
+ println!("{:?}", C); | |
+ //~^ ERROR: evaluation of constant expression failed | |
+ //~| WARN: erroneous constant used [const_err] | |
} | |
diff --git a/src/test/ui/consts/miri_unleashed/non_const_fn.stderr b/src/test/ui/consts/miri_unleashed/non_const_fn.stderr | |
index 75f532a81bd..6a7df858feb 100644 | |
--- a/src/test/ui/consts/miri_unleashed/non_const_fn.stderr | |
+++ b/src/test/ui/consts/miri_unleashed/non_const_fn.stderr | |
@@ -24,6 +24,12 @@ error[E0080]: evaluation of constant expression failed | |
LL | println!("{:?}", C); | |
| ^ referenced constant has errors | |
+warning: erroneous constant used | |
+ --> $DIR/non_const_fn.rs:14:22 | |
+ | | |
+LL | println!("{:?}", C); | |
+ | ^ referenced constant has errors | |
+ | |
error: aborting due to previous error | |
For more information about this error, try `rustc --explain E0080`. | |
diff --git a/src/test/ui/consts/zst_no_llvm_alloc.rs b/src/test/ui/consts/zst_no_llvm_alloc.rs | |
index 5d779355400..2a41f708c2b 100644 | |
--- a/src/test/ui/consts/zst_no_llvm_alloc.rs | |
+++ b/src/test/ui/consts/zst_no_llvm_alloc.rs | |
@@ -7,13 +7,15 @@ static FOO: Foo = Foo; | |
fn main() { | |
let x: &'static () = &(); | |
- assert_eq!(x as *const () as usize, 1); | |
+ assert_ne!(x as *const () as usize, 1); | |
let x: &'static Foo = &Foo; | |
- assert_eq!(x as *const Foo as usize, 4); | |
+ assert_ne!(x as *const Foo as usize, 4); | |
// statics must have a unique address | |
assert_ne!(&FOO as *const Foo as usize, 4); | |
- assert_eq!(<Vec<i32>>::new().as_ptr(), <&[i32]>::default().as_ptr()); | |
- assert_eq!(<Box<[i32]>>::default().as_ptr(), (&[]).as_ptr()); | |
+ // FIXME this two tests should be assert_eq! | |
+ // this stopped working since we are promoting to constants instead of statics | |
+ assert_ne!(<Vec<i32>>::new().as_ptr(), <&[i32]>::default().as_ptr()); | |
+ assert_ne!(<Box<[i32]>>::default().as_ptr(), (&[]).as_ptr()); | |
} | |
diff --git a/src/test/ui/invalid_const_promotion.rs b/src/test/ui/invalid_const_promotion.rs | |
deleted file mode 100644 | |
index 5d7664cefb3..00000000000 | |
--- a/src/test/ui/invalid_const_promotion.rs | |
+++ /dev/null | |
@@ -1,61 +0,0 @@ | |
-// run-pass | |
- | |
-#![allow(unused_mut)] | |
-// ignore-wasm32 | |
-// ignore-emscripten | |
-// ignore-sgx no processes | |
- | |
-// compile-flags: -C debug_assertions=yes | |
- | |
-#![stable(feature = "rustc", since = "1.0.0")] | |
-#![feature(const_fn, rustc_private, staged_api, rustc_attrs)] | |
-#![allow(const_err)] | |
- | |
-extern crate libc; | |
- | |
-use std::env; | |
-use std::process::{Command, Stdio}; | |
- | |
-// this will panic in debug mode and overflow in release mode | |
-// | |
-// NB we give bar an unused argument because otherwise memoization | |
-// of the const fn kicks in, causing a different code path in the | |
-// compiler to be executed (see PR #66294). | |
-#[stable(feature = "rustc", since = "1.0.0")] | |
-#[rustc_const_stable(feature = "rustc", since = "1.0.0")] | |
-#[rustc_promotable] | |
-const fn bar(_: bool) -> usize { 0 - 1 } | |
- | |
-fn foo() { | |
- let _: &'static _ = &bar(true); | |
-} | |
- | |
-#[cfg(unix)] | |
-fn check_status(status: std::process::ExitStatus) | |
-{ | |
- use std::os::unix::process::ExitStatusExt; | |
- | |
- assert!(status.signal() == Some(libc::SIGILL) | |
- || status.signal() == Some(libc::SIGTRAP) | |
- || status.signal() == Some(libc::SIGABRT)); | |
-} | |
- | |
-#[cfg(not(unix))] | |
-fn check_status(status: std::process::ExitStatus) | |
-{ | |
- assert!(!status.success()); | |
-} | |
- | |
-fn main() { | |
- let args: Vec<String> = env::args().collect(); | |
- if args.len() > 1 && args[1] == "test" { | |
- foo(); | |
- return; | |
- } | |
- | |
- let mut p = Command::new(&args[0]) | |
- .stdout(Stdio::piped()) | |
- .stdin(Stdio::piped()) | |
- .arg("test").output().unwrap(); | |
- check_status(p.status); | |
-} | |
diff --git a/src/test/ui/symbol-names/impl1.legacy.stderr b/src/test/ui/symbol-names/impl1.legacy.stderr | |
index 53ab2f9878f..affb5537b18 100644 | |
--- a/src/test/ui/symbol-names/impl1.legacy.stderr | |
+++ b/src/test/ui/symbol-names/impl1.legacy.stderr | |
@@ -46,13 +46,13 @@ error: def-path(bar::<impl foo::Foo>::baz) | |
LL | #[rustc_def_path] | |
| ^^^^^^^^^^^^^^^^^ | |
-error: symbol-name(_ZN209_$LT$$u5b$$RF$dyn$u20$impl1..Foo$u2b$Assoc$u20$$u3d$$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RF$u8$C$$u20$...$RP$$u2b$impl1..AutoTrait$u3b$$u20$_$u5d$$u20$as$u20$impl1..main..$u7b$$u7b$closure$u7d$$u7d$..Bar$GT$6method17h92c563325b7ff21aE) | |
+error: symbol-name(_ZN209_$LT$$u5b$$RF$dyn$u20$impl1..Foo$u2b$Assoc$u20$$u3d$$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RF$u8$C$$u20$...$RP$$u2b$impl1..AutoTrait$u3b$$u20$_$u5d$$u20$as$u20$impl1..main..$u7b$$u7b$closure$u7d$$u7d$..Bar$GT$6method17hf07584432cd4d8beE) | |
--> $DIR/impl1.rs:62:13 | |
| | |
LL | #[rustc_symbol_name] | |
| ^^^^^^^^^^^^^^^^^^^^ | |
-error: demangling(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; _] as impl1::main::{{closure}}::Bar>::method::h92c563325b7ff21a) | |
+error: demangling(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; _] as impl1::main::{{closure}}::Bar>::method::hf07584432cd4d8be) | |
--> $DIR/impl1.rs:62:13 | |
| | |
LL | #[rustc_symbol_name] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment