Auto merge of #67532 - Centril:rollup-3duj42d, r=Centril
Rollup of 8 pull requests Successful merges: - #66877 (Add simpler entry points to const eval for common usages.) - #67299 (Add `ImmTy::try_from_(u)int` methods) - #67487 (Rustdoc mutability removal) - #67499 (Misc MIR building cleanups) - #67506 (Remove iter_private.rs) - #67508 (Fix typo in path parser name) - #67519 (Document why Any is not an unsafe trait) - #67525 (Utilize rust-lang/rust commit hashes in toolstate) Failed merges: r? @ghost
This commit is contained in:
commit
9b98af84c4
@ -14,12 +14,15 @@ printf 'https://%s:x-oauth-basic@github.com\n' "$TOOLSTATE_REPO_ACCESS_TOKEN" \
|
||||
> "$HOME/.git-credentials"
|
||||
git clone --depth=1 $TOOLSTATE_REPO
|
||||
|
||||
GIT_COMMIT="$(git rev-parse HEAD)"
|
||||
GIT_COMMIT_MSG="$(git log --format=%s -n1 HEAD)"
|
||||
|
||||
cd rust-toolstate
|
||||
FAILURE=1
|
||||
for RETRY_COUNT in 1 2 3 4 5; do
|
||||
# The purpose is to publish the new "current" toolstate in the toolstate repo.
|
||||
"$BUILD_SOURCESDIRECTORY/src/tools/publish_toolstate.py" "$(git rev-parse HEAD)" \
|
||||
"$(git log --format=%s -n1 HEAD)" \
|
||||
"$BUILD_SOURCESDIRECTORY/src/tools/publish_toolstate.py" "$GIT_COMMIT" \
|
||||
"$GIT_COMMIT_MSG" \
|
||||
"$MESSAGE_FILE" \
|
||||
"$TOOLSTATE_REPO_ACCESS_TOKEN"
|
||||
# `git commit` failing means nothing to commit.
|
||||
|
@ -74,6 +74,16 @@
|
||||
/// See the [module-level documentation][mod] for more details.
|
||||
///
|
||||
/// [mod]: index.html
|
||||
// This trait is not unsafe, though we rely on the specifics of it's sole impl's
|
||||
// `type_id` function in unsafe code (e.g., `downcast`). Normally, that would be
|
||||
// a problem, but because the only impl of `Any` is a blanket implementation, no
|
||||
// other code can implement `Any`.
|
||||
//
|
||||
// We could plausibly make this trait unsafe -- it would not cause breakage,
|
||||
// since we control all the implementations -- but we choose not to as that's
|
||||
// both not really necessary and may confuse users about the distinction of
|
||||
// unsafe traits and unsafe methods (i.e., `type_id` would still be safe to call,
|
||||
// but we would likely want to indicate as such in documentation).
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait Any: 'static {
|
||||
/// Gets the `TypeId` of `self`.
|
||||
|
@ -1,17 +0,0 @@
|
||||
/// An iterator whose items are random accessible efficiently
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The iterator's .len() and size_hint() must be exact.
|
||||
/// `.len()` must be cheap to call.
|
||||
///
|
||||
/// .get_unchecked() must return distinct mutable references for distinct
|
||||
/// indices (if applicable), and must return a valid reference if index is in
|
||||
/// 0..self.len().
|
||||
#[doc(hidden)]
|
||||
pub unsafe trait TrustedRandomAccess : ExactSizeIterator {
|
||||
unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item;
|
||||
/// Returns `true` if getting an iterator element may have
|
||||
/// side effects. Remember to take inner iterators into account.
|
||||
fn may_have_side_effect() -> bool;
|
||||
}
|
@ -101,6 +101,7 @@ macro_rules! throw_machine_stop {
|
||||
mod value;
|
||||
mod allocation;
|
||||
mod pointer;
|
||||
mod queries;
|
||||
|
||||
pub use self::error::{
|
||||
InterpErrorInfo, InterpResult, InterpError, AssertMessage, ConstEvalErr, struct_error,
|
||||
@ -116,9 +117,10 @@ macro_rules! throw_machine_stop {
|
||||
|
||||
use crate::mir;
|
||||
use crate::hir::def_id::DefId;
|
||||
use crate::ty::{self, TyCtxt, Instance, subst::GenericArgKind};
|
||||
use crate::ty::{self, TyCtxt, Instance};
|
||||
use crate::ty::codec::TyDecoder;
|
||||
use crate::ty::layout::{self, Size};
|
||||
use crate::ty::subst::GenericArgKind;
|
||||
use std::io;
|
||||
use std::fmt;
|
||||
use std::num::NonZeroU32;
|
||||
|
89
src/librustc/mir/interpret/queries.rs
Normal file
89
src/librustc/mir/interpret/queries.rs
Normal file
@ -0,0 +1,89 @@
|
||||
use super::{ConstEvalResult, ErrorHandled, GlobalId};
|
||||
|
||||
use crate::mir;
|
||||
use crate::hir::def_id::DefId;
|
||||
use crate::ty::{self, TyCtxt};
|
||||
use crate::ty::subst::{InternalSubsts, SubstsRef};
|
||||
use syntax_pos::Span;
|
||||
|
||||
|
||||
impl<'tcx> TyCtxt<'tcx> {
|
||||
|
||||
/// Evaluates a constant without providing any substitutions. This is useful to evaluate consts
|
||||
/// that can't take any generic arguments like statics, const items or enum discriminants. If a
|
||||
/// generic parameter is used within the constant `ErrorHandled::ToGeneric` will be returned.
|
||||
pub fn const_eval_poly(self, def_id: DefId) -> ConstEvalResult<'tcx> {
|
||||
// In some situations def_id will have substitutions within scope, but they aren't allowed
|
||||
// to be used. So we can't use `Instance::mono`, instead we feed unresolved substitutions
|
||||
// into `const_eval` which will return `ErrorHandled::ToGeneric` if any og them are
|
||||
// encountered.
|
||||
let substs = InternalSubsts::identity_for_item(self, def_id);
|
||||
let instance = ty::Instance::new(def_id, substs);
|
||||
let cid = GlobalId {
|
||||
instance,
|
||||
promoted: None,
|
||||
};
|
||||
let param_env = self.param_env(def_id);
|
||||
self.const_eval_validated(param_env.and(cid))
|
||||
}
|
||||
|
||||
/// Resolves and evaluates a constant.
|
||||
///
|
||||
/// The constant can be located on a trait like `<A as B>::C`, in which case the given
|
||||
/// substitutions and environment are used to resolve the constant. Alternatively if the
|
||||
/// constant has generic parameters in scope the substitutions are used to evaluate the value of
|
||||
/// the constant. For example in `fn foo<T>() { let _ = [0; bar::<T>()]; }` the repeat count
|
||||
/// constant `bar::<T>()` requires a substitution for `T`, if the substitution for `T` is still
|
||||
/// too generic for the constant to be evaluated then `Err(ErrorHandled::TooGeneric)` is
|
||||
/// returned.
|
||||
pub fn const_eval_resolve(
|
||||
self,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
def_id: DefId,
|
||||
substs: SubstsRef<'tcx>,
|
||||
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)
|
||||
} else {
|
||||
Err(ErrorHandled::TooGeneric)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn const_eval_instance(
|
||||
self,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
instance: ty::Instance<'tcx>,
|
||||
span: Option<Span>
|
||||
) -> ConstEvalResult<'tcx> {
|
||||
let cid = GlobalId {
|
||||
instance,
|
||||
promoted: None,
|
||||
};
|
||||
if let Some(span) = span {
|
||||
self.at(span).const_eval_validated(param_env.and(cid))
|
||||
} else {
|
||||
self.const_eval_validated(param_env.and(cid))
|
||||
}
|
||||
}
|
||||
|
||||
/// Evaluate a promoted constant.
|
||||
pub fn const_eval_promoted(
|
||||
self,
|
||||
instance: ty::Instance<'tcx>,
|
||||
promoted: mir::Promoted
|
||||
) -> ConstEvalResult<'tcx> {
|
||||
let cid = GlobalId {
|
||||
instance,
|
||||
promoted: Some(promoted),
|
||||
};
|
||||
let param_env = ty::ParamEnv::reveal_all();
|
||||
self.const_eval_validated(param_env.and(cid))
|
||||
}
|
||||
}
|
@ -236,14 +236,22 @@ pub fn from_char(c: char) -> Self {
|
||||
Scalar::Raw { data: c as u128, size: 4 }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn try_from_uint(i: impl Into<u128>, size: Size) -> Option<Self> {
|
||||
let i = i.into();
|
||||
if truncate(i, size) == i {
|
||||
Some(Scalar::Raw { data: i, size: size.bytes() as u8 })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn from_uint(i: impl Into<u128>, size: Size) -> Self {
|
||||
let i = i.into();
|
||||
assert_eq!(
|
||||
truncate(i, size), i,
|
||||
"Unsigned value {:#x} does not fit in {} bits", i, size.bits()
|
||||
);
|
||||
Scalar::Raw { data: i, size: size.bytes() as u8 }
|
||||
Self::try_from_uint(i, size).unwrap_or_else(|| {
|
||||
bug!("Unsigned value {:#x} does not fit in {} bits", i, size.bits())
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -267,15 +275,23 @@ pub fn from_u64(i: u64) -> Self {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn from_int(i: impl Into<i128>, size: Size) -> Self {
|
||||
pub fn try_from_int(i: impl Into<i128>, size: Size) -> Option<Self> {
|
||||
let i = i.into();
|
||||
// `into` performed sign extension, we have to truncate
|
||||
let truncated = truncate(i as u128, size);
|
||||
assert_eq!(
|
||||
sign_extend(truncated, size) as i128, i,
|
||||
"Signed value {:#x} does not fit in {} bits", i, size.bits()
|
||||
);
|
||||
Scalar::Raw { data: truncated, size: size.bytes() as u8 }
|
||||
if sign_extend(truncated, size) as i128 == i {
|
||||
Some(Scalar::Raw { data: truncated, size: size.bytes() as u8 })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn from_int(i: impl Into<i128>, size: Size) -> Self {
|
||||
let i = i.into();
|
||||
Self::try_from_int(i, size).unwrap_or_else(|| {
|
||||
bug!("Signed value {:#x} does not fit in {} bits", i, size.bits())
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -448,7 +448,8 @@
|
||||
///
|
||||
/// **Do not use this** outside const eval. Const eval uses this to break query cycles
|
||||
/// during validation. Please add a comment to every use site explaining why using
|
||||
/// `const_eval` isn't sufficient.
|
||||
/// `const_eval_validated` isn't sufficient. The returned constant also isn't in a suitable
|
||||
/// form to be used outside of const eval.
|
||||
query const_eval_raw(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
|
||||
-> ConstEvalRawResult<'tcx> {
|
||||
no_force
|
||||
@ -460,7 +461,13 @@
|
||||
|
||||
/// Results of evaluating const items or constants embedded in
|
||||
/// other items (such as enum variant explicit discriminants).
|
||||
query const_eval(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
|
||||
///
|
||||
/// In contrast to `const_eval_raw` this performs some validation on the constant, and
|
||||
/// returns a proper constant that is usable by the rest of the compiler.
|
||||
///
|
||||
/// **Do not use this** directly, use one of the following wrappers: `tcx.const_eval_poly`,
|
||||
/// `tcx.const_eval_resolve`, `tcx.const_eval_instance`, or `tcx.const_eval_promoted`.
|
||||
query const_eval_validated(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
|
||||
-> ConstEvalResult<'tcx> {
|
||||
no_force
|
||||
desc { |tcx|
|
||||
|
@ -1,5 +1,4 @@
|
||||
use crate::infer::{InferCtxt, ShallowResolver};
|
||||
use crate::mir::interpret::{GlobalId, ErrorHandled};
|
||||
use crate::ty::{self, Ty, TypeFoldable, ToPolyTraitRef};
|
||||
use crate::ty::error::ExpectedFound;
|
||||
use rustc_data_structures::obligation_forest::{DoCompleted, Error, ForestObligation};
|
||||
@ -501,27 +500,13 @@ fn infer_ty(ty: Ty<'tcx>) -> ty::InferTy {
|
||||
ProcessResult::Unchanged
|
||||
} else {
|
||||
if !substs.has_local_value() {
|
||||
let instance = ty::Instance::resolve(
|
||||
self.selcx.tcx(),
|
||||
obligation.param_env,
|
||||
def_id,
|
||||
substs,
|
||||
);
|
||||
if let Some(instance) = instance {
|
||||
let cid = GlobalId {
|
||||
instance,
|
||||
promoted: None,
|
||||
};
|
||||
match self.selcx.tcx().at(obligation.cause.span)
|
||||
.const_eval(obligation.param_env.and(cid)) {
|
||||
Ok(_) => ProcessResult::Changed(vec![]),
|
||||
Err(err) => ProcessResult::Error(
|
||||
CodeSelectionError(ConstEvalFailure(err)))
|
||||
}
|
||||
} else {
|
||||
ProcessResult::Error(CodeSelectionError(
|
||||
ConstEvalFailure(ErrorHandled::TooGeneric)
|
||||
))
|
||||
match self.selcx.tcx().const_eval_resolve(obligation.param_env,
|
||||
def_id,
|
||||
substs,
|
||||
Some(obligation.cause.span)) {
|
||||
Ok(_) => ProcessResult::Changed(vec![]),
|
||||
Err(err) => ProcessResult::Error(
|
||||
CodeSelectionError(ConstEvalFailure(err)))
|
||||
}
|
||||
} else {
|
||||
pending_obligation.stalled_on =
|
||||
|
@ -33,7 +33,6 @@
|
||||
use crate::hir::def_id::DefId;
|
||||
use crate::infer::{CombinedSnapshot, InferCtxt, InferOk, PlaceholderMap, TypeFreshener};
|
||||
use crate::middle::lang_items;
|
||||
use crate::mir::interpret::GlobalId;
|
||||
use crate::ty::fast_reject;
|
||||
use crate::ty::relate::TypeRelation;
|
||||
use crate::ty::subst::{Subst, SubstsRef};
|
||||
@ -820,22 +819,13 @@ fn evaluate_predicate_recursively<'o>(
|
||||
}
|
||||
|
||||
ty::Predicate::ConstEvaluatable(def_id, substs) => {
|
||||
let tcx = self.tcx();
|
||||
if !(obligation.param_env, substs).has_local_value() {
|
||||
let param_env = obligation.param_env;
|
||||
let instance =
|
||||
ty::Instance::resolve(tcx, param_env, def_id, substs);
|
||||
if let Some(instance) = instance {
|
||||
let cid = GlobalId {
|
||||
instance,
|
||||
promoted: None,
|
||||
};
|
||||
match self.tcx().const_eval(param_env.and(cid)) {
|
||||
Ok(_) => Ok(EvaluatedToOk),
|
||||
Err(_) => Ok(EvaluatedToErr),
|
||||
}
|
||||
} else {
|
||||
Ok(EvaluatedToErr)
|
||||
match self.tcx().const_eval_resolve(obligation.param_env,
|
||||
def_id,
|
||||
substs,
|
||||
None) {
|
||||
Ok(_) => Ok(EvaluatedToOk),
|
||||
Err(_) => Ok(EvaluatedToErr),
|
||||
}
|
||||
} else {
|
||||
// Inference variables still left in param_env or substs.
|
||||
|
@ -19,7 +19,7 @@
|
||||
use crate::middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
|
||||
use crate::middle::resolve_lifetime::ObjectLifetimeDefault;
|
||||
use crate::mir::ReadOnlyBodyAndCache;
|
||||
use crate::mir::interpret::{GlobalId, ErrorHandled};
|
||||
use crate::mir::interpret::ErrorHandled;
|
||||
use crate::mir::GeneratorLayout;
|
||||
use crate::session::CrateDisambiguator;
|
||||
use crate::traits::{self, Reveal};
|
||||
@ -2344,13 +2344,7 @@ pub fn variant_of_res(&self, res: Res) -> &VariantDef {
|
||||
pub fn eval_explicit_discr(&self, tcx: TyCtxt<'tcx>, expr_did: DefId) -> Option<Discr<'tcx>> {
|
||||
let param_env = tcx.param_env(expr_did);
|
||||
let repr_type = self.repr.discr_type();
|
||||
let substs = InternalSubsts::identity_for_item(tcx, expr_did);
|
||||
let instance = ty::Instance::new(expr_did, substs);
|
||||
let cid = GlobalId {
|
||||
instance,
|
||||
promoted: None
|
||||
};
|
||||
match tcx.const_eval(param_env.and(cid)) {
|
||||
match tcx.const_eval_poly(expr_did) {
|
||||
Ok(val) => {
|
||||
// FIXME: Find the right type and use it instead of `val.ty` here
|
||||
if let Some(b) = val.try_eval_bits(tcx, param_env, val.ty) {
|
||||
|
@ -15,7 +15,7 @@
|
||||
use crate::ty::{List, TyS, ParamEnvAnd, ParamEnv};
|
||||
use crate::ty::layout::VariantIdx;
|
||||
use crate::util::captures::Captures;
|
||||
use crate::mir::interpret::{Scalar, GlobalId};
|
||||
use crate::mir::interpret::Scalar;
|
||||
|
||||
use polonius_engine::Atom;
|
||||
use rustc_index::vec::Idx;
|
||||
@ -2340,13 +2340,9 @@ pub fn eval(
|
||||
|
||||
let (param_env, substs) = param_env_and_substs.into_parts();
|
||||
|
||||
// try to resolve e.g. associated constants to their definition on an impl
|
||||
let instance = ty::Instance::resolve(tcx, param_env, did, substs)?;
|
||||
let gid = GlobalId {
|
||||
instance,
|
||||
promoted: None,
|
||||
};
|
||||
tcx.const_eval(param_env.and(gid)).ok()
|
||||
// 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()
|
||||
};
|
||||
|
||||
match self.val {
|
||||
|
@ -8,7 +8,7 @@
|
||||
use libc::c_uint;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::mir::interpret::{ConstValue, Allocation, read_target_uint,
|
||||
Pointer, ErrorHandled, GlobalId};
|
||||
Pointer, ErrorHandled};
|
||||
use rustc::mir::mono::MonoItem;
|
||||
use rustc::hir::Node;
|
||||
use rustc_target::abi::HasDataLayout;
|
||||
@ -81,13 +81,7 @@ pub fn codegen_static_initializer(
|
||||
cx: &CodegenCx<'ll, 'tcx>,
|
||||
def_id: DefId,
|
||||
) -> Result<(&'ll Value, &'tcx Allocation), ErrorHandled> {
|
||||
let instance = ty::Instance::mono(cx.tcx, def_id);
|
||||
let cid = GlobalId {
|
||||
instance,
|
||||
promoted: None,
|
||||
};
|
||||
let param_env = ty::ParamEnv::reveal_all();
|
||||
let static_ = cx.tcx.const_eval(param_env.and(cid))?;
|
||||
let static_ = cx.tcx.const_eval_poly(def_id)?;
|
||||
|
||||
let alloc = match static_.val {
|
||||
ty::ConstKind::Value(ConstValue::ByRef {
|
||||
|
@ -14,7 +14,6 @@
|
||||
use rustc_codegen_ssa::base::{to_immediate, wants_msvc_seh, compare_simd_types};
|
||||
use rustc::ty::{self, Ty};
|
||||
use rustc::ty::layout::{self, FnAbiExt, LayoutOf, HasTyCtxt, Primitive};
|
||||
use rustc::mir::interpret::GlobalId;
|
||||
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
|
||||
use rustc::hir;
|
||||
use rustc_target::abi::HasDataLayout;
|
||||
@ -202,11 +201,9 @@ fn codegen_intrinsic_call(
|
||||
"needs_drop" |
|
||||
"type_id" |
|
||||
"type_name" => {
|
||||
let gid = GlobalId {
|
||||
instance,
|
||||
promoted: None,
|
||||
};
|
||||
let ty_name = self.tcx.const_eval(ty::ParamEnv::reveal_all().and(gid)).unwrap();
|
||||
let ty_name = self.tcx
|
||||
.const_eval_instance(ty::ParamEnv::reveal_all(), instance, None)
|
||||
.unwrap();
|
||||
OperandRef::from_const(self, ty_name).immediate_or_packed_pair(self)
|
||||
}
|
||||
"init" => {
|
||||
|
@ -638,12 +638,7 @@ fn codegen_call_terminator(
|
||||
projection: &[],
|
||||
} = place.as_ref()
|
||||
{
|
||||
let param_env = ty::ParamEnv::reveal_all();
|
||||
let cid = mir::interpret::GlobalId {
|
||||
instance: self.instance,
|
||||
promoted: Some(promoted),
|
||||
};
|
||||
let c = bx.tcx().const_eval(param_env.and(cid));
|
||||
let c = bx.tcx().const_eval_promoted(self.instance, promoted);
|
||||
let (llval, ty) = self.simd_shuffle_indices(
|
||||
&bx,
|
||||
terminator.source_info.span,
|
||||
|
@ -43,17 +43,14 @@ pub fn eval_mir_constant(
|
||||
match constant.literal.val {
|
||||
ty::ConstKind::Unevaluated(def_id, substs) => {
|
||||
let substs = self.monomorphize(&substs);
|
||||
let instance = ty::Instance::resolve(
|
||||
self.cx.tcx(), ty::ParamEnv::reveal_all(), def_id, substs,
|
||||
).unwrap();
|
||||
let cid = mir::interpret::GlobalId {
|
||||
instance,
|
||||
promoted: None,
|
||||
};
|
||||
self.cx.tcx().const_eval(ty::ParamEnv::reveal_all().and(cid)).map_err(|err| {
|
||||
self.cx.tcx().sess.span_err(constant.span, "erroneous constant encountered");
|
||||
err
|
||||
})
|
||||
self.cx.tcx()
|
||||
.const_eval_resolve(ty::ParamEnv::reveal_all(), def_id, substs, None)
|
||||
.map_err(|err| {
|
||||
self.cx.tcx().sess.span_err(
|
||||
constant.span,
|
||||
"erroneous constant encountered");
|
||||
err
|
||||
})
|
||||
},
|
||||
_ => Ok(self.monomorphize(&constant.literal)),
|
||||
}
|
||||
|
@ -473,14 +473,9 @@ pub fn codegen_place(
|
||||
}),
|
||||
projection: [],
|
||||
} => {
|
||||
let param_env = ty::ParamEnv::reveal_all();
|
||||
let instance = Instance::new(*def_id, self.monomorphize(substs));
|
||||
let cid = mir::interpret::GlobalId {
|
||||
instance: instance,
|
||||
promoted: Some(*promoted),
|
||||
};
|
||||
let layout = cx.layout_of(self.monomorphize(&ty));
|
||||
match bx.tcx().const_eval(param_env.and(cid)) {
|
||||
match bx.tcx().const_eval_promoted(instance, *promoted) {
|
||||
Ok(val) => match val.val {
|
||||
ty::ConstKind::Value(mir::interpret::ConstValue::ByRef {
|
||||
alloc, offset
|
||||
|
@ -1147,19 +1147,9 @@ fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::Item<'_>) {
|
||||
|
||||
fn check_const(cx: &LateContext<'_, '_>, body_id: hir::BodyId) {
|
||||
let def_id = cx.tcx.hir().body_owner_def_id(body_id);
|
||||
let param_env = if cx.tcx.is_static(def_id) {
|
||||
// Use the same param_env as `codegen_static_initializer`, to reuse the cache.
|
||||
ty::ParamEnv::reveal_all()
|
||||
} else {
|
||||
cx.tcx.param_env(def_id)
|
||||
};
|
||||
let cid = ::rustc::mir::interpret::GlobalId {
|
||||
instance: ty::Instance::mono(cx.tcx, def_id),
|
||||
promoted: None
|
||||
};
|
||||
// trigger the query once for all constants since that will already report the errors
|
||||
// FIXME: Use ensure here
|
||||
let _ = cx.tcx.const_eval(param_env.and(cid));
|
||||
let _ = cx.tcx.const_eval_poly(def_id);
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedBrokenConst {
|
||||
|
@ -33,8 +33,7 @@ pub fn ast_block(&mut self,
|
||||
this.ast_block_stmts(destination, block, span, stmts, expr,
|
||||
safety_mode)
|
||||
});
|
||||
this.cfg.terminate(unpack!(block_exit), source_info,
|
||||
TerminatorKind::Goto { target: exit_block });
|
||||
this.cfg.goto(unpack!(block_exit), source_info, exit_block);
|
||||
exit_block.unit()
|
||||
} else {
|
||||
this.ast_block_stmts(destination, block, span, stmts, expr,
|
||||
|
@ -85,4 +85,9 @@ pub fn terminate(&mut self,
|
||||
kind,
|
||||
});
|
||||
}
|
||||
|
||||
/// In the `origin` block, push a `goto -> target` terminator.
|
||||
pub fn goto(&mut self, origin: BasicBlock, source_info: SourceInfo, target: BasicBlock) {
|
||||
self.terminate(origin, source_info, TerminatorKind::Goto { target })
|
||||
}
|
||||
}
|
||||
|
@ -140,17 +140,9 @@ pub fn into_expr(
|
||||
},
|
||||
);
|
||||
|
||||
this.cfg.terminate(
|
||||
true_block,
|
||||
source_info,
|
||||
TerminatorKind::Goto { target: join_block },
|
||||
);
|
||||
this.cfg.terminate(
|
||||
false_block,
|
||||
source_info,
|
||||
TerminatorKind::Goto { target: join_block },
|
||||
);
|
||||
|
||||
// Link up both branches:
|
||||
this.cfg.goto(true_block, source_info, join_block);
|
||||
this.cfg.goto(false_block, source_info, join_block);
|
||||
join_block.unit()
|
||||
}
|
||||
ExprKind::Loop { body } => {
|
||||
@ -167,12 +159,8 @@ pub fn into_expr(
|
||||
let loop_block = this.cfg.start_new_block();
|
||||
let exit_block = this.cfg.start_new_block();
|
||||
|
||||
// start the loop
|
||||
this.cfg.terminate(
|
||||
block,
|
||||
source_info,
|
||||
TerminatorKind::Goto { target: loop_block },
|
||||
);
|
||||
// Start the loop.
|
||||
this.cfg.goto(block, source_info, loop_block);
|
||||
|
||||
this.in_breakable_scope(
|
||||
Some(loop_block),
|
||||
@ -196,11 +184,7 @@ pub fn into_expr(
|
||||
let tmp = this.get_unit_temp();
|
||||
// Execute the body, branching back to the test.
|
||||
let body_block_end = unpack!(this.into(&tmp, body_block, body));
|
||||
this.cfg.terminate(
|
||||
body_block_end,
|
||||
source_info,
|
||||
TerminatorKind::Goto { target: loop_block },
|
||||
);
|
||||
this.cfg.goto(body_block_end, source_info, loop_block);
|
||||
},
|
||||
);
|
||||
exit_block.unit()
|
||||
|
@ -26,6 +26,7 @@
|
||||
mod test;
|
||||
mod util;
|
||||
|
||||
use itertools::Itertools;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
@ -258,11 +259,7 @@ pub fn match_expr(
|
||||
scrutinee_span,
|
||||
match_scope,
|
||||
);
|
||||
this.cfg.terminate(
|
||||
binding_end,
|
||||
source_info,
|
||||
TerminatorKind::Goto { target: arm_block },
|
||||
);
|
||||
this.cfg.goto(binding_end, source_info, arm_block);
|
||||
}
|
||||
}
|
||||
|
||||
@ -278,11 +275,7 @@ pub fn match_expr(
|
||||
let end_block = self.cfg.start_new_block();
|
||||
|
||||
for arm_block in arm_end_blocks {
|
||||
self.cfg.terminate(
|
||||
unpack!(arm_block),
|
||||
outer_source_info,
|
||||
TerminatorKind::Goto { target: end_block },
|
||||
);
|
||||
self.cfg.goto(unpack!(arm_block), outer_source_info, end_block);
|
||||
}
|
||||
|
||||
self.source_scope = outer_source_info.scope;
|
||||
@ -822,9 +815,7 @@ fn match_candidates<'pat>(
|
||||
);
|
||||
let (matched_candidates, unmatched_candidates) = candidates.split_at_mut(fully_matched);
|
||||
|
||||
let block: BasicBlock;
|
||||
|
||||
if !matched_candidates.is_empty() {
|
||||
let block: BasicBlock = if !matched_candidates.is_empty() {
|
||||
let otherwise_block = self.select_matched_candidates(
|
||||
matched_candidates,
|
||||
start_block,
|
||||
@ -832,35 +823,26 @@ fn match_candidates<'pat>(
|
||||
);
|
||||
|
||||
if let Some(last_otherwise_block) = otherwise_block {
|
||||
block = last_otherwise_block
|
||||
last_otherwise_block
|
||||
} else {
|
||||
// Any remaining candidates are unreachable.
|
||||
if unmatched_candidates.is_empty() {
|
||||
return;
|
||||
}
|
||||
block = self.cfg.start_new_block();
|
||||
};
|
||||
self.cfg.start_new_block()
|
||||
}
|
||||
} else {
|
||||
block = *start_block.get_or_insert_with(|| self.cfg.start_new_block());
|
||||
}
|
||||
*start_block.get_or_insert_with(|| self.cfg.start_new_block())
|
||||
};
|
||||
|
||||
// If there are no candidates that still need testing, we're
|
||||
// done. Since all matches are exhaustive, execution should
|
||||
// never reach this point.
|
||||
if unmatched_candidates.is_empty() {
|
||||
let source_info = self.source_info(span);
|
||||
if let Some(otherwise) = otherwise_block {
|
||||
self.cfg.terminate(
|
||||
block,
|
||||
source_info,
|
||||
TerminatorKind::Goto { target: otherwise },
|
||||
);
|
||||
} else {
|
||||
self.cfg.terminate(
|
||||
block,
|
||||
source_info,
|
||||
TerminatorKind::Unreachable,
|
||||
)
|
||||
match otherwise_block {
|
||||
Some(otherwise) => self.cfg.goto(block, source_info, otherwise),
|
||||
None => self.cfg.terminate(block, source_info, TerminatorKind::Unreachable),
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -885,7 +867,7 @@ fn match_candidates<'pat>(
|
||||
/// ...
|
||||
///
|
||||
/// We generate real edges from:
|
||||
/// * `block` to the prebinding_block of the first pattern,
|
||||
/// * `start_block` to the `prebinding_block` of the first pattern,
|
||||
/// * the otherwise block of the first pattern to the second pattern,
|
||||
/// * the otherwise block of the third pattern to the a block with an
|
||||
/// Unreachable terminator.
|
||||
@ -948,32 +930,25 @@ fn select_matched_candidates(
|
||||
let first_candidate = &reachable_candidates[0];
|
||||
let first_prebinding_block = first_candidate.pre_binding_block;
|
||||
|
||||
// `goto -> first_prebinding_block` from the `start_block` if there is one.
|
||||
if let Some(start_block) = *start_block {
|
||||
let source_info = self.source_info(first_candidate.span);
|
||||
self.cfg.terminate(
|
||||
start_block,
|
||||
source_info,
|
||||
TerminatorKind::Goto { target: first_prebinding_block },
|
||||
);
|
||||
self.cfg.goto(start_block, source_info, first_prebinding_block);
|
||||
} else {
|
||||
*start_block = Some(first_prebinding_block);
|
||||
}
|
||||
|
||||
for window in reachable_candidates.windows(2) {
|
||||
if let [first_candidate, second_candidate] = window {
|
||||
let source_info = self.source_info(first_candidate.span);
|
||||
if let Some(otherwise_block) = first_candidate.otherwise_block {
|
||||
self.false_edges(
|
||||
otherwise_block,
|
||||
second_candidate.pre_binding_block,
|
||||
first_candidate.next_candidate_pre_binding_block,
|
||||
source_info,
|
||||
);
|
||||
} else {
|
||||
bug!("candidate other than the last has no guard");
|
||||
}
|
||||
for (first_candidate, second_candidate) in reachable_candidates.iter().tuple_windows() {
|
||||
let source_info = self.source_info(first_candidate.span);
|
||||
if let Some(otherwise_block) = first_candidate.otherwise_block {
|
||||
self.false_edges(
|
||||
otherwise_block,
|
||||
second_candidate.pre_binding_block,
|
||||
first_candidate.next_candidate_pre_binding_block,
|
||||
source_info,
|
||||
);
|
||||
} else {
|
||||
bug!("<[_]>::windows returned incorrectly sized window");
|
||||
bug!("candidate other than the last has no guard");
|
||||
}
|
||||
}
|
||||
|
||||
@ -992,8 +967,8 @@ fn select_matched_candidates(
|
||||
}
|
||||
}
|
||||
|
||||
let last_candidate = reachable_candidates.last().unwrap();
|
||||
|
||||
let last_candidate = reachable_candidates.last().unwrap();
|
||||
if let Some(otherwise) = last_candidate.otherwise_block {
|
||||
let source_info = self.source_info(last_candidate.span);
|
||||
let block = self.cfg.start_new_block();
|
||||
|
@ -30,7 +30,7 @@ pub fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<'tcx> {
|
||||
Test {
|
||||
span: match_pair.pattern.span,
|
||||
kind: TestKind::Switch {
|
||||
adt_def: adt_def.clone(),
|
||||
adt_def,
|
||||
variants: BitSet::new_empty(adt_def.variants.len()),
|
||||
},
|
||||
}
|
||||
|
@ -109,15 +109,7 @@ pub fn false_edges(
|
||||
},
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
self.cfg.terminate(
|
||||
from_block,
|
||||
source_info,
|
||||
TerminatorKind::Goto {
|
||||
target: real_target
|
||||
}
|
||||
);
|
||||
}
|
||||
_ => self.cfg.goto(from_block, source_info, real_target),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -606,14 +606,11 @@ fn construct_fn<'a, 'tcx, A>(
|
||||
let fn_end = span.shrink_to_hi();
|
||||
let source_info = builder.source_info(fn_end);
|
||||
let return_block = builder.return_block();
|
||||
builder.cfg.terminate(block, source_info,
|
||||
TerminatorKind::Goto { target: return_block });
|
||||
builder.cfg.terminate(return_block, source_info,
|
||||
TerminatorKind::Return);
|
||||
builder.cfg.goto(block, source_info, return_block);
|
||||
builder.cfg.terminate(return_block, source_info, TerminatorKind::Return);
|
||||
// Attribute any unreachable codepaths to the function's closing brace
|
||||
if let Some(unreachable_block) = builder.cached_unreachable_block {
|
||||
builder.cfg.terminate(unreachable_block, source_info,
|
||||
TerminatorKind::Unreachable);
|
||||
builder.cfg.terminate(unreachable_block, source_info, TerminatorKind::Unreachable);
|
||||
}
|
||||
return_block.unit()
|
||||
}));
|
||||
|
@ -564,14 +564,12 @@ pub fn exit_scope(&mut self,
|
||||
let source_info = scope.source_info(span);
|
||||
block = match scope.cached_exits.entry((target, region_scope)) {
|
||||
Entry::Occupied(e) => {
|
||||
self.cfg.terminate(block, source_info,
|
||||
TerminatorKind::Goto { target: *e.get() });
|
||||
self.cfg.goto(block, source_info, *e.get());
|
||||
return;
|
||||
}
|
||||
Entry::Vacant(v) => {
|
||||
let b = self.cfg.start_new_block();
|
||||
self.cfg.terminate(block, source_info,
|
||||
TerminatorKind::Goto { target: b });
|
||||
self.cfg.goto(block, source_info, b);
|
||||
v.insert(b);
|
||||
b
|
||||
}
|
||||
@ -596,8 +594,7 @@ pub fn exit_scope(&mut self,
|
||||
scope = next_scope;
|
||||
}
|
||||
|
||||
let source_info = self.scopes.source_info(scope_count, span);
|
||||
self.cfg.terminate(block, source_info, TerminatorKind::Goto { target });
|
||||
self.cfg.goto(block, self.scopes.source_info(scope_count, span), target);
|
||||
}
|
||||
|
||||
/// Creates a path that performs all required cleanup for dropping a generator.
|
||||
@ -616,14 +613,12 @@ pub fn generator_drop_cleanup(&mut self) -> Option<BasicBlock> {
|
||||
|
||||
while let Some(scope) = scopes.next() {
|
||||
block = if let Some(b) = scope.cached_generator_drop {
|
||||
self.cfg.terminate(block, src_info,
|
||||
TerminatorKind::Goto { target: b });
|
||||
self.cfg.goto(block, src_info, b);
|
||||
return Some(result);
|
||||
} else {
|
||||
let b = self.cfg.start_new_block();
|
||||
scope.cached_generator_drop = Some(b);
|
||||
self.cfg.terminate(block, src_info,
|
||||
TerminatorKind::Goto { target: b });
|
||||
self.cfg.goto(block, src_info, b);
|
||||
b
|
||||
};
|
||||
|
||||
@ -1243,8 +1238,7 @@ fn build_diverge_scope<'tcx>(cfg: &mut CFG<'tcx>,
|
||||
// block for our StorageDead statements.
|
||||
let block = cfg.start_new_cleanup_block();
|
||||
let source_info = SourceInfo { span: DUMMY_SP, scope: source_scope };
|
||||
cfg.terminate(block, source_info,
|
||||
TerminatorKind::Goto { target: target });
|
||||
cfg.goto(block, source_info, target);
|
||||
target = block;
|
||||
target_built_by_us = true;
|
||||
}
|
||||
|
@ -652,7 +652,7 @@ fn validate_and_turn_into_const<'tcx>(
|
||||
})
|
||||
}
|
||||
|
||||
pub fn const_eval_provider<'tcx>(
|
||||
pub fn const_eval_validated_provider<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
|
||||
) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> {
|
||||
@ -660,7 +660,7 @@ pub fn const_eval_provider<'tcx>(
|
||||
if key.param_env.reveal == Reveal::All {
|
||||
let mut key = key.clone();
|
||||
key.param_env.reveal = Reveal::UserFacing;
|
||||
match tcx.const_eval(key) {
|
||||
match tcx.const_eval_validated(key) {
|
||||
// try again with reveal all as requested
|
||||
Err(ErrorHandled::TooGeneric) => {
|
||||
// Promoteds should never be "too generic" when getting evaluated.
|
||||
|
@ -5,7 +5,7 @@
|
||||
use crate::hair::util::UserAnnotatedTyHelpers;
|
||||
use rustc_index::vec::Idx;
|
||||
use rustc::hir::def::{CtorOf, Res, DefKind, CtorKind};
|
||||
use rustc::mir::interpret::{GlobalId, ErrorHandled, Scalar};
|
||||
use rustc::mir::interpret::{ErrorHandled, Scalar};
|
||||
use rustc::ty::{self, AdtKind, Ty};
|
||||
use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability, PointerCast};
|
||||
use rustc::ty::subst::{InternalSubsts, SubstsRef};
|
||||
@ -511,21 +511,15 @@ fn make_mirror_unadjusted<'a, 'tcx>(
|
||||
hir::ExprKind::Repeat(ref v, ref count) => {
|
||||
let def_id = cx.tcx.hir().local_def_id(count.hir_id);
|
||||
let substs = InternalSubsts::identity_for_item(cx.tcx, def_id);
|
||||
let instance = ty::Instance::resolve(
|
||||
cx.tcx,
|
||||
cx.param_env,
|
||||
def_id,
|
||||
substs,
|
||||
).unwrap();
|
||||
let global_id = GlobalId {
|
||||
instance,
|
||||
promoted: None
|
||||
};
|
||||
let span = cx.tcx.def_span(def_id);
|
||||
let count = match cx.tcx.at(span).const_eval(cx.param_env.and(global_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
|
||||
},
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
use rustc::mir::{Field, BorrowKind, Mutability};
|
||||
use rustc::mir::{UserTypeProjection};
|
||||
use rustc::mir::interpret::{GlobalId, ConstValue, get_slice_bytes, sign_extend};
|
||||
use rustc::mir::interpret::{ConstValue, ErrorHandled, get_slice_bytes, sign_extend};
|
||||
use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty, UserType, DefIdTree};
|
||||
use rustc::ty::{CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations};
|
||||
use rustc::ty::subst::{SubstsRef, GenericArg};
|
||||
@ -771,57 +771,37 @@ fn lower_path(&mut self,
|
||||
let kind = match res {
|
||||
Res::Def(DefKind::Const, def_id) | Res::Def(DefKind::AssocConst, def_id) => {
|
||||
let substs = self.tables.node_substs(id);
|
||||
match ty::Instance::resolve(
|
||||
self.tcx,
|
||||
self.param_env,
|
||||
def_id,
|
||||
substs,
|
||||
) {
|
||||
Some(instance) => {
|
||||
let cid = GlobalId {
|
||||
instance,
|
||||
promoted: None,
|
||||
};
|
||||
match self.tcx.at(span).const_eval(self.param_env.and(cid)) {
|
||||
Ok(value) => {
|
||||
let pattern = self.const_to_pat(value, id, span);
|
||||
if !is_associated_const {
|
||||
return pattern;
|
||||
}
|
||||
match self.tcx.const_eval_resolve(self.param_env, def_id, substs, Some(span)) {
|
||||
Ok(value) => {
|
||||
let pattern = self.const_to_pat(value, id, span);
|
||||
if !is_associated_const {
|
||||
return pattern;
|
||||
}
|
||||
|
||||
let user_provided_types = self.tables().user_provided_types();
|
||||
return if let Some(u_ty) = user_provided_types.get(id) {
|
||||
let user_ty = PatTyProj::from_user_type(*u_ty);
|
||||
Pat {
|
||||
span,
|
||||
kind: Box::new(
|
||||
PatKind::AscribeUserType {
|
||||
subpattern: pattern,
|
||||
ascription: Ascription {
|
||||
/// Note that use `Contravariant` here. See the
|
||||
/// `variance` field documentation for details.
|
||||
variance: ty::Variance::Contravariant,
|
||||
user_ty,
|
||||
user_ty_span: span,
|
||||
},
|
||||
}
|
||||
),
|
||||
ty: value.ty,
|
||||
let user_provided_types = self.tables().user_provided_types();
|
||||
return if let Some(u_ty) = user_provided_types.get(id) {
|
||||
let user_ty = PatTyProj::from_user_type(*u_ty);
|
||||
Pat {
|
||||
span,
|
||||
kind: Box::new(
|
||||
PatKind::AscribeUserType {
|
||||
subpattern: pattern,
|
||||
ascription: Ascription {
|
||||
/// Note that use `Contravariant` here. See the
|
||||
/// `variance` field documentation for details.
|
||||
variance: ty::Variance::Contravariant,
|
||||
user_ty,
|
||||
user_ty_span: span,
|
||||
},
|
||||
}
|
||||
} else {
|
||||
pattern
|
||||
}
|
||||
},
|
||||
Err(_) => {
|
||||
self.tcx.sess.span_err(
|
||||
span,
|
||||
"could not evaluate constant pattern",
|
||||
);
|
||||
PatKind::Wild
|
||||
),
|
||||
ty: value.ty,
|
||||
}
|
||||
} else {
|
||||
pattern
|
||||
}
|
||||
},
|
||||
None => {
|
||||
Err(ErrorHandled::TooGeneric) => {
|
||||
self.errors.push(if is_associated_const {
|
||||
PatternError::AssocConstInPattern(span)
|
||||
} else {
|
||||
@ -829,6 +809,13 @@ fn lower_path(&mut self,
|
||||
});
|
||||
PatKind::Wild
|
||||
},
|
||||
Err(_) => {
|
||||
self.tcx.sess.span_err(
|
||||
span,
|
||||
"could not evaluate constant pattern",
|
||||
);
|
||||
PatKind::Wild
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => self.lower_variant_or_leaf(res, id, span, ty, vec![]),
|
||||
|
@ -11,7 +11,7 @@
|
||||
use rustc::ty::TyCtxt;
|
||||
use rustc::mir::{
|
||||
self, BinOp,
|
||||
interpret::{InterpResult, Scalar, GlobalId, ConstValue}
|
||||
interpret::{InterpResult, Scalar, ConstValue}
|
||||
};
|
||||
|
||||
use super::{
|
||||
@ -123,11 +123,9 @@ pub fn emulate_intrinsic(
|
||||
sym::size_of |
|
||||
sym::type_id |
|
||||
sym::type_name => {
|
||||
let gid = GlobalId {
|
||||
instance,
|
||||
promoted: None,
|
||||
};
|
||||
let val = self.tcx.const_eval(self.param_env.and(gid))?;
|
||||
let val = self.tcx.const_eval_instance(self.param_env,
|
||||
instance,
|
||||
Some(self.tcx.span))?;
|
||||
let val = self.eval_const_to_op(val, None)?;
|
||||
self.copy_op(val, dest)?;
|
||||
}
|
||||
|
@ -218,11 +218,20 @@ pub fn from_scalar(val: Scalar<Tag>, layout: TyLayout<'tcx>) -> Self {
|
||||
ImmTy { imm: val.into(), layout }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn try_from_uint(i: impl Into<u128>, layout: TyLayout<'tcx>) -> Option<Self> {
|
||||
Some(Self::from_scalar(Scalar::try_from_uint(i, layout.size)?, layout))
|
||||
}
|
||||
#[inline]
|
||||
pub fn from_uint(i: impl Into<u128>, layout: TyLayout<'tcx>) -> Self {
|
||||
Self::from_scalar(Scalar::from_uint(i, layout.size), layout)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn try_from_int(i: impl Into<i128>, layout: TyLayout<'tcx>) -> Option<Self> {
|
||||
Some(Self::from_scalar(Scalar::try_from_int(i, layout.size)?, layout))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn from_int(i: impl Into<i128>, layout: TyLayout<'tcx>) -> Self {
|
||||
Self::from_scalar(Scalar::from_int(i, layout.size), layout)
|
||||
|
@ -626,11 +626,6 @@ pub(super) fn eval_static_to_mplace(
|
||||
let ty = place_static.ty;
|
||||
assert!(!ty.needs_subst());
|
||||
let layout = self.layout_of(ty)?;
|
||||
let instance = ty::Instance::mono(*self.tcx, place_static.def_id);
|
||||
let cid = GlobalId {
|
||||
instance,
|
||||
promoted: None
|
||||
};
|
||||
// Just create a lazy reference, so we can support recursive statics.
|
||||
// tcx takes care of assigning every static one and only one unique AllocId.
|
||||
// When the data here is ever actually used, memory will notice,
|
||||
@ -646,7 +641,7 @@ pub(super) fn eval_static_to_mplace(
|
||||
// Notice that statics have *two* AllocIds: the lazy one, and the resolved
|
||||
// one. Here we make sure that the interpreted program never sees the
|
||||
// resolved ID. Also see the doc comment of `Memory::get_static_alloc`.
|
||||
let alloc_id = self.tcx.alloc_map.lock().create_static_alloc(cid.instance.def_id());
|
||||
let alloc_id = self.tcx.alloc_map.lock().create_static_alloc(place_static.def_id);
|
||||
let ptr = self.tag_static_base_pointer(Pointer::from(alloc_id));
|
||||
MPlaceTy::from_aligned_ptr(ptr, layout)
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ pub fn provide(providers: &mut Providers<'_>) {
|
||||
shim::provide(providers);
|
||||
transform::provide(providers);
|
||||
monomorphize::partitioning::provide(providers);
|
||||
providers.const_eval = const_eval::const_eval_provider;
|
||||
providers.const_eval_validated = const_eval::const_eval_validated_provider;
|
||||
providers.const_eval_raw = const_eval::const_eval_raw_provider;
|
||||
providers.check_match = hair::pattern::check_match;
|
||||
providers.const_caller_location = const_eval::const_caller_location;
|
||||
|
@ -189,7 +189,7 @@
|
||||
use rustc::mir::{self, Location, PlaceBase, Static, StaticKind};
|
||||
use rustc::mir::visit::Visitor as MirVisitor;
|
||||
use rustc::mir::mono::{MonoItem, InstantiationMode};
|
||||
use rustc::mir::interpret::{Scalar, GlobalId, GlobalAlloc, ErrorHandled};
|
||||
use rustc::mir::interpret::{Scalar, GlobalAlloc, ErrorHandled};
|
||||
use rustc::util::nodemap::{FxHashSet, FxHashMap, DefIdMap};
|
||||
use rustc::util::common::time;
|
||||
|
||||
@ -379,13 +379,7 @@ fn collect_items_rec<'tcx>(
|
||||
|
||||
recursion_depth_reset = None;
|
||||
|
||||
let cid = GlobalId {
|
||||
instance,
|
||||
promoted: None,
|
||||
};
|
||||
let param_env = ty::ParamEnv::reveal_all();
|
||||
|
||||
if let Ok(val) = tcx.const_eval(param_env.and(cid)) {
|
||||
if let Ok(val) = tcx.const_eval_poly(def_id) {
|
||||
collect_const(tcx, val, InternalSubsts::empty(), &mut neighbors);
|
||||
}
|
||||
}
|
||||
@ -681,12 +675,8 @@ fn visit_place_base(&mut self,
|
||||
def_id,
|
||||
..
|
||||
}) => {
|
||||
let param_env = ty::ParamEnv::reveal_all();
|
||||
let cid = GlobalId {
|
||||
instance: Instance::new(*def_id, substs.subst(self.tcx, self.param_substs)),
|
||||
promoted: Some(*promoted),
|
||||
};
|
||||
match self.tcx.const_eval(param_env.and(cid)) {
|
||||
let instance = Instance::new(*def_id, substs.subst(self.tcx, self.param_substs));
|
||||
match self.tcx.const_eval_promoted(instance, *promoted) {
|
||||
Ok(val) => collect_const(self.tcx, val, substs, self.output),
|
||||
Err(ErrorHandled::Reported) => {},
|
||||
Err(ErrorHandled::TooGeneric) => {
|
||||
@ -1041,14 +1031,7 @@ fn visit_item(&mut self, item: &'v hir::Item<'v>) {
|
||||
// but even just declaring them must collect the items they refer to
|
||||
let def_id = self.tcx.hir().local_def_id(item.hir_id);
|
||||
|
||||
let instance = Instance::mono(self.tcx, def_id);
|
||||
let cid = GlobalId {
|
||||
instance,
|
||||
promoted: None,
|
||||
};
|
||||
let param_env = ty::ParamEnv::reveal_all();
|
||||
|
||||
if let Ok(val) = self.tcx.const_eval(param_env.and(cid)) {
|
||||
if let Ok(val) = self.tcx.const_eval_poly(def_id) {
|
||||
collect_const(self.tcx, val, InternalSubsts::empty(), &mut self.output);
|
||||
}
|
||||
}
|
||||
@ -1288,16 +1271,7 @@ fn collect_const<'tcx>(
|
||||
}
|
||||
}
|
||||
ty::ConstKind::Unevaluated(def_id, substs) => {
|
||||
let instance = ty::Instance::resolve(tcx,
|
||||
param_env,
|
||||
def_id,
|
||||
substs).unwrap();
|
||||
|
||||
let cid = GlobalId {
|
||||
instance,
|
||||
promoted: None,
|
||||
};
|
||||
match tcx.const_eval(param_env.and(cid)) {
|
||||
match tcx.const_eval_resolve(param_env, def_id, substs, None) {
|
||||
Ok(val) => collect_const(tcx, val, param_substs, output),
|
||||
Err(ErrorHandled::Reported) => {},
|
||||
Err(ErrorHandled::TooGeneric) => span_bug!(
|
||||
|
@ -173,7 +173,7 @@ pub(super) fn parse_path_segment(&mut self, style: PathStyle) -> PResult<'a, Pat
|
||||
let args = if self.eat_lt() {
|
||||
// `<'a, T, A = U>`
|
||||
let (args, constraints) =
|
||||
self.parse_generic_args_with_leaning_angle_bracket_recovery(style, lo)?;
|
||||
self.parse_generic_args_with_leading_angle_bracket_recovery(style, lo)?;
|
||||
self.expect_gt()?;
|
||||
let span = lo.to(self.prev_span);
|
||||
AngleBracketedArgs { args, constraints, span }.into()
|
||||
@ -212,7 +212,7 @@ pub(super) fn parse_path_segment_ident(&mut self) -> PResult<'a, Ident> {
|
||||
/// bar::<<<<T as Foo>::Output>();
|
||||
/// ^^ help: remove extra angle brackets
|
||||
/// ```
|
||||
fn parse_generic_args_with_leaning_angle_bracket_recovery(
|
||||
fn parse_generic_args_with_leading_angle_bracket_recovery(
|
||||
&mut self,
|
||||
style: PathStyle,
|
||||
lo: Span,
|
||||
|
@ -31,7 +31,6 @@
|
||||
use rustc::infer;
|
||||
use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc::middle::lang_items;
|
||||
use rustc::mir::interpret::GlobalId;
|
||||
use rustc::ty;
|
||||
use rustc::ty::adjustment::{
|
||||
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability,
|
||||
@ -39,7 +38,6 @@
|
||||
use rustc::ty::{AdtKind, Visibility};
|
||||
use rustc::ty::Ty;
|
||||
use rustc::ty::TypeFoldable;
|
||||
use rustc::ty::subst::InternalSubsts;
|
||||
use rustc::traits::{self, ObligationCauseCode};
|
||||
|
||||
use rustc_error_codes::*;
|
||||
@ -1023,20 +1021,7 @@ fn check_expr_repeat(
|
||||
let count = if self.const_param_def_id(count).is_some() {
|
||||
Ok(self.to_const(count, tcx.type_of(count_def_id)))
|
||||
} else {
|
||||
let param_env = ty::ParamEnv::empty();
|
||||
let substs = InternalSubsts::identity_for_item(tcx, count_def_id);
|
||||
let instance = ty::Instance::resolve(
|
||||
tcx,
|
||||
param_env,
|
||||
count_def_id,
|
||||
substs,
|
||||
).unwrap();
|
||||
let global_id = GlobalId {
|
||||
instance,
|
||||
promoted: None
|
||||
};
|
||||
|
||||
tcx.const_eval(param_env.and(global_id))
|
||||
tcx.const_eval_poly(count_def_id)
|
||||
};
|
||||
|
||||
let uty = match expected {
|
||||
|
@ -106,7 +106,7 @@
|
||||
use rustc::infer::error_reporting::TypeAnnotationNeeded::E0282;
|
||||
use rustc::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
|
||||
use rustc::middle::region;
|
||||
use rustc::mir::interpret::{ConstValue, GlobalId};
|
||||
use rustc::mir::interpret::ConstValue;
|
||||
use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine};
|
||||
use rustc::ty::{
|
||||
self, AdtKind, CanonicalUserType, Ty, TyCtxt, Const, GenericParamDefKind,
|
||||
@ -1836,13 +1836,7 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: DefId, span: Span)
|
||||
// `#[link_section]` may contain arbitrary, or even undefined bytes, but it is
|
||||
// the consumer's responsibility to ensure all bytes that have been read
|
||||
// have defined values.
|
||||
let instance = ty::Instance::mono(tcx, id);
|
||||
let cid = GlobalId {
|
||||
instance,
|
||||
promoted: None
|
||||
};
|
||||
let param_env = ty::ParamEnv::reveal_all();
|
||||
if let Ok(static_) = tcx.const_eval(param_env.and(cid)) {
|
||||
if let Ok(static_) = tcx.const_eval_poly(id) {
|
||||
let alloc = if let ty::ConstKind::Value(ConstValue::ByRef { alloc, .. }) = static_.val {
|
||||
alloc
|
||||
} else {
|
||||
|
@ -7,7 +7,7 @@
|
||||
use syntax_pos::hygiene::MacroKind;
|
||||
use syntax_pos::Span;
|
||||
|
||||
use rustc::hir;
|
||||
use rustc::hir::{self, Mutability};
|
||||
use rustc::hir::def::{Res, DefKind, CtorKind};
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc_metadata::creader::LoadedMacro;
|
||||
@ -472,7 +472,7 @@ fn build_const(cx: &DocContext<'_>, did: DefId) -> clean::Constant {
|
||||
fn build_static(cx: &DocContext<'_>, did: DefId, mutable: bool) -> clean::Static {
|
||||
clean::Static {
|
||||
type_: cx.tcx.type_of(did).clean(cx),
|
||||
mutability: if mutable {clean::Mutable} else {clean::Immutable},
|
||||
mutability: if mutable { Mutability::Mut } else { Mutability::Not },
|
||||
expr: "\n\n\n".to_string(), // trigger the "[definition]" links
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,6 @@
|
||||
use rustc::middle::resolve_lifetime as rl;
|
||||
use rustc::middle::lang_items;
|
||||
use rustc::middle::stability;
|
||||
use rustc::mir::interpret::GlobalId;
|
||||
use rustc::hir;
|
||||
use rustc::hir::def::{CtorKind, DefKind, Res};
|
||||
use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
|
||||
@ -46,7 +45,6 @@
|
||||
|
||||
pub use self::types::*;
|
||||
pub use self::types::Type::*;
|
||||
pub use self::types::Mutability::*;
|
||||
pub use self::types::ItemEnum::*;
|
||||
pub use self::types::SelfTy::*;
|
||||
pub use self::types::FunctionRetTy::*;
|
||||
@ -1328,26 +1326,19 @@ fn clean(&self, cx: &DocContext<'_>) -> Type {
|
||||
|
||||
match self.kind {
|
||||
TyKind::Never => Never,
|
||||
TyKind::Ptr(ref m) => RawPointer(m.mutbl.clean(cx), box m.ty.clean(cx)),
|
||||
TyKind::Ptr(ref m) => RawPointer(m.mutbl, box m.ty.clean(cx)),
|
||||
TyKind::Rptr(ref l, ref m) => {
|
||||
let lifetime = if l.is_elided() {
|
||||
None
|
||||
} else {
|
||||
Some(l.clean(cx))
|
||||
};
|
||||
BorrowedRef {lifetime, mutability: m.mutbl.clean(cx),
|
||||
type_: box m.ty.clean(cx)}
|
||||
BorrowedRef {lifetime, mutability: m.mutbl, type_: box m.ty.clean(cx)}
|
||||
}
|
||||
TyKind::Slice(ref ty) => Slice(box ty.clean(cx)),
|
||||
TyKind::Array(ref ty, ref length) => {
|
||||
let def_id = cx.tcx.hir().local_def_id(length.hir_id);
|
||||
let param_env = cx.tcx.param_env(def_id);
|
||||
let substs = InternalSubsts::identity_for_item(cx.tcx, def_id);
|
||||
let cid = GlobalId {
|
||||
instance: ty::Instance::new(def_id, substs),
|
||||
promoted: None
|
||||
};
|
||||
let length = match cx.tcx.const_eval(param_env.and(cid)) {
|
||||
let length = match cx.tcx.const_eval_poly(def_id) {
|
||||
Ok(length) => print_const(cx, length),
|
||||
Err(_) => cx.sess()
|
||||
.source_map()
|
||||
@ -1541,23 +1532,14 @@ fn clean(&self, cx: &DocContext<'_>) -> Type {
|
||||
ty::Slice(ty) => Slice(box ty.clean(cx)),
|
||||
ty::Array(ty, n) => {
|
||||
let mut n = cx.tcx.lift(&n).expect("array lift failed");
|
||||
if let ty::ConstKind::Unevaluated(def_id, substs) = n.val {
|
||||
let param_env = cx.tcx.param_env(def_id);
|
||||
let cid = GlobalId {
|
||||
instance: ty::Instance::new(def_id, substs),
|
||||
promoted: None
|
||||
};
|
||||
if let Ok(new_n) = cx.tcx.const_eval(param_env.and(cid)) {
|
||||
n = new_n;
|
||||
}
|
||||
};
|
||||
n = n.eval(cx.tcx, ty::ParamEnv::reveal_all());
|
||||
let n = print_const(cx, n);
|
||||
Array(box ty.clean(cx), n)
|
||||
}
|
||||
ty::RawPtr(mt) => RawPointer(mt.mutbl.clean(cx), box mt.ty.clean(cx)),
|
||||
ty::RawPtr(mt) => RawPointer(mt.mutbl, box mt.ty.clean(cx)),
|
||||
ty::Ref(r, ty, mutbl) => BorrowedRef {
|
||||
lifetime: r.clean(cx),
|
||||
mutability: mutbl.clean(cx),
|
||||
mutability: mutbl,
|
||||
type_: box ty.clean(cx),
|
||||
},
|
||||
ty::FnDef(..) |
|
||||
@ -2080,7 +2062,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
|
||||
deprecation: cx.deprecation(self.id).clean(cx),
|
||||
inner: StaticItem(Static {
|
||||
type_: self.type_.clean(cx),
|
||||
mutability: self.mutability.clean(cx),
|
||||
mutability: self.mutability,
|
||||
expr: print_const_expr(cx, self.expr),
|
||||
}),
|
||||
}
|
||||
@ -2105,15 +2087,6 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
|
||||
}
|
||||
}
|
||||
|
||||
impl Clean<Mutability> for hir::Mutability {
|
||||
fn clean(&self, _: &DocContext<'_>) -> Mutability {
|
||||
match self {
|
||||
&hir::Mutability::Mut => Mutable,
|
||||
&hir::Mutability::Not => Immutable,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Clean<ImplPolarity> for ty::ImplPolarity {
|
||||
fn clean(&self, _: &DocContext<'_>) -> ImplPolarity {
|
||||
match self {
|
||||
@ -2303,7 +2276,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
|
||||
hir::ForeignItemKind::Static(ref ty, mutbl) => {
|
||||
ForeignStaticItem(Static {
|
||||
type_: ty.clean(cx),
|
||||
mutability: mutbl.clean(cx),
|
||||
mutability: *mutbl,
|
||||
expr: String::new(),
|
||||
})
|
||||
}
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
use rustc::middle::lang_items;
|
||||
use rustc::middle::stability;
|
||||
use rustc::hir;
|
||||
use rustc::hir::{self, Mutability};
|
||||
use rustc::hir::def::Res;
|
||||
use rustc::hir::def_id::{CrateNum, DefId};
|
||||
use rustc::ty::layout::VariantIdx;
|
||||
@ -1450,12 +1450,6 @@ pub struct Constant {
|
||||
pub expr: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Copy, Hash)]
|
||||
pub enum Mutability {
|
||||
Mutable,
|
||||
Immutable,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
pub enum ImplPolarity {
|
||||
Positive,
|
||||
|
@ -670,8 +670,8 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) ->
|
||||
clean::Never => primitive_link(f, PrimitiveType::Never, "!"),
|
||||
clean::RawPointer(m, ref t) => {
|
||||
let m = match m {
|
||||
clean::Immutable => "const",
|
||||
clean::Mutable => "mut",
|
||||
hir::Mutability::Mut => "mut",
|
||||
hir::Mutability::Not => "const",
|
||||
};
|
||||
match **t {
|
||||
clean::Generic(_) | clean::ResolvedPath {is_generic: true, ..} => {
|
||||
@ -1082,6 +1082,15 @@ fn print_with_space(&self) -> &str {
|
||||
}
|
||||
}
|
||||
|
||||
impl PrintWithSpace for hir::Mutability {
|
||||
fn print_with_space(&self) -> &str {
|
||||
match self {
|
||||
hir::Mutability::Not => "",
|
||||
hir::Mutability::Mut => "mut ",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl clean::Import {
|
||||
crate fn print(&self) -> impl fmt::Display + '_ {
|
||||
display_fn(move |f| {
|
||||
@ -1151,15 +1160,6 @@ impl clean::TypeBinding {
|
||||
}
|
||||
}
|
||||
|
||||
impl clean::Mutability {
|
||||
crate fn print_with_space(&self) -> &str {
|
||||
match self {
|
||||
clean::Immutable => "",
|
||||
clean::Mutable => "mut ",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
crate fn print_abi_with_space(abi: Abi) -> impl fmt::Display {
|
||||
display_fn(move |f| {
|
||||
let quot = if f.alternate() { "\"" } else { """ };
|
||||
|
@ -54,12 +54,12 @@
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::middle::privacy::AccessLevels;
|
||||
use rustc::middle::stability;
|
||||
use rustc::hir;
|
||||
use rustc::hir::{self, Mutability};
|
||||
use rustc::util::nodemap::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::flock;
|
||||
use rustc_feature::UnstableFeatures;
|
||||
|
||||
use crate::clean::{self, AttributesExt, Deprecation, GetDefId, SelfTy, Mutability};
|
||||
use crate::clean::{self, AttributesExt, Deprecation, GetDefId, SelfTy};
|
||||
use crate::config::RenderOptions;
|
||||
use crate::docfs::{DocFS, ErrorStorage, PathError};
|
||||
use crate::doctree;
|
||||
@ -3298,7 +3298,7 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool) -> bool {
|
||||
let (by_mut_ref, by_box, by_value) = match self_ty {
|
||||
SelfTy::SelfBorrowed(_, mutability) |
|
||||
SelfTy::SelfExplicit(clean::BorrowedRef { mutability, .. }) => {
|
||||
(mutability == Mutability::Mutable, false, false)
|
||||
(mutability == Mutability::Mut, false, false)
|
||||
},
|
||||
SelfTy::SelfExplicit(clean::ResolvedPath { did, .. }) => {
|
||||
(false, Some(did) == cache().owned_box_did, false)
|
||||
|
Loading…
Reference in New Issue
Block a user