mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-05 14:37:37 +00:00
Auto merge of #59276 - oli-obk:cleanups, r=eddyb
Cleanup (pretty) printing of `ty::Const` r? @eddyb addresses5cd2806621 (r266243236)
and5cd2806621 (r266243336)
This commit is contained in:
commit
f492693982
2
.gitignore
vendored
2
.gitignore
vendored
@ -12,7 +12,7 @@ __pycache__/
|
|||||||
.project
|
.project
|
||||||
.settings/
|
.settings/
|
||||||
.valgrindrc
|
.valgrindrc
|
||||||
.vscode/
|
.vscode
|
||||||
.favorites.json
|
.favorites.json
|
||||||
/*-*-*-*/
|
/*-*-*-*/
|
||||||
/*-*-*/
|
/*-*-*/
|
||||||
|
@ -462,6 +462,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||||||
type Region = !;
|
type Region = !;
|
||||||
type Type = !;
|
type Type = !;
|
||||||
type DynExistential = !;
|
type DynExistential = !;
|
||||||
|
type Const = !;
|
||||||
|
|
||||||
fn tcx<'a>(&'a self) -> TyCtxt<'a, 'gcx, 'tcx> {
|
fn tcx<'a>(&'a self) -> TyCtxt<'a, 'gcx, 'tcx> {
|
||||||
self.tcx
|
self.tcx
|
||||||
@ -488,6 +489,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||||||
Err(NonTrivialPath)
|
Err(NonTrivialPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn print_const(
|
||||||
|
self,
|
||||||
|
_ct: &'tcx ty::Const<'tcx>,
|
||||||
|
) -> Result<Self::Const, Self::Error> {
|
||||||
|
Err(NonTrivialPath)
|
||||||
|
}
|
||||||
|
|
||||||
fn path_crate(
|
fn path_crate(
|
||||||
self,
|
self,
|
||||||
cnum: CrateNum,
|
cnum: CrateNum,
|
||||||
|
@ -260,7 +260,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
|
|||||||
|
|
||||||
ConstValue::Param(_) |
|
ConstValue::Param(_) |
|
||||||
ConstValue::Scalar(_) |
|
ConstValue::Scalar(_) |
|
||||||
ConstValue::Slice(..) |
|
ConstValue::Slice { .. } |
|
||||||
ConstValue::ByRef(..) |
|
ConstValue::ByRef(..) |
|
||||||
ConstValue::Unevaluated(..) => {}
|
ConstValue::Unevaluated(..) => {}
|
||||||
}
|
}
|
||||||
|
@ -791,6 +791,7 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> {
|
|||||||
type Region = ();
|
type Region = ();
|
||||||
type Type = ();
|
type Type = ();
|
||||||
type DynExistential = ();
|
type DynExistential = ();
|
||||||
|
type Const = ();
|
||||||
|
|
||||||
fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
|
fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
|
||||||
self.tcx
|
self.tcx
|
||||||
@ -811,6 +812,13 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn print_const(
|
||||||
|
self,
|
||||||
|
_ct: &'tcx ty::Const<'tcx>,
|
||||||
|
) -> Result<Self::Const, Self::Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn path_crate(self, cnum: CrateNum) -> Result<Self::Path, Self::Error> {
|
fn path_crate(self, cnum: CrateNum) -> Result<Self::Path, Self::Error> {
|
||||||
Ok(vec![self.tcx.original_crate_name(cnum).as_str()])
|
Ok(vec![self.tcx.original_crate_name(cnum).as_str()])
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ impl ErrorHandled {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub type ConstEvalRawResult<'tcx> = Result<RawConst<'tcx>, ErrorHandled>;
|
pub type ConstEvalRawResult<'tcx> = Result<RawConst<'tcx>, ErrorHandled>;
|
||||||
pub type ConstEvalResult<'tcx> = Result<ty::Const<'tcx>, ErrorHandled>;
|
pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ErrorHandled>;
|
||||||
|
|
||||||
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
|
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
|
||||||
pub struct ConstEvalErr<'tcx> {
|
pub struct ConstEvalErr<'tcx> {
|
||||||
|
@ -35,14 +35,12 @@ pub enum ConstValue<'tcx> {
|
|||||||
/// Not using the enum `Value` to encode that this must not be `Undef`.
|
/// Not using the enum `Value` to encode that this must not be `Undef`.
|
||||||
Scalar(Scalar),
|
Scalar(Scalar),
|
||||||
|
|
||||||
/// Used only for slices and strings (`&[T]`, `&str`, `*const [T]`, `*mut str`, `Box<str>`,
|
/// Used only for `&[u8]` and `&str`
|
||||||
/// etc.).
|
Slice {
|
||||||
///
|
data: &'tcx Allocation,
|
||||||
/// Empty slices don't necessarily have an address backed by an `AllocId`, thus we also need to
|
start: usize,
|
||||||
/// enable integer pointers. The `Scalar` type covers exactly those two cases. While we could
|
end: usize,
|
||||||
/// create dummy-`AllocId`s, the additional code effort for the conversions doesn't seem worth
|
},
|
||||||
/// it.
|
|
||||||
Slice(Scalar, u64),
|
|
||||||
|
|
||||||
/// An allocation together with a pointer into the allocation.
|
/// An allocation together with a pointer into the allocation.
|
||||||
/// Invariant: the pointer's `AllocId` resolves to the allocation.
|
/// Invariant: the pointer's `AllocId` resolves to the allocation.
|
||||||
@ -54,7 +52,7 @@ pub enum ConstValue<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
static_assert_size!(ConstValue<'_>, 40);
|
static_assert_size!(ConstValue<'_>, 32);
|
||||||
|
|
||||||
impl<'tcx> ConstValue<'tcx> {
|
impl<'tcx> ConstValue<'tcx> {
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -65,7 +63,7 @@ impl<'tcx> ConstValue<'tcx> {
|
|||||||
ConstValue::Placeholder(_) |
|
ConstValue::Placeholder(_) |
|
||||||
ConstValue::ByRef(..) |
|
ConstValue::ByRef(..) |
|
||||||
ConstValue::Unevaluated(..) |
|
ConstValue::Unevaluated(..) |
|
||||||
ConstValue::Slice(..) => None,
|
ConstValue::Slice { .. } => None,
|
||||||
ConstValue::Scalar(val) => Some(val),
|
ConstValue::Scalar(val) => Some(val),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -79,14 +77,6 @@ impl<'tcx> ConstValue<'tcx> {
|
|||||||
pub fn try_to_ptr(&self) -> Option<Pointer> {
|
pub fn try_to_ptr(&self) -> Option<Pointer> {
|
||||||
self.try_to_scalar()?.to_ptr().ok()
|
self.try_to_scalar()?.to_ptr().ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn new_slice(
|
|
||||||
val: Scalar,
|
|
||||||
len: u64,
|
|
||||||
) -> Self {
|
|
||||||
ConstValue::Slice(val, len)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A `Scalar` represents an immediate, primitive value existing outside of a
|
/// A `Scalar` represents an immediate, primitive value existing outside of a
|
||||||
|
@ -9,8 +9,6 @@ use crate::hir::def_id::DefId;
|
|||||||
use crate::hir::{self, InlineAsm as HirInlineAsm};
|
use crate::hir::{self, InlineAsm as HirInlineAsm};
|
||||||
use crate::mir::interpret::{ConstValue, InterpError, Scalar};
|
use crate::mir::interpret::{ConstValue, InterpError, Scalar};
|
||||||
use crate::mir::visit::MirVisitable;
|
use crate::mir::visit::MirVisitable;
|
||||||
use rustc_apfloat::ieee::{Double, Single};
|
|
||||||
use rustc_apfloat::Float;
|
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_data_structures::graph::dominators::{dominators, Dominators};
|
use rustc_data_structures::graph::dominators::{dominators, Dominators};
|
||||||
use rustc_data_structures::graph::{self, GraphPredecessors, GraphSuccessors};
|
use rustc_data_structures::graph::{self, GraphPredecessors, GraphSuccessors};
|
||||||
@ -21,13 +19,13 @@ use rustc_macros::HashStable;
|
|||||||
use crate::rustc_serialize::{self as serialize};
|
use crate::rustc_serialize::{self as serialize};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::fmt::{self, Debug, Formatter, Write};
|
use std::fmt::{self, Debug, Formatter, Write, Display};
|
||||||
use std::iter::FusedIterator;
|
use std::iter::FusedIterator;
|
||||||
use std::ops::{Index, IndexMut};
|
use std::ops::{Index, IndexMut};
|
||||||
use std::slice;
|
use std::slice;
|
||||||
use std::vec::IntoIter;
|
use std::vec::IntoIter;
|
||||||
use std::{iter, mem, option, u32};
|
use std::{iter, mem, option, u32};
|
||||||
use syntax::ast::{self, Name};
|
use syntax::ast::Name;
|
||||||
use syntax::symbol::{InternedString, Symbol};
|
use syntax::symbol::{InternedString, Symbol};
|
||||||
use syntax_pos::{Span, DUMMY_SP};
|
use syntax_pos::{Span, DUMMY_SP};
|
||||||
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
|
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
|
||||||
@ -1662,16 +1660,14 @@ impl<'tcx> TerminatorKind<'tcx> {
|
|||||||
switch_ty,
|
switch_ty,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let size = ty::tls::with(|tcx| {
|
ty::tls::with(|tcx| {
|
||||||
let param_env = ty::ParamEnv::empty();
|
let param_env = ty::ParamEnv::empty();
|
||||||
let switch_ty = tcx.lift_to_global(&switch_ty).unwrap();
|
let switch_ty = tcx.lift_to_global(&switch_ty).unwrap();
|
||||||
tcx.layout_of(param_env.and(switch_ty)).unwrap().size
|
let size = tcx.layout_of(param_env.and(switch_ty)).unwrap().size;
|
||||||
});
|
|
||||||
values
|
values
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&u| {
|
.map(|&u| {
|
||||||
let mut s = String::new();
|
tcx.mk_const(ty::Const {
|
||||||
let c = ty::Const {
|
|
||||||
val: ConstValue::Scalar(
|
val: ConstValue::Scalar(
|
||||||
Scalar::Bits {
|
Scalar::Bits {
|
||||||
bits: u,
|
bits: u,
|
||||||
@ -1679,11 +1675,10 @@ impl<'tcx> TerminatorKind<'tcx> {
|
|||||||
}.into(),
|
}.into(),
|
||||||
),
|
),
|
||||||
ty: switch_ty,
|
ty: switch_ty,
|
||||||
};
|
}).to_string().into()
|
||||||
fmt_const_val(&mut s, c).unwrap();
|
|
||||||
s.into()
|
|
||||||
}).chain(iter::once("otherwise".into()))
|
}).chain(iter::once("otherwise".into()))
|
||||||
.collect()
|
.collect()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
Call {
|
Call {
|
||||||
destination: Some(_),
|
destination: Some(_),
|
||||||
@ -2331,9 +2326,7 @@ impl<'tcx> Operand<'tcx> {
|
|||||||
span,
|
span,
|
||||||
ty,
|
ty,
|
||||||
user_ty: None,
|
user_ty: None,
|
||||||
literal: tcx.mk_const(
|
literal: ty::Const::zero_sized(tcx, ty),
|
||||||
ty::Const::zero_sized(ty),
|
|
||||||
),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2827,67 +2820,15 @@ newtype_index! {
|
|||||||
|
|
||||||
impl<'tcx> Debug for Constant<'tcx> {
|
impl<'tcx> Debug for Constant<'tcx> {
|
||||||
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
|
||||||
write!(fmt, "const ")?;
|
write!(fmt, "{}", self)
|
||||||
fmt_const_val(fmt, *self.literal)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Write a `ConstValue` in a way closer to the original source code than the `Debug` output.
|
|
||||||
pub fn fmt_const_val(f: &mut impl Write, const_val: ty::Const<'_>) -> fmt::Result {
|
|
||||||
use crate::ty::TyKind::*;
|
|
||||||
let value = const_val.val;
|
|
||||||
let ty = const_val.ty;
|
|
||||||
// print some primitives
|
|
||||||
if let ConstValue::Scalar(Scalar::Bits { bits, .. }) = value {
|
|
||||||
match ty.sty {
|
|
||||||
Bool if bits == 0 => return write!(f, "false"),
|
|
||||||
Bool if bits == 1 => return write!(f, "true"),
|
|
||||||
Float(ast::FloatTy::F32) => return write!(f, "{}f32", Single::from_bits(bits)),
|
|
||||||
Float(ast::FloatTy::F64) => return write!(f, "{}f64", Double::from_bits(bits)),
|
|
||||||
Uint(ui) => return write!(f, "{:?}{}", bits, ui),
|
|
||||||
Int(i) => {
|
|
||||||
let bit_width = ty::tls::with(|tcx| {
|
|
||||||
let ty = tcx.lift_to_global(&ty).unwrap();
|
|
||||||
tcx.layout_of(ty::ParamEnv::empty().and(ty))
|
|
||||||
.unwrap()
|
|
||||||
.size
|
|
||||||
.bits()
|
|
||||||
});
|
|
||||||
let shift = 128 - bit_width;
|
|
||||||
return write!(f, "{:?}{}", ((bits as i128) << shift) >> shift, i);
|
|
||||||
}
|
|
||||||
Char => return write!(f, "{:?}", ::std::char::from_u32(bits as u32).unwrap()),
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// print function definitions
|
|
||||||
if let FnDef(did, _) = ty.sty {
|
|
||||||
return write!(f, "{}", def_path_str(did));
|
|
||||||
}
|
|
||||||
// print string literals
|
|
||||||
if let ConstValue::Slice(ptr, len) = value {
|
|
||||||
if let Scalar::Ptr(ptr) = ptr {
|
|
||||||
if let Ref(_, &ty::TyS { sty: Str, .. }, _) = ty.sty {
|
|
||||||
return ty::tls::with(|tcx| {
|
|
||||||
let alloc = tcx.alloc_map.lock().get(ptr.alloc_id);
|
|
||||||
if let Some(interpret::AllocKind::Memory(alloc)) = alloc {
|
|
||||||
assert_eq!(len as usize as u64, len);
|
|
||||||
let slice =
|
|
||||||
&alloc.bytes[(ptr.offset.bytes() as usize)..][..(len as usize)];
|
|
||||||
let s = ::std::str::from_utf8(slice).expect("non utf8 str from miri");
|
|
||||||
write!(f, "{:?}", s)
|
|
||||||
} else {
|
|
||||||
write!(f, "pointer to erroneous constant {:?}, {:?}", ptr, len)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// just raw dump everything else
|
|
||||||
write!(f, "{:?} : {}", value, ty)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn def_path_str(def_id: DefId) -> String {
|
impl<'tcx> Display for Constant<'tcx> {
|
||||||
ty::tls::with(|tcx| tcx.def_path_str(def_id))
|
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(fmt, "const ")?;
|
||||||
|
write!(fmt, "{}", self.literal)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> graph::DirectedGraph for Mir<'tcx> {
|
impl<'tcx> graph::DirectedGraph for Mir<'tcx> {
|
||||||
|
@ -412,7 +412,6 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a,
|
|||||||
};
|
};
|
||||||
if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) {
|
if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) {
|
||||||
let substs = tcx.lift_to_global(&substs).unwrap();
|
let substs = tcx.lift_to_global(&substs).unwrap();
|
||||||
let evaluated = tcx.mk_const(evaluated);
|
|
||||||
let evaluated = evaluated.subst(tcx, substs);
|
let evaluated = evaluated.subst(tcx, substs);
|
||||||
return evaluated;
|
return evaluated;
|
||||||
}
|
}
|
||||||
@ -426,7 +425,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a,
|
|||||||
promoted: None
|
promoted: None
|
||||||
};
|
};
|
||||||
if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) {
|
if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) {
|
||||||
return tcx.mk_const(evaluated);
|
return evaluated;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -202,7 +202,6 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx
|
|||||||
};
|
};
|
||||||
if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) {
|
if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) {
|
||||||
let substs = tcx.lift_to_global(&substs).unwrap();
|
let substs = tcx.lift_to_global(&substs).unwrap();
|
||||||
let evaluated = tcx.mk_const(evaluated);
|
|
||||||
let evaluated = evaluated.subst(tcx, substs);
|
let evaluated = evaluated.subst(tcx, substs);
|
||||||
return evaluated;
|
return evaluated;
|
||||||
}
|
}
|
||||||
@ -216,7 +215,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx
|
|||||||
promoted: None,
|
promoted: None,
|
||||||
};
|
};
|
||||||
if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) {
|
if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) {
|
||||||
return tcx.mk_const(evaluated);
|
return evaluated;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ use crate::middle::lang_items;
|
|||||||
use crate::middle::resolve_lifetime::{self, ObjectLifetimeDefault};
|
use crate::middle::resolve_lifetime::{self, ObjectLifetimeDefault};
|
||||||
use crate::middle::stability;
|
use crate::middle::stability;
|
||||||
use crate::mir::{self, Mir, interpret, ProjectionKind};
|
use crate::mir::{self, Mir, interpret, ProjectionKind};
|
||||||
use crate::mir::interpret::{ConstValue, Allocation};
|
use crate::mir::interpret::{ConstValue, Allocation, Scalar};
|
||||||
use crate::ty::subst::{Kind, InternalSubsts, SubstsRef, Subst};
|
use crate::ty::subst::{Kind, InternalSubsts, SubstsRef, Subst};
|
||||||
use crate::ty::ReprOptions;
|
use crate::ty::ReprOptions;
|
||||||
use crate::traits;
|
use crate::traits;
|
||||||
@ -1000,7 +1000,10 @@ impl<'tcx> CommonConsts<'tcx> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
CommonConsts {
|
CommonConsts {
|
||||||
err: mk_const(ty::Const::zero_sized(types.err)),
|
err: mk_const(ty::Const {
|
||||||
|
val: ConstValue::Scalar(Scalar::Bits { bits: 0, size: 0 }),
|
||||||
|
ty: types.err,
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1822,14 +1825,6 @@ nop_list_lift!{ProjectionKind => ProjectionKind}
|
|||||||
// this is the impl for `&'a InternalSubsts<'a>`
|
// this is the impl for `&'a InternalSubsts<'a>`
|
||||||
nop_list_lift!{Kind<'a> => Kind<'tcx>}
|
nop_list_lift!{Kind<'a> => Kind<'tcx>}
|
||||||
|
|
||||||
impl<'a, 'tcx> Lift<'tcx> for &'a mir::interpret::Allocation {
|
|
||||||
type Lifted = &'tcx mir::interpret::Allocation;
|
|
||||||
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
|
|
||||||
assert!(tcx.global_arenas.const_allocs.in_arena(*self as *const _));
|
|
||||||
Some(unsafe { mem::transmute(*self) })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod tls {
|
pub mod tls {
|
||||||
use super::{GlobalCtxt, TyCtxt, ptr_eq};
|
use super::{GlobalCtxt, TyCtxt, ptr_eq};
|
||||||
|
|
||||||
@ -2594,9 +2589,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn mk_array(self, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> {
|
pub fn mk_array(self, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> {
|
||||||
self.mk_ty(Array(ty, self.mk_const(
|
self.mk_ty(Array(ty, ty::Const::from_usize(self.global_tcx(), n)))
|
||||||
ty::Const::from_usize(self.global_tcx(), n)
|
|
||||||
)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -939,7 +939,7 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
|
|||||||
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
|
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
|
||||||
let flags = FlagComputation::for_const(c);
|
let flags = FlagComputation::for_const(c);
|
||||||
debug!("HasTypeFlagsVisitor: c={:?} c.flags={:?} self.flags={:?}", c, flags, self.flags);
|
debug!("HasTypeFlagsVisitor: c={:?} c.flags={:?} self.flags={:?}", c, flags, self.flags);
|
||||||
flags.intersects(self.flags) || c.super_visit_with(self)
|
flags.intersects(self.flags)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ pub trait Printer<'gcx: 'tcx, 'tcx>: Sized {
|
|||||||
type Region;
|
type Region;
|
||||||
type Type;
|
type Type;
|
||||||
type DynExistential;
|
type DynExistential;
|
||||||
|
type Const;
|
||||||
|
|
||||||
fn tcx(&'a self) -> TyCtxt<'a, 'gcx, 'tcx>;
|
fn tcx(&'a self) -> TyCtxt<'a, 'gcx, 'tcx>;
|
||||||
|
|
||||||
@ -66,6 +67,11 @@ pub trait Printer<'gcx: 'tcx, 'tcx>: Sized {
|
|||||||
predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
|
predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
|
||||||
) -> Result<Self::DynExistential, Self::Error>;
|
) -> Result<Self::DynExistential, Self::Error>;
|
||||||
|
|
||||||
|
fn print_const(
|
||||||
|
self,
|
||||||
|
ct: &'tcx ty::Const<'tcx>,
|
||||||
|
) -> Result<Self::Const, Self::Error>;
|
||||||
|
|
||||||
fn path_crate(
|
fn path_crate(
|
||||||
self,
|
self,
|
||||||
cnum: CrateNum,
|
cnum: CrateNum,
|
||||||
@ -325,3 +331,11 @@ impl<'gcx: 'tcx, 'tcx, P: Printer<'gcx, 'tcx>> Print<'gcx, 'tcx, P>
|
|||||||
cx.print_dyn_existential(self)
|
cx.print_dyn_existential(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'gcx: 'tcx, 'tcx, P: Printer<'gcx, 'tcx>> Print<'gcx, 'tcx, P> for &'tcx ty::Const<'tcx> {
|
||||||
|
type Output = P::Const;
|
||||||
|
type Error = P::Error;
|
||||||
|
fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
|
||||||
|
cx.print_const(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,12 +1,16 @@
|
|||||||
use crate::hir;
|
use crate::hir;
|
||||||
use crate::hir::def::Namespace;
|
use crate::hir::def::{Namespace, DefKind};
|
||||||
use crate::hir::map::{DefPathData, DisambiguatedDefPathData};
|
use crate::hir::map::{DefPathData, DisambiguatedDefPathData};
|
||||||
use crate::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
|
use crate::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
|
||||||
use crate::middle::cstore::{ExternCrate, ExternCrateSource};
|
use crate::middle::cstore::{ExternCrate, ExternCrateSource};
|
||||||
use crate::middle::region;
|
use crate::middle::region;
|
||||||
use crate::ty::{self, DefIdTree, ParamConst, Ty, TyCtxt, TypeFoldable};
|
use crate::ty::{self, DefIdTree, ParamConst, Ty, TyCtxt, TypeFoldable};
|
||||||
use crate::ty::subst::{Kind, Subst, UnpackedKind};
|
use crate::ty::subst::{Kind, Subst, UnpackedKind};
|
||||||
use crate::mir::interpret::ConstValue;
|
use crate::ty::layout::Size;
|
||||||
|
use crate::mir::interpret::{ConstValue, sign_extend, Scalar};
|
||||||
|
use syntax::ast;
|
||||||
|
use rustc_apfloat::ieee::{Double, Single};
|
||||||
|
use rustc_apfloat::Float;
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
use syntax::symbol::{kw, InternedString};
|
use syntax::symbol::{kw, InternedString};
|
||||||
|
|
||||||
@ -169,6 +173,7 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>:
|
|||||||
Region = Self,
|
Region = Self,
|
||||||
Type = Self,
|
Type = Self,
|
||||||
DynExistential = Self,
|
DynExistential = Self,
|
||||||
|
Const = Self,
|
||||||
> +
|
> +
|
||||||
fmt::Write
|
fmt::Write
|
||||||
{
|
{
|
||||||
@ -661,12 +666,10 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>:
|
|||||||
},
|
},
|
||||||
ty::Array(ty, sz) => {
|
ty::Array(ty, sz) => {
|
||||||
p!(write("["), print(ty), write("; "));
|
p!(write("["), print(ty), write("; "));
|
||||||
match sz.val {
|
if let Some(n) = sz.assert_usize(self.tcx()) {
|
||||||
ConstValue::Unevaluated(..) |
|
p!(write("{}", n));
|
||||||
ConstValue::Infer(..) => p!(write("_")),
|
} else {
|
||||||
ConstValue::Param(ParamConst { name, .. }) =>
|
p!(write("_"));
|
||||||
p!(write("{}", name)),
|
|
||||||
_ => p!(write("{}", sz.unwrap_usize(self.tcx()))),
|
|
||||||
}
|
}
|
||||||
p!(write("]"))
|
p!(write("]"))
|
||||||
}
|
}
|
||||||
@ -804,6 +807,113 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>:
|
|||||||
|
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn pretty_print_const(
|
||||||
|
mut self,
|
||||||
|
ct: &'tcx ty::Const<'tcx>,
|
||||||
|
) -> Result<Self::Const, Self::Error> {
|
||||||
|
define_scoped_cx!(self);
|
||||||
|
|
||||||
|
let u8 = self.tcx().types.u8;
|
||||||
|
if let ty::FnDef(did, substs) = ct.ty.sty {
|
||||||
|
p!(print_value_path(did, substs));
|
||||||
|
return Ok(self);
|
||||||
|
}
|
||||||
|
if let ConstValue::Unevaluated(did, substs) = ct.val {
|
||||||
|
match self.tcx().def_kind(did) {
|
||||||
|
| Some(DefKind::Static)
|
||||||
|
| Some(DefKind::Const)
|
||||||
|
| Some(DefKind::AssociatedConst) => 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))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return Ok(self);
|
||||||
|
}
|
||||||
|
if let ConstValue::Infer(..) = ct.val {
|
||||||
|
p!(write("_: "), print(ct.ty));
|
||||||
|
return Ok(self);
|
||||||
|
}
|
||||||
|
if let ConstValue::Param(ParamConst { name, .. }) = ct.val {
|
||||||
|
p!(write("{}", name));
|
||||||
|
return Ok(self);
|
||||||
|
}
|
||||||
|
if let ConstValue::Scalar(Scalar::Bits { bits, .. }) = ct.val {
|
||||||
|
match ct.ty.sty {
|
||||||
|
ty::Bool => {
|
||||||
|
p!(write("{}", if bits == 0 { "false" } else { "true" }));
|
||||||
|
return Ok(self);
|
||||||
|
},
|
||||||
|
ty::Float(ast::FloatTy::F32) => {
|
||||||
|
p!(write("{}f32", Single::from_bits(bits)));
|
||||||
|
return Ok(self);
|
||||||
|
},
|
||||||
|
ty::Float(ast::FloatTy::F64) => {
|
||||||
|
p!(write("{}f64", Double::from_bits(bits)));
|
||||||
|
return Ok(self);
|
||||||
|
},
|
||||||
|
ty::Uint(ui) => {
|
||||||
|
p!(write("{}{}", bits, ui));
|
||||||
|
return Ok(self);
|
||||||
|
},
|
||||||
|
ty::Int(i) =>{
|
||||||
|
let ty = self.tcx().lift_to_global(&ct.ty).unwrap();
|
||||||
|
let size = self.tcx().layout_of(ty::ParamEnv::empty().and(ty))
|
||||||
|
.unwrap()
|
||||||
|
.size;
|
||||||
|
p!(write("{}{}", sign_extend(bits, size) as i128, i));
|
||||||
|
return Ok(self);
|
||||||
|
},
|
||||||
|
ty::Char => {
|
||||||
|
p!(write("{:?}", ::std::char::from_u32(bits as u32).unwrap()));
|
||||||
|
return Ok(self);
|
||||||
|
}
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let ty::Ref(_, ref_ty, _) = ct.ty.sty {
|
||||||
|
let byte_str = match (ct.val, &ref_ty.sty) {
|
||||||
|
(ConstValue::Scalar(Scalar::Ptr(ptr)), ty::Array(t, n)) if *t == u8 => {
|
||||||
|
let n = n.unwrap_usize(self.tcx());
|
||||||
|
Some(self.tcx()
|
||||||
|
.alloc_map.lock()
|
||||||
|
.unwrap_memory(ptr.alloc_id)
|
||||||
|
.get_bytes(&self.tcx(), ptr, Size::from_bytes(n)).unwrap())
|
||||||
|
},
|
||||||
|
(ConstValue::Slice { data, start, end }, ty::Slice(t)) if *t == u8 => {
|
||||||
|
Some(&data.bytes[start..end])
|
||||||
|
},
|
||||||
|
(ConstValue::Slice { data, start, end }, ty::Str) => {
|
||||||
|
let slice = &data.bytes[start..end];
|
||||||
|
let s = ::std::str::from_utf8(slice)
|
||||||
|
.expect("non utf8 str from miri");
|
||||||
|
p!(write("{:?}", s));
|
||||||
|
return Ok(self);
|
||||||
|
},
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
if let Some(byte_str) = byte_str {
|
||||||
|
p!(write("b\""));
|
||||||
|
for &c in byte_str {
|
||||||
|
for e in std::ascii::escape_default(c) {
|
||||||
|
self.write_char(e as char)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p!(write("\""));
|
||||||
|
return Ok(self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p!(write("{:?} : ", ct.val), print(ct.ty));
|
||||||
|
|
||||||
|
Ok(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// HACK(eddyb) boxed to avoid moving around a large struct by-value.
|
// HACK(eddyb) boxed to avoid moving around a large struct by-value.
|
||||||
@ -896,6 +1006,7 @@ impl<F: fmt::Write> Printer<'gcx, 'tcx> for FmtPrinter<'_, 'gcx, 'tcx, F> {
|
|||||||
type Region = Self;
|
type Region = Self;
|
||||||
type Type = Self;
|
type Type = Self;
|
||||||
type DynExistential = Self;
|
type DynExistential = Self;
|
||||||
|
type Const = Self;
|
||||||
|
|
||||||
fn tcx(&'a self) -> TyCtxt<'a, 'gcx, 'tcx> {
|
fn tcx(&'a self) -> TyCtxt<'a, 'gcx, 'tcx> {
|
||||||
self.tcx
|
self.tcx
|
||||||
@ -971,6 +1082,13 @@ impl<F: fmt::Write> Printer<'gcx, 'tcx> for FmtPrinter<'_, 'gcx, 'tcx, F> {
|
|||||||
self.pretty_print_dyn_existential(predicates)
|
self.pretty_print_dyn_existential(predicates)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn print_const(
|
||||||
|
self,
|
||||||
|
ct: &'tcx ty::Const<'tcx>,
|
||||||
|
) -> Result<Self::Const, Self::Error> {
|
||||||
|
self.pretty_print_const(ct)
|
||||||
|
}
|
||||||
|
|
||||||
fn path_crate(
|
fn path_crate(
|
||||||
mut self,
|
mut self,
|
||||||
cnum: CrateNum,
|
cnum: CrateNum,
|
||||||
@ -1444,6 +1562,7 @@ impl fmt::Display for ty::RegionKind {
|
|||||||
forward_display_to_print! {
|
forward_display_to_print! {
|
||||||
Ty<'tcx>,
|
Ty<'tcx>,
|
||||||
&'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
|
&'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
|
||||||
|
&'tcx ty::Const<'tcx>,
|
||||||
|
|
||||||
// HACK(eddyb) these are exhaustive instead of generic,
|
// HACK(eddyb) these are exhaustive instead of generic,
|
||||||
// because `for<'gcx: 'tcx, 'tcx>` isn't possible yet.
|
// because `for<'gcx: 'tcx, 'tcx>` isn't possible yet.
|
||||||
@ -1533,15 +1652,6 @@ define_print_and_forward_display! {
|
|||||||
p!(print_def_path(self.def_id, self.substs));
|
p!(print_def_path(self.def_id, self.substs));
|
||||||
}
|
}
|
||||||
|
|
||||||
&'tcx ty::Const<'tcx> {
|
|
||||||
match self.val {
|
|
||||||
ConstValue::Unevaluated(..) |
|
|
||||||
ConstValue::Infer(..) => p!(write("_")),
|
|
||||||
ConstValue::Param(ParamConst { name, .. }) => p!(write("{}", name)),
|
|
||||||
_ => p!(write("{:?}", self)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ty::ParamTy {
|
ty::ParamTy {
|
||||||
p!(write("{}", self.name))
|
p!(write("{}", self.name))
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
use crate::hir::def::Namespace;
|
use crate::hir::def::Namespace;
|
||||||
use crate::mir::ProjectionKind;
|
use crate::mir::ProjectionKind;
|
||||||
use crate::mir::interpret::ConstValue;
|
use crate::mir::interpret::ConstValue;
|
||||||
use crate::ty::{self, Lift, Ty, TyCtxt, ConstVid, InferConst};
|
use crate::ty::{self, Lift, Ty, TyCtxt, InferConst};
|
||||||
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
|
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
|
||||||
use crate::ty::print::{FmtPrinter, Printer};
|
use crate::ty::print::{FmtPrinter, Printer};
|
||||||
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
|
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
|
||||||
@ -14,7 +14,6 @@ use smallvec::SmallVec;
|
|||||||
use crate::mir::interpret;
|
use crate::mir::interpret;
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::marker::PhantomData;
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
impl fmt::Debug for ty::GenericParamDef {
|
impl fmt::Debug for ty::GenericParamDef {
|
||||||
@ -788,16 +787,6 @@ BraceStructLiftImpl! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> Lift<'tcx> for ConstVid<'a> {
|
|
||||||
type Lifted = ConstVid<'tcx>;
|
|
||||||
fn lift_to_tcx<'b, 'gcx>(&self, _: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
|
|
||||||
Some(ConstVid {
|
|
||||||
index: self.index,
|
|
||||||
phantom: PhantomData,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// TypeFoldable implementations.
|
// TypeFoldable implementations.
|
||||||
//
|
//
|
||||||
@ -1356,7 +1345,7 @@ impl<'tcx> TypeFoldable<'tcx> for ConstValue<'tcx> {
|
|||||||
ConstValue::Param(p) => ConstValue::Param(p.fold_with(folder)),
|
ConstValue::Param(p) => ConstValue::Param(p.fold_with(folder)),
|
||||||
ConstValue::Placeholder(p) => ConstValue::Placeholder(p),
|
ConstValue::Placeholder(p) => ConstValue::Placeholder(p),
|
||||||
ConstValue::Scalar(a) => ConstValue::Scalar(a),
|
ConstValue::Scalar(a) => ConstValue::Scalar(a),
|
||||||
ConstValue::Slice(a, b) => ConstValue::Slice(a, b),
|
ConstValue::Slice { data, start, end } => ConstValue::Slice { data, start, end },
|
||||||
ConstValue::Unevaluated(did, substs)
|
ConstValue::Unevaluated(did, substs)
|
||||||
=> ConstValue::Unevaluated(did, substs.fold_with(folder)),
|
=> ConstValue::Unevaluated(did, substs.fold_with(folder)),
|
||||||
}
|
}
|
||||||
@ -1369,7 +1358,7 @@ impl<'tcx> TypeFoldable<'tcx> for ConstValue<'tcx> {
|
|||||||
ConstValue::Param(p) => p.visit_with(visitor),
|
ConstValue::Param(p) => p.visit_with(visitor),
|
||||||
ConstValue::Placeholder(_) => false,
|
ConstValue::Placeholder(_) => false,
|
||||||
ConstValue::Scalar(_) => false,
|
ConstValue::Scalar(_) => false,
|
||||||
ConstValue::Slice(..) => false,
|
ConstValue::Slice { .. } => false,
|
||||||
ConstValue::Unevaluated(_, substs) => substs.visit_with(visitor),
|
ConstValue::Unevaluated(_, substs) => substs.visit_with(visitor),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2207,18 +2207,19 @@ pub struct Const<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
static_assert_size!(Const<'_>, 48);
|
static_assert_size!(Const<'_>, 40);
|
||||||
|
|
||||||
impl<'tcx> Const<'tcx> {
|
impl<'tcx> Const<'tcx> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_scalar(
|
pub fn from_scalar(
|
||||||
|
tcx: TyCtxt<'_, '_, 'tcx>,
|
||||||
val: Scalar,
|
val: Scalar,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
) -> Self {
|
) -> &'tcx Self {
|
||||||
Self {
|
tcx.mk_const(Self {
|
||||||
val: ConstValue::Scalar(val),
|
val: ConstValue::Scalar(val),
|
||||||
ty,
|
ty,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -2226,28 +2227,28 @@ impl<'tcx> Const<'tcx> {
|
|||||||
tcx: TyCtxt<'_, '_, 'tcx>,
|
tcx: TyCtxt<'_, '_, 'tcx>,
|
||||||
bits: u128,
|
bits: u128,
|
||||||
ty: ParamEnvAnd<'tcx, Ty<'tcx>>,
|
ty: ParamEnvAnd<'tcx, Ty<'tcx>>,
|
||||||
) -> Self {
|
) -> &'tcx Self {
|
||||||
let ty = tcx.lift_to_global(&ty).unwrap();
|
let ty = tcx.lift_to_global(&ty).unwrap();
|
||||||
let size = tcx.layout_of(ty).unwrap_or_else(|e| {
|
let size = tcx.layout_of(ty).unwrap_or_else(|e| {
|
||||||
panic!("could not compute layout for {:?}: {:?}", ty, e)
|
panic!("could not compute layout for {:?}: {:?}", ty, e)
|
||||||
}).size;
|
}).size;
|
||||||
let truncated = truncate(bits, size);
|
let truncated = truncate(bits, size);
|
||||||
assert_eq!(truncated, bits, "from_bits called with untruncated value");
|
assert_eq!(truncated, bits, "from_bits called with untruncated value");
|
||||||
Self::from_scalar(Scalar::Bits { bits, size: size.bytes() as u8 }, ty.value)
|
Self::from_scalar(tcx, Scalar::Bits { bits, size: size.bytes() as u8 }, ty.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn zero_sized(ty: Ty<'tcx>) -> Self {
|
pub fn zero_sized(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) -> &'tcx Self {
|
||||||
Self::from_scalar(Scalar::Bits { bits: 0, size: 0 }, ty)
|
Self::from_scalar(tcx, Scalar::Bits { bits: 0, size: 0 }, ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_bool(tcx: TyCtxt<'_, '_, 'tcx>, v: bool) -> Self {
|
pub fn from_bool(tcx: TyCtxt<'_, '_, 'tcx>, v: bool) -> &'tcx Self {
|
||||||
Self::from_bits(tcx, v as u128, ParamEnv::empty().and(tcx.types.bool))
|
Self::from_bits(tcx, v as u128, ParamEnv::empty().and(tcx.types.bool))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_usize(tcx: TyCtxt<'_, '_, 'tcx>, n: u64) -> Self {
|
pub fn from_usize(tcx: TyCtxt<'_, '_, 'tcx>, n: u64) -> &'tcx Self {
|
||||||
Self::from_bits(tcx, n as u128, ParamEnv::empty().and(tcx.types.usize))
|
Self::from_bits(tcx, n as u128, ParamEnv::empty().and(tcx.types.usize))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
pub fn eval_mir_constant(
|
pub fn eval_mir_constant(
|
||||||
&mut self,
|
&mut self,
|
||||||
constant: &mir::Constant<'tcx>,
|
constant: &mir::Constant<'tcx>,
|
||||||
) -> Result<ty::Const<'tcx>, ErrorHandled> {
|
) -> Result<&'tcx ty::Const<'tcx>, ErrorHandled> {
|
||||||
match constant.literal.val {
|
match constant.literal.val {
|
||||||
mir::interpret::ConstValue::Unevaluated(def_id, ref substs) => {
|
mir::interpret::ConstValue::Unevaluated(def_id, ref substs) => {
|
||||||
let substs = self.monomorphize(substs);
|
let substs = self.monomorphize(substs);
|
||||||
@ -26,7 +26,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
};
|
};
|
||||||
self.cx.tcx().const_eval(ty::ParamEnv::reveal_all().and(cid))
|
self.cx.tcx().const_eval(ty::ParamEnv::reveal_all().and(cid))
|
||||||
},
|
},
|
||||||
_ => Ok(*self.monomorphize(&constant.literal)),
|
_ => Ok(self.monomorphize(&constant.literal)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
bx: &Bx,
|
bx: &Bx,
|
||||||
span: Span,
|
span: Span,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
constant: Result<ty::Const<'tcx>, ErrorHandled>,
|
constant: Result<&'tcx ty::Const<'tcx>, ErrorHandled>,
|
||||||
) -> (Bx::Value, Ty<'tcx>) {
|
) -> (Bx::Value, Ty<'tcx>) {
|
||||||
constant
|
constant
|
||||||
.map(|c| {
|
.map(|c| {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use rustc::mir::interpret::{ConstValue, ErrorHandled};
|
use rustc::mir::interpret::{ConstValue, ErrorHandled, Pointer, Scalar};
|
||||||
use rustc::mir;
|
use rustc::mir;
|
||||||
use rustc::ty;
|
use rustc::ty;
|
||||||
use rustc::ty::layout::{self, Align, LayoutOf, TyLayout};
|
use rustc::ty::layout::{self, Align, LayoutOf, TyLayout, Size};
|
||||||
|
|
||||||
use crate::base;
|
use crate::base;
|
||||||
use crate::MemFlags;
|
use crate::MemFlags;
|
||||||
@ -67,7 +67,7 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandRef<'tcx, V> {
|
|||||||
|
|
||||||
pub fn from_const<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
|
pub fn from_const<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
|
||||||
bx: &mut Bx,
|
bx: &mut Bx,
|
||||||
val: ty::Const<'tcx>
|
val: &'tcx ty::Const<'tcx>
|
||||||
) -> Result<Self, ErrorHandled> {
|
) -> Result<Self, ErrorHandled> {
|
||||||
let layout = bx.layout_of(val.ty);
|
let layout = bx.layout_of(val.ty);
|
||||||
|
|
||||||
@ -92,17 +92,21 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandRef<'tcx, V> {
|
|||||||
);
|
);
|
||||||
OperandValue::Immediate(llval)
|
OperandValue::Immediate(llval)
|
||||||
},
|
},
|
||||||
ConstValue::Slice(a, b) => {
|
ConstValue::Slice { data, start, end } => {
|
||||||
let a_scalar = match layout.abi {
|
let a_scalar = match layout.abi {
|
||||||
layout::Abi::ScalarPair(ref a, _) => a,
|
layout::Abi::ScalarPair(ref a, _) => a,
|
||||||
_ => bug!("from_const: invalid ScalarPair layout: {:#?}", layout)
|
_ => bug!("from_const: invalid ScalarPair layout: {:#?}", layout)
|
||||||
};
|
};
|
||||||
|
let a = Scalar::from(Pointer::new(
|
||||||
|
bx.tcx().alloc_map.lock().allocate(data),
|
||||||
|
Size::from_bytes(start as u64),
|
||||||
|
)).into();
|
||||||
let a_llval = bx.scalar_to_backend(
|
let a_llval = bx.scalar_to_backend(
|
||||||
a,
|
a,
|
||||||
a_scalar,
|
a_scalar,
|
||||||
bx.scalar_pair_element_backend_type(layout, 0, true),
|
bx.scalar_pair_element_backend_type(layout, 0, true),
|
||||||
);
|
);
|
||||||
let b_llval = bx.const_usize(b);
|
let b_llval = bx.const_usize((end - start) as u64);
|
||||||
OperandValue::Pair(a_llval, b_llval)
|
OperandValue::Pair(a_llval, b_llval)
|
||||||
},
|
},
|
||||||
ConstValue::ByRef(ptr, alloc) => {
|
ConstValue::ByRef(ptr, alloc) => {
|
||||||
|
@ -96,6 +96,7 @@ use rustc::ty::print::{PrettyPrinter, Printer, Print};
|
|||||||
use rustc::ty::query::Providers;
|
use rustc::ty::query::Providers;
|
||||||
use rustc::ty::subst::{Kind, SubstsRef, UnpackedKind};
|
use rustc::ty::subst::{Kind, SubstsRef, UnpackedKind};
|
||||||
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
|
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||||
|
use rustc::mir::interpret::{ConstValue, Scalar};
|
||||||
use rustc::util::common::record_time;
|
use rustc::util::common::record_time;
|
||||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||||
use rustc_mir::monomorphize::item::{InstantiationMode, MonoItem, MonoItemExt};
|
use rustc_mir::monomorphize::item::{InstantiationMode, MonoItem, MonoItemExt};
|
||||||
@ -391,6 +392,7 @@ impl Printer<'tcx, 'tcx> for SymbolPrinter<'_, 'tcx> {
|
|||||||
type Region = Self;
|
type Region = Self;
|
||||||
type Type = Self;
|
type Type = Self;
|
||||||
type DynExistential = Self;
|
type DynExistential = Self;
|
||||||
|
type Const = Self;
|
||||||
|
|
||||||
fn tcx(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
|
fn tcx(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
|
||||||
self.tcx
|
self.tcx
|
||||||
@ -436,6 +438,20 @@ impl Printer<'tcx, 'tcx> for SymbolPrinter<'_, 'tcx> {
|
|||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn print_const(
|
||||||
|
mut self,
|
||||||
|
ct: &'tcx ty::Const<'tcx>,
|
||||||
|
) -> Result<Self::Const, Self::Error> {
|
||||||
|
// only print integers
|
||||||
|
if let ConstValue::Scalar(Scalar::Bits { .. }) = ct.val {
|
||||||
|
if ct.ty.is_integral() {
|
||||||
|
return self.pretty_print_const(ct);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.write_str("_")?;
|
||||||
|
Ok(self)
|
||||||
|
}
|
||||||
|
|
||||||
fn path_crate(
|
fn path_crate(
|
||||||
mut self,
|
mut self,
|
||||||
cnum: CrateNum,
|
cnum: CrateNum,
|
||||||
|
@ -737,12 +737,12 @@ enum TestKind<'tcx> {
|
|||||||
SwitchInt {
|
SwitchInt {
|
||||||
switch_ty: Ty<'tcx>,
|
switch_ty: Ty<'tcx>,
|
||||||
options: Vec<u128>,
|
options: Vec<u128>,
|
||||||
indices: FxHashMap<ty::Const<'tcx>, usize>,
|
indices: FxHashMap<&'tcx ty::Const<'tcx>, usize>,
|
||||||
},
|
},
|
||||||
|
|
||||||
// test for equality
|
// test for equality
|
||||||
Eq {
|
Eq {
|
||||||
value: ty::Const<'tcx>,
|
value: &'tcx ty::Const<'tcx>,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -98,7 +98,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||||||
candidate: &Candidate<'pat, 'tcx>,
|
candidate: &Candidate<'pat, 'tcx>,
|
||||||
switch_ty: Ty<'tcx>,
|
switch_ty: Ty<'tcx>,
|
||||||
options: &mut Vec<u128>,
|
options: &mut Vec<u128>,
|
||||||
indices: &mut FxHashMap<ty::Const<'tcx>, usize>)
|
indices: &mut FxHashMap<&'tcx ty::Const<'tcx>, usize>)
|
||||||
-> bool
|
-> bool
|
||||||
{
|
{
|
||||||
let match_pair = match candidate.match_pairs.iter().find(|mp| mp.place == *test_place) {
|
let match_pair = match candidate.match_pairs.iter().find(|mp| mp.place == *test_place) {
|
||||||
@ -305,7 +305,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||||||
}
|
}
|
||||||
let eq_def_id = self.hir.tcx().lang_items().eq_trait().unwrap();
|
let eq_def_id = self.hir.tcx().lang_items().eq_trait().unwrap();
|
||||||
let (mty, method) = self.hir.trait_method(eq_def_id, "eq", ty, &[ty.into()]);
|
let (mty, method) = self.hir.trait_method(eq_def_id, "eq", ty, &[ty.into()]);
|
||||||
let method = self.hir.tcx().mk_const(method);
|
|
||||||
|
|
||||||
let re_erased = self.hir.tcx().lifetimes.re_erased;
|
let re_erased = self.hir.tcx().lifetimes.re_erased;
|
||||||
// take the argument by reference
|
// take the argument by reference
|
||||||
@ -371,8 +370,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||||||
|
|
||||||
TestKind::Range(PatternRange { ref lo, ref hi, ty, ref end }) => {
|
TestKind::Range(PatternRange { ref lo, ref hi, ty, ref end }) => {
|
||||||
// Test `val` by computing `lo <= val && val <= hi`, using primitive comparisons.
|
// Test `val` by computing `lo <= val && val <= hi`, using primitive comparisons.
|
||||||
let lo = self.literal_operand(test.span, ty.clone(), lo.clone());
|
let lo = self.literal_operand(test.span, ty, lo);
|
||||||
let hi = self.literal_operand(test.span, ty.clone(), hi.clone());
|
let hi = self.literal_operand(test.span, ty, hi);
|
||||||
let val = Operand::Copy(place.clone());
|
let val = Operand::Copy(place.clone());
|
||||||
|
|
||||||
let fail = self.cfg.start_new_block();
|
let fail = self.cfg.start_new_block();
|
||||||
@ -724,7 +723,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||||||
fn const_range_contains(
|
fn const_range_contains(
|
||||||
&self,
|
&self,
|
||||||
range: PatternRange<'tcx>,
|
range: PatternRange<'tcx>,
|
||||||
value: ty::Const<'tcx>,
|
value: &'tcx ty::Const<'tcx>,
|
||||||
) -> Option<bool> {
|
) -> Option<bool> {
|
||||||
use std::cmp::Ordering::*;
|
use std::cmp::Ordering::*;
|
||||||
|
|
||||||
@ -744,7 +743,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||||||
fn values_not_contained_in_range(
|
fn values_not_contained_in_range(
|
||||||
&self,
|
&self,
|
||||||
range: PatternRange<'tcx>,
|
range: PatternRange<'tcx>,
|
||||||
indices: &FxHashMap<ty::Const<'tcx>, usize>,
|
indices: &FxHashMap<&'tcx ty::Const<'tcx>, usize>,
|
||||||
) -> Option<bool> {
|
) -> Option<bool> {
|
||||||
for &val in indices.keys() {
|
for &val in indices.keys() {
|
||||||
if self.const_range_contains(range, val)? {
|
if self.const_range_contains(range, val)? {
|
||||||
|
@ -27,13 +27,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||||||
pub fn literal_operand(&mut self,
|
pub fn literal_operand(&mut self,
|
||||||
span: Span,
|
span: Span,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
literal: ty::Const<'tcx>)
|
literal: &'tcx ty::Const<'tcx>)
|
||||||
-> Operand<'tcx> {
|
-> Operand<'tcx> {
|
||||||
let constant = box Constant {
|
let constant = box Constant {
|
||||||
span,
|
span,
|
||||||
ty,
|
ty,
|
||||||
user_ty: None,
|
user_ty: None,
|
||||||
literal: self.hir.tcx().mk_const(literal),
|
literal,
|
||||||
};
|
};
|
||||||
Operand::Constant(constant)
|
Operand::Constant(constant)
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ use std::error::Error;
|
|||||||
use std::borrow::{Borrow, Cow};
|
use std::borrow::{Borrow, Cow};
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use std::collections::hash_map::Entry;
|
use std::collections::hash_map::Entry;
|
||||||
|
use std::convert::TryInto;
|
||||||
|
|
||||||
use rustc::hir::def::DefKind;
|
use rustc::hir::def::DefKind;
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
@ -65,7 +66,7 @@ pub(crate) fn eval_promoted<'a, 'mir, 'tcx>(
|
|||||||
fn mplace_to_const<'tcx>(
|
fn mplace_to_const<'tcx>(
|
||||||
ecx: &CompileTimeEvalContext<'_, '_, 'tcx>,
|
ecx: &CompileTimeEvalContext<'_, '_, 'tcx>,
|
||||||
mplace: MPlaceTy<'tcx>,
|
mplace: MPlaceTy<'tcx>,
|
||||||
) -> ty::Const<'tcx> {
|
) -> &'tcx ty::Const<'tcx> {
|
||||||
let MemPlace { ptr, align, meta } = *mplace;
|
let MemPlace { ptr, align, meta } = *mplace;
|
||||||
// extract alloc-offset pair
|
// extract alloc-offset pair
|
||||||
assert!(meta.is_none());
|
assert!(meta.is_none());
|
||||||
@ -79,17 +80,24 @@ fn mplace_to_const<'tcx>(
|
|||||||
// interned this? I thought that is the entire point of that `FinishStatic` stuff?
|
// interned this? I thought that is the entire point of that `FinishStatic` stuff?
|
||||||
let alloc = ecx.tcx.intern_const_alloc(alloc);
|
let alloc = ecx.tcx.intern_const_alloc(alloc);
|
||||||
let val = ConstValue::ByRef(ptr, alloc);
|
let val = ConstValue::ByRef(ptr, alloc);
|
||||||
ty::Const { val, ty: mplace.layout.ty }
|
ecx.tcx.mk_const(ty::Const { val, ty: mplace.layout.ty })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op_to_const<'tcx>(
|
fn op_to_const<'tcx>(
|
||||||
ecx: &CompileTimeEvalContext<'_, '_, 'tcx>,
|
ecx: &CompileTimeEvalContext<'_, '_, 'tcx>,
|
||||||
op: OpTy<'tcx>,
|
op: OpTy<'tcx>,
|
||||||
) -> ty::Const<'tcx> {
|
) -> &'tcx ty::Const<'tcx> {
|
||||||
// We do not normalize just any data. Only non-union scalars and slices.
|
// We do not normalize just any data. Only non-union scalars and slices.
|
||||||
let normalize = match op.layout.abi {
|
let normalize = match op.layout.abi {
|
||||||
layout::Abi::Scalar(..) => op.layout.ty.ty_adt_def().map_or(true, |adt| !adt.is_union()),
|
layout::Abi::Scalar(..) => op.layout.ty.ty_adt_def().map_or(true, |adt| !adt.is_union()),
|
||||||
layout::Abi::ScalarPair(..) => op.layout.ty.is_slice(),
|
layout::Abi::ScalarPair(..) => match op.layout.ty.sty {
|
||||||
|
ty::Ref(_, inner, _) => match inner.sty {
|
||||||
|
ty::Slice(elem) => elem == ecx.tcx.types.u8,
|
||||||
|
ty::Str => true,
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
let normalized_op = if normalize {
|
let normalized_op = if normalize {
|
||||||
@ -101,10 +109,28 @@ fn op_to_const<'tcx>(
|
|||||||
Ok(mplace) => return mplace_to_const(ecx, mplace),
|
Ok(mplace) => return mplace_to_const(ecx, mplace),
|
||||||
Err(Immediate::Scalar(x)) =>
|
Err(Immediate::Scalar(x)) =>
|
||||||
ConstValue::Scalar(x.not_undef().unwrap()),
|
ConstValue::Scalar(x.not_undef().unwrap()),
|
||||||
Err(Immediate::ScalarPair(a, b)) =>
|
Err(Immediate::ScalarPair(a, b)) => {
|
||||||
ConstValue::Slice(a.not_undef().unwrap(), b.to_usize(ecx).unwrap()),
|
let (data, start) = match a.not_undef().unwrap() {
|
||||||
|
Scalar::Ptr(ptr) => (
|
||||||
|
ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id),
|
||||||
|
ptr.offset.bytes(),
|
||||||
|
),
|
||||||
|
Scalar::Bits { .. } => (
|
||||||
|
ecx.tcx.intern_const_alloc(Allocation::from_byte_aligned_bytes(b"", ())),
|
||||||
|
0,
|
||||||
|
),
|
||||||
};
|
};
|
||||||
ty::Const { val, ty: op.layout.ty }
|
let len = b.to_usize(&ecx.tcx.tcx).unwrap();
|
||||||
|
let start = start.try_into().unwrap();
|
||||||
|
let len: usize = len.try_into().unwrap();
|
||||||
|
ConstValue::Slice {
|
||||||
|
data,
|
||||||
|
start,
|
||||||
|
end: start + len,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
ecx.tcx.mk_const(ty::Const { val, ty: op.layout.ty })
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a pointer to where the result lives
|
// Returns a pointer to where the result lives
|
||||||
@ -450,8 +476,8 @@ pub fn const_field<'a, 'tcx>(
|
|||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
variant: Option<VariantIdx>,
|
variant: Option<VariantIdx>,
|
||||||
field: mir::Field,
|
field: mir::Field,
|
||||||
value: ty::Const<'tcx>,
|
value: &'tcx ty::Const<'tcx>,
|
||||||
) -> ty::Const<'tcx> {
|
) -> &'tcx ty::Const<'tcx> {
|
||||||
trace!("const_field: {:?}, {:?}", field, value);
|
trace!("const_field: {:?}, {:?}", field, value);
|
||||||
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env);
|
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env);
|
||||||
// get the operand again
|
// get the operand again
|
||||||
@ -473,7 +499,7 @@ pub fn const_field<'a, 'tcx>(
|
|||||||
pub fn const_variant_index<'a, 'tcx>(
|
pub fn const_variant_index<'a, 'tcx>(
|
||||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
val: ty::Const<'tcx>,
|
val: &'tcx ty::Const<'tcx>,
|
||||||
) -> VariantIdx {
|
) -> VariantIdx {
|
||||||
trace!("const_variant_index: {:?}", val);
|
trace!("const_variant_index: {:?}", val);
|
||||||
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env);
|
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env);
|
||||||
|
@ -14,7 +14,7 @@ crate fn lit_to_const<'a, 'gcx, 'tcx>(
|
|||||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
neg: bool,
|
neg: bool,
|
||||||
) -> Result<ty::Const<'tcx>, LitToConstError> {
|
) -> Result<&'tcx ty::Const<'tcx>, LitToConstError> {
|
||||||
use syntax::ast::*;
|
use syntax::ast::*;
|
||||||
|
|
||||||
let trunc = |n| {
|
let trunc = |n| {
|
||||||
@ -33,16 +33,18 @@ crate fn lit_to_const<'a, 'gcx, 'tcx>(
|
|||||||
let lit = match *lit {
|
let lit = match *lit {
|
||||||
LitKind::Str(ref s, _) => {
|
LitKind::Str(ref s, _) => {
|
||||||
let s = s.as_str();
|
let s = s.as_str();
|
||||||
let id = tcx.allocate_bytes(s.as_bytes());
|
let allocation = Allocation::from_byte_aligned_bytes(s.as_bytes(), ());
|
||||||
ConstValue::new_slice(Scalar::Ptr(id.into()), s.len() as u64)
|
let allocation = tcx.intern_const_alloc(allocation);
|
||||||
|
ConstValue::Slice { data: allocation, start: 0, end: s.len() }
|
||||||
},
|
},
|
||||||
LitKind::Err(ref s) => {
|
LitKind::Err(ref s) => {
|
||||||
let s = s.as_str();
|
let s = s.as_str();
|
||||||
let id = tcx.allocate_bytes(s.as_bytes());
|
let allocation = Allocation::from_byte_aligned_bytes(s.as_bytes(), ());
|
||||||
return Ok(ty::Const {
|
let allocation = tcx.intern_const_alloc(allocation);
|
||||||
val: ConstValue::new_slice(Scalar::Ptr(id.into()), s.len() as u64),
|
return Ok(tcx.mk_const(ty::Const {
|
||||||
|
val: ConstValue::Slice{ data: allocation, start: 0, end: s.len() },
|
||||||
ty: tcx.types.err,
|
ty: tcx.types.err,
|
||||||
});
|
}));
|
||||||
},
|
},
|
||||||
LitKind::ByteStr(ref data) => {
|
LitKind::ByteStr(ref data) => {
|
||||||
let id = tcx.allocate_bytes(data);
|
let id = tcx.allocate_bytes(data);
|
||||||
@ -71,7 +73,7 @@ crate fn lit_to_const<'a, 'gcx, 'tcx>(
|
|||||||
LitKind::Bool(b) => ConstValue::Scalar(Scalar::from_bool(b)),
|
LitKind::Bool(b) => ConstValue::Scalar(Scalar::from_bool(b)),
|
||||||
LitKind::Char(c) => ConstValue::Scalar(Scalar::from_char(c)),
|
LitKind::Char(c) => ConstValue::Scalar(Scalar::from_char(c)),
|
||||||
};
|
};
|
||||||
Ok(ty::Const { val: lit, ty })
|
Ok(tcx.mk_const(ty::Const { val: lit, ty }))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_float<'tcx>(
|
fn parse_float<'tcx>(
|
||||||
|
@ -329,9 +329,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||||||
}
|
}
|
||||||
|
|
||||||
hir::ExprKind::Lit(ref lit) => ExprKind::Literal {
|
hir::ExprKind::Lit(ref lit) => ExprKind::Literal {
|
||||||
literal: cx.tcx.mk_const(
|
literal: cx.const_eval_literal(&lit.node, expr_ty, lit.span, false),
|
||||||
cx.const_eval_literal(&lit.node, expr_ty, lit.span, false)
|
|
||||||
),
|
|
||||||
user_ty: None,
|
user_ty: None,
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -429,9 +427,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||||||
} else {
|
} else {
|
||||||
if let hir::ExprKind::Lit(ref lit) = arg.node {
|
if let hir::ExprKind::Lit(ref lit) = arg.node {
|
||||||
ExprKind::Literal {
|
ExprKind::Literal {
|
||||||
literal: cx.tcx.mk_const(
|
literal: cx.const_eval_literal(&lit.node, expr_ty, lit.span, true),
|
||||||
cx.const_eval_literal(&lit.node, expr_ty, lit.span, true)
|
|
||||||
),
|
|
||||||
user_ty: None,
|
user_ty: None,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -680,7 +676,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||||||
ty: var_ty,
|
ty: var_ty,
|
||||||
span: expr.span,
|
span: expr.span,
|
||||||
kind: ExprKind::Literal {
|
kind: ExprKind::Literal {
|
||||||
literal: cx.tcx.mk_const(literal),
|
literal,
|
||||||
user_ty: None
|
user_ty: None
|
||||||
},
|
},
|
||||||
}.to_ref();
|
}.to_ref();
|
||||||
@ -694,10 +690,10 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||||||
// in case we are offsetting from a computed discriminant
|
// in case we are offsetting from a computed discriminant
|
||||||
// and not the beginning of discriminants (which is always `0`)
|
// and not the beginning of discriminants (which is always `0`)
|
||||||
let substs = InternalSubsts::identity_for_item(cx.tcx(), did);
|
let substs = InternalSubsts::identity_for_item(cx.tcx(), did);
|
||||||
let lhs = mk_const(ty::Const {
|
let lhs = mk_const(cx.tcx().mk_const(ty::Const {
|
||||||
val: ConstValue::Unevaluated(did, substs),
|
val: ConstValue::Unevaluated(did, substs),
|
||||||
ty: var_ty,
|
ty: var_ty,
|
||||||
});
|
}));
|
||||||
let bin = ExprKind::Binary {
|
let bin = ExprKind::Binary {
|
||||||
op: BinOp::Add,
|
op: BinOp::Add,
|
||||||
lhs,
|
lhs,
|
||||||
@ -837,9 +833,7 @@ fn method_callee<'a, 'gcx, 'tcx>(
|
|||||||
ty,
|
ty,
|
||||||
span,
|
span,
|
||||||
kind: ExprKind::Literal {
|
kind: ExprKind::Literal {
|
||||||
literal: cx.tcx().mk_const(
|
literal: ty::Const::zero_sized(cx.tcx(), ty),
|
||||||
ty::Const::zero_sized(ty)
|
|
||||||
),
|
|
||||||
user_ty,
|
user_ty,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -902,9 +896,10 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||||||
let user_ty = user_substs_applied_to_res(cx, expr.hir_id, res);
|
let user_ty = user_substs_applied_to_res(cx, expr.hir_id, res);
|
||||||
debug!("convert_path_expr: user_ty={:?}", user_ty);
|
debug!("convert_path_expr: user_ty={:?}", user_ty);
|
||||||
ExprKind::Literal {
|
ExprKind::Literal {
|
||||||
literal: cx.tcx.mk_const(ty::Const::zero_sized(
|
literal: ty::Const::zero_sized(
|
||||||
|
cx.tcx,
|
||||||
cx.tables().node_type(expr.hir_id),
|
cx.tables().node_type(expr.hir_id),
|
||||||
)),
|
),
|
||||||
user_ty,
|
user_ty,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn usize_literal(&mut self, value: u64) -> &'tcx ty::Const<'tcx> {
|
pub fn usize_literal(&mut self, value: u64) -> &'tcx ty::Const<'tcx> {
|
||||||
self.tcx.mk_const(ty::Const::from_usize(self.tcx, value))
|
ty::Const::from_usize(self.tcx, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bool_ty(&mut self) -> Ty<'tcx> {
|
pub fn bool_ty(&mut self) -> Ty<'tcx> {
|
||||||
@ -118,11 +118,11 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn true_literal(&mut self) -> &'tcx ty::Const<'tcx> {
|
pub fn true_literal(&mut self) -> &'tcx ty::Const<'tcx> {
|
||||||
self.tcx.mk_const(ty::Const::from_bool(self.tcx, true))
|
ty::Const::from_bool(self.tcx, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn false_literal(&mut self) -> &'tcx ty::Const<'tcx> {
|
pub fn false_literal(&mut self) -> &'tcx ty::Const<'tcx> {
|
||||||
self.tcx.mk_const(ty::Const::from_bool(self.tcx, false))
|
ty::Const::from_bool(self.tcx, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn const_eval_literal(
|
pub fn const_eval_literal(
|
||||||
@ -131,7 +131,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
|||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
sp: Span,
|
sp: Span,
|
||||||
neg: bool,
|
neg: bool,
|
||||||
) -> ty::Const<'tcx> {
|
) -> &'tcx ty::Const<'tcx> {
|
||||||
trace!("const_eval_literal: {:#?}, {:?}, {:?}, {:?}", lit, ty, sp, neg);
|
trace!("const_eval_literal: {:#?}, {:?}, {:?}, {:?}", lit, ty, sp, neg);
|
||||||
|
|
||||||
match lit_to_const(lit, self.tcx, ty, neg) {
|
match lit_to_const(lit, self.tcx, ty, neg) {
|
||||||
@ -166,14 +166,14 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
|||||||
method_name: &str,
|
method_name: &str,
|
||||||
self_ty: Ty<'tcx>,
|
self_ty: Ty<'tcx>,
|
||||||
params: &[Kind<'tcx>])
|
params: &[Kind<'tcx>])
|
||||||
-> (Ty<'tcx>, ty::Const<'tcx>) {
|
-> (Ty<'tcx>, &'tcx ty::Const<'tcx>) {
|
||||||
let method_name = Symbol::intern(method_name);
|
let method_name = Symbol::intern(method_name);
|
||||||
let substs = self.tcx.mk_substs_trait(self_ty, params);
|
let substs = self.tcx.mk_substs_trait(self_ty, params);
|
||||||
for item in self.tcx.associated_items(trait_def_id) {
|
for item in self.tcx.associated_items(trait_def_id) {
|
||||||
if item.kind == ty::AssociatedKind::Method && item.ident.name == method_name {
|
if item.kind == ty::AssociatedKind::Method && item.ident.name == method_name {
|
||||||
let method_ty = self.tcx.type_of(item.def_id);
|
let method_ty = self.tcx.type_of(item.def_id);
|
||||||
let method_ty = method_ty.subst(self.tcx, substs);
|
let method_ty = method_ty.subst(self.tcx, substs);
|
||||||
return (method_ty, ty::Const::zero_sized(method_ty));
|
return (method_ty, ty::Const::zero_sized(self.tcx, method_ty));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,7 +172,7 @@ use rustc::ty::{self, Ty, TyCtxt, TypeFoldable, Const};
|
|||||||
use rustc::ty::layout::{Integer, IntegerExt, VariantIdx, Size};
|
use rustc::ty::layout::{Integer, IntegerExt, VariantIdx, Size};
|
||||||
|
|
||||||
use rustc::mir::Field;
|
use rustc::mir::Field;
|
||||||
use rustc::mir::interpret::{ConstValue, Scalar, truncate};
|
use rustc::mir::interpret::{ConstValue, Scalar, truncate, AllocId, Pointer};
|
||||||
use rustc::util::common::ErrorReported;
|
use rustc::util::common::ErrorReported;
|
||||||
|
|
||||||
use syntax::attr::{SignedInt, UnsignedInt};
|
use syntax::attr::{SignedInt, UnsignedInt};
|
||||||
@ -186,6 +186,7 @@ use std::fmt;
|
|||||||
use std::iter::{FromIterator, IntoIterator};
|
use std::iter::{FromIterator, IntoIterator};
|
||||||
use std::ops::RangeInclusive;
|
use std::ops::RangeInclusive;
|
||||||
use std::u128;
|
use std::u128;
|
||||||
|
use std::convert::TryInto;
|
||||||
|
|
||||||
pub fn expand_pattern<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>, pat: Pattern<'tcx>)
|
pub fn expand_pattern<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>, pat: Pattern<'tcx>)
|
||||||
-> &'a Pattern<'tcx>
|
-> &'a Pattern<'tcx>
|
||||||
@ -221,16 +222,17 @@ impl<'a, 'tcx> LiteralExpander<'a, 'tcx> {
|
|||||||
// unsize array to slice if pattern is array but match value or other patterns are slice
|
// unsize array to slice if pattern is array but match value or other patterns are slice
|
||||||
(ConstValue::Scalar(Scalar::Ptr(p)), ty::Array(t, n), ty::Slice(u)) => {
|
(ConstValue::Scalar(Scalar::Ptr(p)), ty::Array(t, n), ty::Slice(u)) => {
|
||||||
assert_eq!(t, u);
|
assert_eq!(t, u);
|
||||||
ConstValue::Slice(
|
ConstValue::Slice {
|
||||||
Scalar::Ptr(p),
|
data: self.tcx.alloc_map.lock().unwrap_memory(p.alloc_id),
|
||||||
n.val.try_to_scalar()
|
start: p.offset.bytes().try_into().unwrap(),
|
||||||
.unwrap()
|
end: n.unwrap_usize(self.tcx).try_into().unwrap(),
|
||||||
.to_usize(&self.tcx)
|
}
|
||||||
.unwrap(),
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
// fat pointers stay the same
|
// fat pointers stay the same
|
||||||
(ConstValue::Slice(..), _, _) => val,
|
| (ConstValue::Slice { .. }, _, _)
|
||||||
|
| (_, ty::Slice(_), ty::Slice(_))
|
||||||
|
| (_, ty::Str, ty::Str)
|
||||||
|
=> val,
|
||||||
// FIXME(oli-obk): this is reachable for `const FOO: &&&u32 = &&&42;` being used
|
// FIXME(oli-obk): this is reachable for `const FOO: &&&u32 = &&&42;` being used
|
||||||
_ => bug!("cannot deref {:#?}, {} -> {}", val, crty, rty),
|
_ => bug!("cannot deref {:#?}, {} -> {}", val, crty, rty),
|
||||||
}
|
}
|
||||||
@ -255,10 +257,10 @@ impl<'a, 'tcx> PatternFolder<'tcx> for LiteralExpander<'a, 'tcx> {
|
|||||||
subpattern: Pattern {
|
subpattern: Pattern {
|
||||||
ty: rty,
|
ty: rty,
|
||||||
span: pat.span,
|
span: pat.span,
|
||||||
kind: box PatternKind::Constant { value: Const {
|
kind: box PatternKind::Constant { value: self.tcx.mk_const(Const {
|
||||||
val: self.fold_const_value_deref(val, rty, crty),
|
val: self.fold_const_value_deref(*val, rty, crty),
|
||||||
ty: rty,
|
ty: rty,
|
||||||
} },
|
}) },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -423,7 +425,7 @@ enum Constructor<'tcx> {
|
|||||||
/// Enum variants.
|
/// Enum variants.
|
||||||
Variant(DefId),
|
Variant(DefId),
|
||||||
/// Literal values.
|
/// Literal values.
|
||||||
ConstantValue(ty::Const<'tcx>),
|
ConstantValue(&'tcx ty::Const<'tcx>),
|
||||||
/// Ranges of literal values (`2...5` and `2..5`).
|
/// Ranges of literal values (`2...5` and `2..5`).
|
||||||
ConstantRange(u128, u128, Ty<'tcx>, RangeEnd),
|
ConstantRange(u128, u128, Ty<'tcx>, RangeEnd),
|
||||||
/// Array patterns of length n.
|
/// Array patterns of length n.
|
||||||
@ -786,9 +788,9 @@ fn max_slice_length<'p, 'a: 'p, 'tcx: 'a, I>(
|
|||||||
max_fixed_len,
|
max_fixed_len,
|
||||||
n.unwrap_usize(cx.tcx),
|
n.unwrap_usize(cx.tcx),
|
||||||
),
|
),
|
||||||
(ConstValue::Slice(_, n), ty::Slice(_)) => max_fixed_len = cmp::max(
|
(ConstValue::Slice{ start, end, .. }, ty::Slice(_)) => max_fixed_len = cmp::max(
|
||||||
max_fixed_len,
|
max_fixed_len,
|
||||||
n,
|
(end - start) as u64,
|
||||||
),
|
),
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
@ -1424,49 +1426,24 @@ fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>,
|
|||||||
fn slice_pat_covered_by_const<'tcx>(
|
fn slice_pat_covered_by_const<'tcx>(
|
||||||
tcx: TyCtxt<'_, 'tcx, '_>,
|
tcx: TyCtxt<'_, 'tcx, '_>,
|
||||||
_span: Span,
|
_span: Span,
|
||||||
const_val: ty::Const<'tcx>,
|
const_val: &'tcx ty::Const<'tcx>,
|
||||||
prefix: &[Pattern<'tcx>],
|
prefix: &[Pattern<'tcx>],
|
||||||
slice: &Option<Pattern<'tcx>>,
|
slice: &Option<Pattern<'tcx>>,
|
||||||
suffix: &[Pattern<'tcx>]
|
suffix: &[Pattern<'tcx>]
|
||||||
) -> Result<bool, ErrorReported> {
|
) -> Result<bool, ErrorReported> {
|
||||||
let data: &[u8] = match (const_val.val, &const_val.ty.sty) {
|
let data: &[u8] = match (const_val.val, &const_val.ty.sty) {
|
||||||
(ConstValue::ByRef(ptr, alloc), ty::Array(t, n)) => {
|
(ConstValue::ByRef(ptr, alloc), ty::Array(t, n)) => {
|
||||||
if *t != tcx.types.u8 {
|
assert_eq!(*t, tcx.types.u8);
|
||||||
// FIXME(oli-obk): can't mix const patterns with slice patterns and get
|
|
||||||
// any sort of exhaustiveness/unreachable check yet
|
|
||||||
// This solely means that we don't lint about unreachable patterns, even if some
|
|
||||||
// are definitely unreachable.
|
|
||||||
return Ok(false);
|
|
||||||
}
|
|
||||||
let n = n.assert_usize(tcx).unwrap();
|
let n = n.assert_usize(tcx).unwrap();
|
||||||
alloc.get_bytes(&tcx, ptr, Size::from_bytes(n)).unwrap()
|
alloc.get_bytes(&tcx, ptr, Size::from_bytes(n)).unwrap()
|
||||||
},
|
},
|
||||||
// a slice fat pointer to a zero length slice
|
(ConstValue::Slice { data, start, end }, ty::Slice(t)) => {
|
||||||
(ConstValue::Slice(Scalar::Bits { .. }, 0), ty::Slice(t)) => {
|
assert_eq!(*t, tcx.types.u8);
|
||||||
if *t != tcx.types.u8 {
|
let ptr = Pointer::new(AllocId(0), Size::from_bytes(start as u64));
|
||||||
// FIXME(oli-obk): can't mix const patterns with slice patterns and get
|
data.get_bytes(&tcx, ptr, Size::from_bytes((end - start) as u64)).unwrap()
|
||||||
// any sort of exhaustiveness/unreachable check yet
|
|
||||||
// This solely means that we don't lint about unreachable patterns, even if some
|
|
||||||
// are definitely unreachable.
|
|
||||||
return Ok(false);
|
|
||||||
}
|
|
||||||
&[]
|
|
||||||
},
|
|
||||||
//
|
|
||||||
(ConstValue::Slice(Scalar::Ptr(ptr), n), ty::Slice(t)) => {
|
|
||||||
if *t != tcx.types.u8 {
|
|
||||||
// FIXME(oli-obk): can't mix const patterns with slice patterns and get
|
|
||||||
// any sort of exhaustiveness/unreachable check yet
|
|
||||||
// This solely means that we don't lint about unreachable patterns, even if some
|
|
||||||
// are definitely unreachable.
|
|
||||||
return Ok(false);
|
|
||||||
}
|
|
||||||
tcx.alloc_map
|
|
||||||
.lock()
|
|
||||||
.unwrap_memory(ptr.alloc_id)
|
|
||||||
.get_bytes(&tcx, ptr, Size::from_bytes(n))
|
|
||||||
.unwrap()
|
|
||||||
},
|
},
|
||||||
|
// FIXME(oli-obk): create a way to extract fat pointers from ByRef
|
||||||
|
(_, ty::Slice(_)) => return Ok(false),
|
||||||
_ => bug!(
|
_ => bug!(
|
||||||
"slice_pat_covered_by_const: {:#?}, {:#?}, {:#?}, {:#?}",
|
"slice_pat_covered_by_const: {:#?}, {:#?}, {:#?}, {:#?}",
|
||||||
const_val, prefix, slice, suffix,
|
const_val, prefix, slice, suffix,
|
||||||
@ -1774,11 +1751,12 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
|
|||||||
// necessarily point to memory, they are usually just integers. The only time
|
// necessarily point to memory, they are usually just integers. The only time
|
||||||
// they should be pointing to memory is when they are subslices of nonzero
|
// they should be pointing to memory is when they are subslices of nonzero
|
||||||
// slices
|
// slices
|
||||||
let (opt_ptr, n, ty) = match value.ty.sty {
|
let (alloc, offset, n, ty) = match value.ty.sty {
|
||||||
ty::Array(t, n) => {
|
ty::Array(t, n) => {
|
||||||
match value.val {
|
match value.val {
|
||||||
ConstValue::ByRef(ptr, alloc) => (
|
ConstValue::ByRef(ptr, alloc) => (
|
||||||
Some((ptr, alloc)),
|
alloc,
|
||||||
|
ptr.offset,
|
||||||
n.unwrap_usize(cx.tcx),
|
n.unwrap_usize(cx.tcx),
|
||||||
t,
|
t,
|
||||||
),
|
),
|
||||||
@ -1790,14 +1768,16 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
|
|||||||
},
|
},
|
||||||
ty::Slice(t) => {
|
ty::Slice(t) => {
|
||||||
match value.val {
|
match value.val {
|
||||||
ConstValue::Slice(ptr, n) => (
|
ConstValue::Slice { data, start, end } => (
|
||||||
ptr.to_ptr().ok().map(|ptr| (
|
data,
|
||||||
ptr,
|
Size::from_bytes(start as u64),
|
||||||
cx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id),
|
(end - start) as u64,
|
||||||
)),
|
|
||||||
n,
|
|
||||||
t,
|
t,
|
||||||
),
|
),
|
||||||
|
ConstValue::ByRef(..) => {
|
||||||
|
// FIXME(oli-obk): implement `deref` for `ConstValue`
|
||||||
|
return None;
|
||||||
|
},
|
||||||
_ => span_bug!(
|
_ => span_bug!(
|
||||||
pat.span,
|
pat.span,
|
||||||
"slice pattern constant must be scalar pair but is {:?}",
|
"slice pattern constant must be scalar pair but is {:?}",
|
||||||
@ -1814,17 +1794,15 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
|
|||||||
};
|
};
|
||||||
if wild_patterns.len() as u64 == n {
|
if wild_patterns.len() as u64 == n {
|
||||||
// convert a constant slice/array pattern to a list of patterns.
|
// convert a constant slice/array pattern to a list of patterns.
|
||||||
match (n, opt_ptr) {
|
|
||||||
(0, _) => Some(SmallVec::new()),
|
|
||||||
(_, Some((ptr, alloc))) => {
|
|
||||||
let layout = cx.tcx.layout_of(cx.param_env.and(ty)).ok()?;
|
let layout = cx.tcx.layout_of(cx.param_env.and(ty)).ok()?;
|
||||||
|
let ptr = Pointer::new(AllocId(0), offset);
|
||||||
(0..n).map(|i| {
|
(0..n).map(|i| {
|
||||||
let ptr = ptr.offset(layout.size * i, &cx.tcx).ok()?;
|
let ptr = ptr.offset(layout.size * i, &cx.tcx).ok()?;
|
||||||
let scalar = alloc.read_scalar(
|
let scalar = alloc.read_scalar(
|
||||||
&cx.tcx, ptr, layout.size,
|
&cx.tcx, ptr, layout.size,
|
||||||
).ok()?;
|
).ok()?;
|
||||||
let scalar = scalar.not_undef().ok()?;
|
let scalar = scalar.not_undef().ok()?;
|
||||||
let value = ty::Const::from_scalar(scalar, ty);
|
let value = ty::Const::from_scalar(cx.tcx, scalar, ty);
|
||||||
let pattern = Pattern {
|
let pattern = Pattern {
|
||||||
ty,
|
ty,
|
||||||
span: pat.span,
|
span: pat.span,
|
||||||
@ -1832,13 +1810,6 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
|
|||||||
};
|
};
|
||||||
Some(&*cx.pattern_arena.alloc(pattern))
|
Some(&*cx.pattern_arena.alloc(pattern))
|
||||||
}).collect()
|
}).collect()
|
||||||
},
|
|
||||||
(_, None) => span_bug!(
|
|
||||||
pat.span,
|
|
||||||
"non zero length slice with const-val {:?}",
|
|
||||||
value,
|
|
||||||
),
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -10,13 +10,13 @@ use crate::const_eval::{const_field, const_variant_index};
|
|||||||
use crate::hair::util::UserAnnotatedTyHelpers;
|
use crate::hair::util::UserAnnotatedTyHelpers;
|
||||||
use crate::hair::constant::*;
|
use crate::hair::constant::*;
|
||||||
|
|
||||||
use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability};
|
use rustc::mir::{Field, BorrowKind, Mutability};
|
||||||
use rustc::mir::{UserTypeProjection};
|
use rustc::mir::{UserTypeProjection};
|
||||||
use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend};
|
use rustc::mir::interpret::{GlobalId, ConstValue, sign_extend, AllocId, Pointer};
|
||||||
use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty, UserType, DefIdTree};
|
use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty, UserType, DefIdTree};
|
||||||
use rustc::ty::{CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations};
|
use rustc::ty::{CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations};
|
||||||
use rustc::ty::subst::{SubstsRef, Kind};
|
use rustc::ty::subst::{SubstsRef, Kind};
|
||||||
use rustc::ty::layout::VariantIdx;
|
use rustc::ty::layout::{VariantIdx, Size};
|
||||||
use rustc::hir::{self, PatKind, RangeEnd};
|
use rustc::hir::{self, PatKind, RangeEnd};
|
||||||
use rustc::hir::def::{CtorOf, Res, DefKind, CtorKind};
|
use rustc::hir::def::{CtorOf, Res, DefKind, CtorKind};
|
||||||
use rustc::hir::pat_util::EnumerateAndAdjustIterator;
|
use rustc::hir::pat_util::EnumerateAndAdjustIterator;
|
||||||
@ -152,7 +152,7 @@ pub enum PatternKind<'tcx> {
|
|||||||
},
|
},
|
||||||
|
|
||||||
Constant {
|
Constant {
|
||||||
value: ty::Const<'tcx>,
|
value: &'tcx ty::Const<'tcx>,
|
||||||
},
|
},
|
||||||
|
|
||||||
Range(PatternRange<'tcx>),
|
Range(PatternRange<'tcx>),
|
||||||
@ -176,8 +176,8 @@ pub enum PatternKind<'tcx> {
|
|||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
pub struct PatternRange<'tcx> {
|
pub struct PatternRange<'tcx> {
|
||||||
pub lo: ty::Const<'tcx>,
|
pub lo: &'tcx ty::Const<'tcx>,
|
||||||
pub hi: ty::Const<'tcx>,
|
pub hi: &'tcx ty::Const<'tcx>,
|
||||||
pub ty: Ty<'tcx>,
|
pub ty: Ty<'tcx>,
|
||||||
pub end: RangeEnd,
|
pub end: RangeEnd,
|
||||||
}
|
}
|
||||||
@ -291,15 +291,15 @@ impl<'tcx> fmt::Display for Pattern<'tcx> {
|
|||||||
write!(f, "{}", subpattern)
|
write!(f, "{}", subpattern)
|
||||||
}
|
}
|
||||||
PatternKind::Constant { value } => {
|
PatternKind::Constant { value } => {
|
||||||
fmt_const_val(f, value)
|
write!(f, "{}", value)
|
||||||
}
|
}
|
||||||
PatternKind::Range(PatternRange { lo, hi, ty: _, end }) => {
|
PatternKind::Range(PatternRange { lo, hi, ty: _, end }) => {
|
||||||
fmt_const_val(f, lo)?;
|
write!(f, "{}", lo)?;
|
||||||
match end {
|
match end {
|
||||||
RangeEnd::Included => write!(f, "..=")?,
|
RangeEnd::Included => write!(f, "..=")?,
|
||||||
RangeEnd::Excluded => write!(f, "..")?,
|
RangeEnd::Excluded => write!(f, "..")?,
|
||||||
}
|
}
|
||||||
fmt_const_val(f, hi)
|
write!(f, "{}", hi)
|
||||||
}
|
}
|
||||||
PatternKind::Slice { ref prefix, ref slice, ref suffix } |
|
PatternKind::Slice { ref prefix, ref slice, ref suffix } |
|
||||||
PatternKind::Array { ref prefix, ref slice, ref suffix } => {
|
PatternKind::Array { ref prefix, ref slice, ref suffix } => {
|
||||||
@ -942,7 +942,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
|
|||||||
fn const_to_pat(
|
fn const_to_pat(
|
||||||
&self,
|
&self,
|
||||||
instance: ty::Instance<'tcx>,
|
instance: ty::Instance<'tcx>,
|
||||||
cv: ty::Const<'tcx>,
|
cv: &'tcx ty::Const<'tcx>,
|
||||||
id: hir::HirId,
|
id: hir::HirId,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> Pattern<'tcx> {
|
) -> Pattern<'tcx> {
|
||||||
@ -1205,7 +1205,7 @@ impl<'tcx> PatternFoldable<'tcx> for PatternKind<'tcx> {
|
|||||||
PatternKind::Constant {
|
PatternKind::Constant {
|
||||||
value
|
value
|
||||||
} => PatternKind::Constant {
|
} => PatternKind::Constant {
|
||||||
value: value.fold_with(folder)
|
value,
|
||||||
},
|
},
|
||||||
PatternKind::Range(PatternRange {
|
PatternKind::Range(PatternRange {
|
||||||
lo,
|
lo,
|
||||||
@ -1213,8 +1213,8 @@ impl<'tcx> PatternFoldable<'tcx> for PatternKind<'tcx> {
|
|||||||
ty,
|
ty,
|
||||||
end,
|
end,
|
||||||
}) => PatternKind::Range(PatternRange {
|
}) => PatternKind::Range(PatternRange {
|
||||||
lo: lo.fold_with(folder),
|
lo,
|
||||||
hi: hi.fold_with(folder),
|
hi,
|
||||||
ty: ty.fold_with(folder),
|
ty: ty.fold_with(folder),
|
||||||
end,
|
end,
|
||||||
}),
|
}),
|
||||||
@ -1242,8 +1242,8 @@ impl<'tcx> PatternFoldable<'tcx> for PatternKind<'tcx> {
|
|||||||
|
|
||||||
pub fn compare_const_vals<'a, 'gcx, 'tcx>(
|
pub fn compare_const_vals<'a, 'gcx, 'tcx>(
|
||||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||||
a: ty::Const<'tcx>,
|
a: &'tcx ty::Const<'tcx>,
|
||||||
b: ty::Const<'tcx>,
|
b: &'tcx ty::Const<'tcx>,
|
||||||
ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
|
ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
|
||||||
) -> Option<Ordering> {
|
) -> Option<Ordering> {
|
||||||
trace!("compare_const_vals: {:?}, {:?}", a, b);
|
trace!("compare_const_vals: {:?}, {:?}", a, b);
|
||||||
@ -1293,22 +1293,25 @@ pub fn compare_const_vals<'a, 'gcx, 'tcx>(
|
|||||||
if let ty::Str = ty.value.sty {
|
if let ty::Str = ty.value.sty {
|
||||||
match (a.val, b.val) {
|
match (a.val, b.val) {
|
||||||
(
|
(
|
||||||
ConstValue::Slice(
|
ConstValue::Slice { data: alloc_a, start: offset_a, end: end_a },
|
||||||
Scalar::Ptr(ptr_a),
|
ConstValue::Slice { data: alloc_b, start: offset_b, end: end_b },
|
||||||
len_a,
|
) => {
|
||||||
),
|
let len_a = end_a - offset_a;
|
||||||
ConstValue::Slice(
|
let len_b = end_b - offset_b;
|
||||||
Scalar::Ptr(ptr_b),
|
let a = alloc_a.get_bytes(
|
||||||
len_b,
|
&tcx,
|
||||||
),
|
// invent a pointer, only the offset is relevant anyway
|
||||||
) if ptr_a.offset.bytes() == 0 && ptr_b.offset.bytes() == 0 => {
|
Pointer::new(AllocId(0), Size::from_bytes(offset_a as u64)),
|
||||||
if len_a == len_b {
|
Size::from_bytes(len_a as u64),
|
||||||
let map = tcx.alloc_map.lock();
|
);
|
||||||
let alloc_a = map.unwrap_memory(ptr_a.alloc_id);
|
let b = alloc_b.get_bytes(
|
||||||
let alloc_b = map.unwrap_memory(ptr_b.alloc_id);
|
&tcx,
|
||||||
if alloc_a.bytes.len() as u64 == len_a {
|
// invent a pointer, only the offset is relevant anyway
|
||||||
return from_bool(alloc_a == alloc_b);
|
Pointer::new(AllocId(0), Size::from_bytes(offset_b as u64)),
|
||||||
}
|
Size::from_bytes(len_b as u64),
|
||||||
|
);
|
||||||
|
if let (Ok(a), Ok(b)) = (a, b) {
|
||||||
|
return from_bool(a == b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
|
@ -512,7 +512,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
|
|||||||
Move(ref place) =>
|
Move(ref place) =>
|
||||||
self.eval_place_to_op(place, layout)?,
|
self.eval_place_to_op(place, layout)?,
|
||||||
|
|
||||||
Constant(ref constant) => self.eval_const_to_op(*constant.literal, layout)?,
|
Constant(ref constant) => self.eval_const_to_op(constant.literal, layout)?,
|
||||||
};
|
};
|
||||||
trace!("{:?}: {:?}", mir_op, *op);
|
trace!("{:?}: {:?}", mir_op, *op);
|
||||||
Ok(op)
|
Ok(op)
|
||||||
@ -532,7 +532,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
|
|||||||
// in patterns via the `const_eval` module
|
// in patterns via the `const_eval` module
|
||||||
crate fn eval_const_to_op(
|
crate fn eval_const_to_op(
|
||||||
&self,
|
&self,
|
||||||
val: ty::Const<'tcx>,
|
val: &'tcx ty::Const<'tcx>,
|
||||||
layout: Option<TyLayout<'tcx>>,
|
layout: Option<TyLayout<'tcx>>,
|
||||||
) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
|
) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
|
||||||
let op = match val.val {
|
let op = match val.val {
|
||||||
@ -545,11 +545,16 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
|
|||||||
MemPlace::from_ptr(ptr.with_default_tag(), alloc.align)
|
MemPlace::from_ptr(ptr.with_default_tag(), alloc.align)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
ConstValue::Slice(a, b) =>
|
ConstValue::Slice { data, start, end } =>
|
||||||
Operand::Immediate(Immediate::ScalarPair(
|
Operand::Immediate(Immediate::ScalarPair(
|
||||||
a.with_default_tag().into(),
|
Scalar::from(Pointer::new(
|
||||||
Scalar::from_uint(b, self.tcx.data_layout.pointer_size)
|
self.tcx.alloc_map.lock().allocate(data),
|
||||||
.with_default_tag().into(),
|
Size::from_bytes(start as u64),
|
||||||
|
)).with_default_tag().into(),
|
||||||
|
Scalar::from_uint(
|
||||||
|
(end - start) as u64,
|
||||||
|
self.tcx.data_layout.pointer_size,
|
||||||
|
).with_default_tag().into(),
|
||||||
)),
|
)),
|
||||||
ConstValue::Scalar(x) =>
|
ConstValue::Scalar(x) =>
|
||||||
Operand::Immediate(Immediate::Scalar(x.with_default_tag().into())),
|
Operand::Immediate(Immediate::Scalar(x.with_default_tag().into())),
|
||||||
|
@ -609,7 +609,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
|
|||||||
fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, location: Location) {
|
fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, location: Location) {
|
||||||
debug!("visiting const {:?} @ {:?}", *constant, location);
|
debug!("visiting const {:?} @ {:?}", *constant, location);
|
||||||
|
|
||||||
collect_const(self.tcx, **constant, self.param_substs, self.output);
|
collect_const(self.tcx, *constant, self.param_substs, self.output);
|
||||||
|
|
||||||
self.super_const(constant);
|
self.super_const(constant);
|
||||||
}
|
}
|
||||||
@ -1248,17 +1248,17 @@ fn def_id_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||||||
|
|
||||||
fn collect_const<'a, 'tcx>(
|
fn collect_const<'a, 'tcx>(
|
||||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
constant: ty::Const<'tcx>,
|
constant: &'tcx ty::Const<'tcx>,
|
||||||
param_substs: SubstsRef<'tcx>,
|
param_substs: SubstsRef<'tcx>,
|
||||||
output: &mut Vec<MonoItem<'tcx>>,
|
output: &mut Vec<MonoItem<'tcx>>,
|
||||||
) {
|
) {
|
||||||
debug!("visiting const {:?}", constant);
|
debug!("visiting const {:?}", constant);
|
||||||
|
|
||||||
match constant.val {
|
match constant.val {
|
||||||
ConstValue::Slice(Scalar::Ptr(ptr), _) |
|
|
||||||
ConstValue::Scalar(Scalar::Ptr(ptr)) =>
|
ConstValue::Scalar(Scalar::Ptr(ptr)) =>
|
||||||
collect_miri(tcx, ptr.alloc_id, output),
|
collect_miri(tcx, ptr.alloc_id, output),
|
||||||
ConstValue::ByRef(_ptr, alloc) => {
|
ConstValue::Slice { data: alloc, start: _, end: _ } |
|
||||||
|
ConstValue::ByRef(_, alloc) => {
|
||||||
for &((), id) in alloc.relocations.values() {
|
for &((), id) in alloc.relocations.values() {
|
||||||
collect_miri(tcx, id, output);
|
collect_miri(tcx, id, output);
|
||||||
}
|
}
|
||||||
|
@ -401,7 +401,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
|
|||||||
// as well as the unprintable types of constants (see `push_type_name` for more details).
|
// as well as the unprintable types of constants (see `push_type_name` for more details).
|
||||||
pub fn push_const_name(&self, c: &Const<'tcx>, output: &mut String, debug: bool) {
|
pub fn push_const_name(&self, c: &Const<'tcx>, output: &mut String, debug: bool) {
|
||||||
match c.val {
|
match c.val {
|
||||||
ConstValue::Scalar(..) | ConstValue::Slice(..) | ConstValue::ByRef(..) => {
|
ConstValue::Scalar(..) | ConstValue::Slice { .. } | ConstValue::ByRef(..) => {
|
||||||
// FIXME(const_generics): we could probably do a better job here.
|
// FIXME(const_generics): we could probably do a better job here.
|
||||||
write!(output, "{:?}", c).unwrap()
|
write!(output, "{:?}", c).unwrap()
|
||||||
}
|
}
|
||||||
|
@ -458,9 +458,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
|
|||||||
span: self.span,
|
span: self.span,
|
||||||
ty: func_ty,
|
ty: func_ty,
|
||||||
user_ty: None,
|
user_ty: None,
|
||||||
literal: tcx.mk_const(
|
literal: ty::Const::zero_sized(tcx, func_ty),
|
||||||
ty::Const::zero_sized(func_ty),
|
|
||||||
),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let ref_loc = self.make_place(
|
let ref_loc = self.make_place(
|
||||||
@ -520,9 +518,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
|
|||||||
span: self.span,
|
span: self.span,
|
||||||
ty: self.tcx.types.usize,
|
ty: self.tcx.types.usize,
|
||||||
user_ty: None,
|
user_ty: None,
|
||||||
literal: self.tcx.mk_const(
|
literal: ty::Const::from_usize(self.tcx, value),
|
||||||
ty::Const::from_usize(self.tcx, value),
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -762,9 +758,7 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||||||
span,
|
span,
|
||||||
ty,
|
ty,
|
||||||
user_ty: None,
|
user_ty: None,
|
||||||
literal: tcx.mk_const(
|
literal: ty::Const::zero_sized(tcx, ty),
|
||||||
ty::Const::zero_sized(ty)
|
|
||||||
),
|
|
||||||
}),
|
}),
|
||||||
vec![rcvr])
|
vec![rcvr])
|
||||||
}
|
}
|
||||||
|
@ -282,7 +282,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
|
|||||||
c: &Constant<'tcx>,
|
c: &Constant<'tcx>,
|
||||||
) -> Option<Const<'tcx>> {
|
) -> Option<Const<'tcx>> {
|
||||||
self.ecx.tcx.span = c.span;
|
self.ecx.tcx.span = c.span;
|
||||||
match self.ecx.eval_const_to_op(*c.literal, None) {
|
match self.ecx.eval_const_to_op(c.literal, None) {
|
||||||
Ok(op) => {
|
Ok(op) => {
|
||||||
Some(op)
|
Some(op)
|
||||||
},
|
},
|
||||||
@ -506,7 +506,8 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
|
|||||||
span,
|
span,
|
||||||
ty,
|
ty,
|
||||||
user_ty: None,
|
user_ty: None,
|
||||||
literal: self.tcx.mk_const(ty::Const::from_scalar(
|
literal: self.tcx.mk_const(*ty::Const::from_scalar(
|
||||||
|
self.tcx,
|
||||||
scalar,
|
scalar,
|
||||||
ty,
|
ty,
|
||||||
))
|
))
|
||||||
|
@ -533,9 +533,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
|
|||||||
span,
|
span,
|
||||||
ty: self.tcx.types.bool,
|
ty: self.tcx.types.bool,
|
||||||
user_ty: None,
|
user_ty: None,
|
||||||
literal: self.tcx.mk_const(
|
literal: ty::Const::from_bool(self.tcx, val),
|
||||||
ty::Const::from_bool(self.tcx, val),
|
|
||||||
),
|
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -757,9 +757,7 @@ fn insert_panic_block<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||||||
span: mir.span,
|
span: mir.span,
|
||||||
ty: tcx.types.bool,
|
ty: tcx.types.bool,
|
||||||
user_ty: None,
|
user_ty: None,
|
||||||
literal: tcx.mk_const(
|
literal: ty::Const::from_bool(tcx, false),
|
||||||
ty::Const::from_bool(tcx, false),
|
|
||||||
),
|
|
||||||
}),
|
}),
|
||||||
expected: true,
|
expected: true,
|
||||||
msg: message,
|
msg: message,
|
||||||
|
@ -975,9 +975,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
|||||||
span: self.source_info.span,
|
span: self.source_info.span,
|
||||||
ty: self.tcx().types.usize,
|
ty: self.tcx().types.usize,
|
||||||
user_ty: None,
|
user_ty: None,
|
||||||
literal: self.tcx().mk_const(
|
literal: ty::Const::from_usize(self.tcx(), val.into()),
|
||||||
ty::Const::from_usize(self.tcx(), val.into())
|
|
||||||
),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4441,7 +4441,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
if element_ty.references_error() {
|
if element_ty.references_error() {
|
||||||
tcx.types.err
|
tcx.types.err
|
||||||
} else if let Ok(count) = count {
|
} else if let Ok(count) = count {
|
||||||
tcx.mk_ty(ty::Array(t, tcx.mk_const(count)))
|
tcx.mk_ty(ty::Array(t, count))
|
||||||
} else {
|
} else {
|
||||||
tcx.types.err
|
tcx.types.err
|
||||||
}
|
}
|
||||||
|
@ -2956,7 +2956,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
|
|||||||
ty::Str => Primitive(PrimitiveType::Str),
|
ty::Str => Primitive(PrimitiveType::Str),
|
||||||
ty::Slice(ty) => Slice(box ty.clean(cx)),
|
ty::Slice(ty) => Slice(box ty.clean(cx)),
|
||||||
ty::Array(ty, n) => {
|
ty::Array(ty, n) => {
|
||||||
let mut n = *cx.tcx.lift(&n).expect("array lift failed");
|
let mut n = cx.tcx.lift(&n).expect("array lift failed");
|
||||||
if let ConstValue::Unevaluated(def_id, substs) = n.val {
|
if let ConstValue::Unevaluated(def_id, substs) = n.val {
|
||||||
let param_env = cx.tcx.param_env(def_id);
|
let param_env = cx.tcx.param_env(def_id);
|
||||||
let cid = GlobalId {
|
let cid = GlobalId {
|
||||||
@ -4126,7 +4126,7 @@ fn name_from_pat(p: &hir::Pat) -> String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String {
|
fn print_const(cx: &DocContext<'_>, n: &ty::Const<'_>) -> String {
|
||||||
match n.val {
|
match n.val {
|
||||||
ConstValue::Unevaluated(def_id, _) => {
|
ConstValue::Unevaluated(def_id, _) => {
|
||||||
if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(def_id) {
|
if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(def_id) {
|
||||||
@ -4136,12 +4136,15 @@ fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
let mut s = String::new();
|
let mut s = n.to_string();
|
||||||
::rustc::mir::fmt_const_val(&mut s, n).expect("fmt_const_val failed");
|
|
||||||
// array lengths are obviously usize
|
// array lengths are obviously usize
|
||||||
if s.ends_with("usize") {
|
if s.ends_with("usize") {
|
||||||
let n = s.len() - "usize".len();
|
let n = s.len() - "usize".len();
|
||||||
s.truncate(n);
|
s.truncate(n);
|
||||||
|
if s.ends_with(": ") {
|
||||||
|
let n = s.len() - ": ".len();
|
||||||
|
s.truncate(n);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
s
|
s
|
||||||
},
|
},
|
||||||
|
@ -52,7 +52,7 @@ impl Drop for S {
|
|||||||
// StorageDead(_2);
|
// StorageDead(_2);
|
||||||
// StorageLive(_4);
|
// StorageLive(_4);
|
||||||
// _4 = move _1;
|
// _4 = move _1;
|
||||||
// _3 = const std::mem::drop(move _4) -> [return: bb5, unwind: bb7];
|
// _3 = const std::mem::drop::<std::boxed::Box<S>>(move _4) -> [return: bb5, unwind: bb7];
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// bb5: {
|
// bb5: {
|
||||||
|
15
src/test/mir-opt/byte_slice.rs
Normal file
15
src/test/mir-opt/byte_slice.rs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// compile-flags: -Z mir-opt-level=0
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let x = b"foo";
|
||||||
|
let y = [5u8, b'x'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// END RUST SOURCE
|
||||||
|
// START rustc.main.EraseRegions.after.mir
|
||||||
|
// ...
|
||||||
|
// _1 = const b"foo";
|
||||||
|
// ...
|
||||||
|
// _2 = [const 5u8, const 120u8];
|
||||||
|
// ...
|
||||||
|
// END rustc.main.EraseRegions.after.mir
|
@ -25,7 +25,7 @@ impl X for () {
|
|||||||
// ...
|
// ...
|
||||||
// bb0: {
|
// bb0: {
|
||||||
// ...
|
// ...
|
||||||
// _0 = const X::y(move _2) -> bb1;
|
// _0 = const <dyn X as X>::y(move _2) -> bb1;
|
||||||
// }
|
// }
|
||||||
// ...
|
// ...
|
||||||
// END rustc.test.Inline.after.mir
|
// END rustc.test.Inline.after.mir
|
||||||
|
@ -30,7 +30,7 @@ fn main() {
|
|||||||
// ...
|
// ...
|
||||||
// bb0: {
|
// bb0: {
|
||||||
// ...
|
// ...
|
||||||
// _0 = const X::y(move _2) -> bb1;
|
// _0 = const <dyn X as X>::y(move _2) -> bb1;
|
||||||
// }
|
// }
|
||||||
// ...
|
// ...
|
||||||
// END rustc.test2.Inline.after.mir
|
// END rustc.test2.Inline.after.mir
|
||||||
|
@ -93,7 +93,7 @@ fn main() {
|
|||||||
// StorageDead(_3);
|
// StorageDead(_3);
|
||||||
// StorageLive(_6);
|
// StorageLive(_6);
|
||||||
// _6 = &_2;
|
// _6 = &_2;
|
||||||
// _5 = const std::mem::drop(move _6) -> [return: bb19, unwind: bb4];
|
// _5 = const std::mem::drop::<&i32>(move _6) -> [return: bb19, unwind: bb4];
|
||||||
// }
|
// }
|
||||||
// bb19: {
|
// bb19: {
|
||||||
// StorageDead(_6);
|
// StorageDead(_6);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
// Test that we don't ICE when trying to dump MIR for unusual item types and
|
// Test that we don't ICE when trying to dump MIR for unusual item types and
|
||||||
// that we don't create filenames containing `<` and `>`
|
// that we don't create filenames containing `<` and `>`
|
||||||
|
// ignore-tidy-linelength
|
||||||
|
|
||||||
struct A;
|
struct A;
|
||||||
|
|
||||||
@ -68,7 +69,7 @@ fn main() {
|
|||||||
// }
|
// }
|
||||||
// bb7: {
|
// bb7: {
|
||||||
// _2 = &mut (*_1);
|
// _2 = &mut (*_1);
|
||||||
// _3 = const std::ops::Drop::drop(move _2) -> [return: bb6, unwind: bb5];
|
// _3 = const <std::vec::Vec<i32> as std::ops::Drop>::drop(move _2) -> [return: bb6, unwind: bb5];
|
||||||
// }
|
// }
|
||||||
// END rustc.ptr-real_drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir
|
// END rustc.ptr-real_drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ error[E0282]: type annotations needed
|
|||||||
--> $DIR/cannot-infer-const-args.rs:9:5
|
--> $DIR/cannot-infer-const-args.rs:9:5
|
||||||
|
|
|
|
||||||
LL | foo();
|
LL | foo();
|
||||||
| ^^^ cannot infer type for `fn() -> usize {foo::<_>}`
|
| ^^^ cannot infer type for `fn() -> usize {foo::<_: usize>}`
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ error[E0005]: refutable pattern in function argument: `&[]` not covered
|
|||||||
LL | const fn slice([a, b]: &[i32]) -> i32 {
|
LL | const fn slice([a, b]: &[i32]) -> i32 {
|
||||||
| ^^^^^^ pattern `&[]` not covered
|
| ^^^^^^ pattern `&[]` not covered
|
||||||
|
|
||||||
error[E0723]: can only call other `const fn` within a `const fn`, but `const std::ops::Add::add` is not stable as `const fn`
|
error[E0723]: can only call other `const fn` within a `const fn`, but `const <&i32 as std::ops::Add>::add` is not stable as `const fn`
|
||||||
--> $DIR/const_let_refutable.rs:4:5
|
--> $DIR/const_let_refutable.rs:4:5
|
||||||
|
|
|
|
||||||
LL | a + b
|
LL | a + b
|
||||||
|
@ -4,7 +4,7 @@ error[E0005]: refutable pattern in function argument: `&[]` not covered
|
|||||||
LL | const fn slice([a, b]: &[i32]) -> i32 {
|
LL | const fn slice([a, b]: &[i32]) -> i32 {
|
||||||
| ^^^^^^ pattern `&[]` not covered
|
| ^^^^^^ pattern `&[]` not covered
|
||||||
|
|
||||||
error[E0723]: can only call other `const fn` within a `const fn`, but `const std::ops::Add::add` is not stable as `const fn`
|
error[E0723]: can only call other `const fn` within a `const fn`, but `const <&i32 as std::ops::Add>::add` is not stable as `const fn`
|
||||||
--> $DIR/const_let_refutable.rs:4:5
|
--> $DIR/const_let_refutable.rs:4:5
|
||||||
|
|
|
|
||||||
LL | a + b
|
LL | a + b
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
thread 'rustc' panicked at 'assertion failed: rows.iter().all(|r| r.len() == v.len())', src/librustc_mir/hair/pattern/_match.rs:1083:5
|
thread 'rustc' panicked at 'assertion failed: rows.iter().all(|r| r.len() == v.len())', src/librustc_mir/hair/pattern/_match.rs:1085:5
|
||||||
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
|
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
|
||||||
|
|
||||||
error: internal compiler error: unexpected panic
|
error: internal compiler error: unexpected panic
|
||||||
|
@ -6,13 +6,13 @@ fn main() {
|
|||||||
match s {
|
match s {
|
||||||
MAGIC_TEST => (),
|
MAGIC_TEST => (),
|
||||||
[0x00, 0x00, 0x00, 0x00] => (),
|
[0x00, 0x00, 0x00, 0x00] => (),
|
||||||
[4, 5, 6, 7] => (), //~ ERROR unreachable pattern
|
[4, 5, 6, 7] => (), // FIXME(oli-obk): this should warn, but currently does not
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
match s {
|
match s {
|
||||||
[0x00, 0x00, 0x00, 0x00] => (),
|
[0x00, 0x00, 0x00, 0x00] => (),
|
||||||
MAGIC_TEST => (),
|
MAGIC_TEST => (),
|
||||||
[4, 5, 6, 7] => (), //~ ERROR unreachable pattern
|
[4, 5, 6, 7] => (), // FIXME(oli-obk): this should warn, but currently does not
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
match s {
|
match s {
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/slice-pattern-const-2.rs:9:9
|
--> $DIR/slice-pattern-const-2.rs:28:9
|
||||||
|
|
|
|
||||||
LL | [4, 5, 6, 7] => (),
|
LL | FOO => (),
|
||||||
| ^^^^^^^^^^^^
|
| ^^^
|
||||||
|
|
|
|
||||||
note: lint level defined here
|
note: lint level defined here
|
||||||
--> $DIR/slice-pattern-const-2.rs:1:9
|
--> $DIR/slice-pattern-const-2.rs:1:9
|
||||||
@ -10,17 +10,5 @@ note: lint level defined here
|
|||||||
LL | #![deny(unreachable_patterns)]
|
LL | #![deny(unreachable_patterns)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: aborting due to previous error
|
||||||
--> $DIR/slice-pattern-const-2.rs:15:9
|
|
||||||
|
|
|
||||||
LL | [4, 5, 6, 7] => (),
|
|
||||||
| ^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: unreachable pattern
|
|
||||||
--> $DIR/slice-pattern-const-2.rs:28:9
|
|
||||||
|
|
|
||||||
LL | FOO => (),
|
|
||||||
| ^^^
|
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
|
||||||
|
|
||||||
|
14
src/test/ui/symbol-names/impl2.rs
Normal file
14
src/test/ui/symbol-names/impl2.rs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#![feature(rustc_attrs)]
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
trait Foo {
|
||||||
|
fn baz();
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Foo for [u8; 1 + 2] {
|
||||||
|
#[rustc_def_path] //~ ERROR def-path(<[u8; _] as Foo>::baz)
|
||||||
|
fn baz() { }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
}
|
8
src/test/ui/symbol-names/impl2.stderr
Normal file
8
src/test/ui/symbol-names/impl2.stderr
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
error: def-path(<[u8; _] as Foo>::baz)
|
||||||
|
--> $DIR/impl2.rs:9:5
|
||||||
|
|
|
||||||
|
LL | #[rustc_def_path]
|
||||||
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
Loading…
Reference in New Issue
Block a user