Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 6 pull requests #58691

Merged
merged 29 commits into from
Feb 24, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
e41e694
Clarify guarantees for `Box` allocation
Feb 5, 2019
70c5af8
Avoid allocation in std::sys::unix::weak
cuviper Feb 13, 2019
33d80bf
Return without a reference in unix Weak::get()
cuviper Feb 13, 2019
235a6b7
Expose const -> op functions that don't allow violiting const eval in…
oli-obk Feb 16, 2019
bd18cc5
Remove an intermediate value from discriminant reading
oli-obk Feb 16, 2019
b2bf37a
Burn some invariants we keep up into code
oli-obk Feb 16, 2019
f7c4931
Reuse the `Pointer` type instead of passing reassembling it at many u…
oli-obk Feb 16, 2019
7db96a3
Reintroduce the invariant comment for clarity
oli-obk Feb 16, 2019
bee3c67
Update src/librustc_mir/interpret/operand.rs
RalfJung Feb 16, 2019
525983a
Make validity checking use `MPlaceTy` instead of `OpTy`
oli-obk Feb 15, 2019
27e438a
Make `may_normalize` explicit in the type system
oli-obk Feb 16, 2019
4fdeb2d
Add `eval` prefix to clarify what the function does
oli-obk Feb 16, 2019
4b08533
Update docs and visibilities of const to op methods
oli-obk Feb 16, 2019
1fe7eb0
Limit the visibility further and expand on a comment
oli-obk Feb 16, 2019
0651157
Remove sys::*::Stderr Write implementation
pitdicker Feb 11, 2019
cc20ed6
Remove unused Read implementation on sys::Windows::Stdin
pitdicker Feb 14, 2019
f411852
Refactor Windows stdio and remove stdin double buffering
pitdicker Feb 14, 2019
b09803e
Address review comments
pitdicker Feb 19, 2019
6464e32
Use standard Read/Write traits in sys::stdio
pitdicker Feb 20, 2019
7cfddfb
Improve parsing diagnostic for negative supertrait bounds
hdhoang Dec 16, 2018
1a944b0
Remove pub(crate) from stderr_raw
pitdicker Feb 23, 2019
bde4d19
rustdoc: support methods on primitives in intra-doc links
tspiteri Feb 22, 2019
aa0fa75
fix build for Rust 2018 now that #58100 has been merged
tspiteri Feb 23, 2019
ae64668
Rollup merge of #57364 - hdhoang:33418_negative_bounds, r=estebank
Centril Feb 24, 2019
55b5ab8
Rollup merge of #58183 - jethrogb:jb/alloc-box-guarantees, r=SimonSapin
Centril Feb 24, 2019
b78e9f4
Rollup merge of #58442 - cuviper:unix-weak, r=alexcrichton
Centril Feb 24, 2019
4dcb7af
Rollup merge of #58454 - pitdicker:windows_stdio, r=alexcrichton
Centril Feb 24, 2019
1082a29
Rollup merge of #58511 - oli-obk:const_to_op, r=RalfJung
Centril Feb 24, 2019
f01ebc5
Rollup merge of #58642 - tspiteri:intra-rustdoc-prim-method, r=Guilla…
Centril Feb 24, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/liballoc/alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ extern "Rust" {
/// This type implements the [`Alloc`] trait by forwarding calls
/// to the allocator registered with the `#[global_allocator]` attribute
/// if there is one, or the `std` crate’s default.
///
/// Note: while this type is unstable, the functionality it provides can be
/// accessed through the [free functions in `alloc`](index.html#functions).
#[unstable(feature = "allocator_api", issue = "32838")]
#[derive(Copy, Clone, Default, Debug)]
pub struct Global;
Expand Down
10 changes: 10 additions & 0 deletions src/liballoc/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@
//! heap allocation in Rust. Boxes provide ownership for this allocation, and
//! drop their contents when they go out of scope.
//!
//! For non-zero-sized values, a [`Box`] will use the [`Global`] allocator for
//! its allocation. It is valid to convert both ways between a [`Box`] and a
//! raw pointer allocated with the [`Global`] allocator, given that the
//! [`Layout`] used with the allocator is correct for the type. More precisely,
//! a `value: *mut T` that has been allocated with the [`Global`] allocator
//! with `Layout::for_value(&*value)` may be converted into a box using
//! `Box::<T>::from_raw(value)`. Conversely, the memory backing a `value: *mut
//! T` obtained from `Box::<T>::into_raw` may be deallocated using the
//! [`Global`] allocator with `Layout::for_value(&*value)`.
//!
//! # Examples
//!
//! Move a value from the stack to the heap by creating a [`Box`]:
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/ich/impls_ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ impl_stable_hash_for!(
impl<'tcx> for enum mir::interpret::ConstValue<'tcx> [ mir::interpret::ConstValue ] {
Scalar(val),
Slice(a, b),
ByRef(id, alloc, offset),
ByRef(ptr, alloc),
}
);
impl_stable_hash_for!(struct crate::mir::interpret::RawConst<'tcx> {
Expand Down
6 changes: 3 additions & 3 deletions src/librustc/mir/interpret/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ pub enum ConstValue<'tcx> {
/// it.
Slice(Scalar, u64),

/// An allocation together with an offset into the allocation.
/// Invariant: the `AllocId` matches the allocation.
ByRef(AllocId, &'tcx Allocation, Size),
/// An allocation together with a pointer into the allocation.
/// Invariant: the pointer's `AllocId` resolves to the allocation.
ByRef(Pointer, &'tcx Allocation),
}

#[cfg(target_arch = "x86_64")]
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/ty/structural_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -505,8 +505,8 @@ impl<'a, 'tcx> Lift<'tcx> for ConstValue<'a> {
match *self {
ConstValue::Scalar(x) => Some(ConstValue::Scalar(x)),
ConstValue::Slice(x, y) => Some(ConstValue::Slice(x, y)),
ConstValue::ByRef(x, alloc, z) => Some(ConstValue::ByRef(
x, alloc.lift_to_tcx(tcx)?, z,
ConstValue::ByRef(ptr, alloc) => Some(ConstValue::ByRef(
ptr, alloc.lift_to_tcx(tcx)?,
)),
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_codegen_llvm/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ pub fn codegen_static_initializer(
let static_ = cx.tcx.const_eval(param_env.and(cid))?;

let alloc = match static_.val {
ConstValue::ByRef(_, alloc, n) if n.bytes() == 0 => alloc,
ConstValue::ByRef(ptr, alloc) if ptr.offset.bytes() == 0 => alloc,
_ => bug!("static const eval returned {:#?}", static_),
};
Ok((const_alloc_to_llvm(cx, alloc), alloc))
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_codegen_ssa/mir/operand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandRef<'tcx, V> {
let b_llval = bx.cx().const_usize(b);
OperandValue::Pair(a_llval, b_llval)
},
ConstValue::ByRef(_, alloc, offset) => {
return Ok(bx.load_operand(bx.cx().from_const_alloc(layout, alloc, offset)));
ConstValue::ByRef(ptr, alloc) => {
return Ok(bx.load_operand(bx.cx().from_const_alloc(layout, alloc, ptr.offset)));
},
};

Expand Down
4 changes: 2 additions & 2 deletions src/librustc_codegen_ssa/mir/place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -417,8 +417,8 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let layout = cx.layout_of(self.monomorphize(&ty));
match bx.tcx().const_eval(param_env.and(cid)) {
Ok(val) => match val.val {
mir::interpret::ConstValue::ByRef(_, alloc, offset) => {
bx.cx().from_const_alloc(layout, alloc, offset)
mir::interpret::ConstValue::ByRef(ptr, alloc) => {
bx.cx().from_const_alloc(layout, alloc, ptr.offset)
}
_ => bug!("promoteds should have an allocation: {:?}", val),
},
Expand Down
86 changes: 44 additions & 42 deletions src/librustc_mir/const_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use syntax::ast::Mutability;
use syntax::source_map::{Span, DUMMY_SP};

use crate::interpret::{self,
PlaceTy, MPlaceTy, MemPlace, OpTy, ImmTy, Operand, Immediate, Scalar, Pointer,
PlaceTy, MPlaceTy, MemPlace, OpTy, ImmTy, Immediate, Scalar, Pointer,
RawConst, ConstValue,
EvalResult, EvalError, EvalErrorKind, GlobalId, EvalContext, StackPopCleanup,
Allocation, AllocId, MemoryKind,
Expand Down Expand Up @@ -62,45 +62,46 @@ pub(crate) fn eval_promoted<'a, 'mir, 'tcx>(
eval_body_using_ecx(&mut ecx, cid, Some(mir), param_env)
}

// FIXME: These two conversion functions are bad hacks. We should just always use allocations.
pub fn op_to_const<'tcx>(
fn mplace_to_const<'tcx>(
ecx: &CompileTimeEvalContext<'_, '_, 'tcx>,
mplace: MPlaceTy<'tcx>,
) -> EvalResult<'tcx, ty::Const<'tcx>> {
let MemPlace { ptr, align, meta } = *mplace;
// extract alloc-offset pair
assert!(meta.is_none());
let ptr = ptr.to_ptr()?;
let alloc = ecx.memory.get(ptr.alloc_id)?;
assert!(alloc.align >= align);
assert!(alloc.bytes.len() as u64 - ptr.offset.bytes() >= mplace.layout.size.bytes());
let mut alloc = alloc.clone();
alloc.align = align;
// FIXME shouldn't it be the case that `mark_static_initialized` has already
// interned this? I thought that is the entire point of that `FinishStatic` stuff?
let alloc = ecx.tcx.intern_const_alloc(alloc);
let val = ConstValue::ByRef(ptr, alloc);
Ok(ty::Const { val, ty: mplace.layout.ty })
}

fn op_to_const<'tcx>(
ecx: &CompileTimeEvalContext<'_, '_, 'tcx>,
op: OpTy<'tcx>,
may_normalize: bool,
) -> EvalResult<'tcx, ty::Const<'tcx>> {
// We do not normalize just any data. Only scalar layout and slices.
let normalize = may_normalize
&& match op.layout.abi {
layout::Abi::Scalar(..) => true,
layout::Abi::ScalarPair(..) => op.layout.ty.is_slice(),
_ => false,
};
let normalize = match op.layout.abi {
layout::Abi::Scalar(..) => true,
layout::Abi::ScalarPair(..) => op.layout.ty.is_slice(),
_ => false,
};
let normalized_op = if normalize {
ecx.try_read_immediate(op)?
Err(*ecx.read_immediate(op).expect("normalization works on validated constants"))
} else {
match *op {
Operand::Indirect(mplace) => Err(mplace),
Operand::Immediate(val) => Ok(val)
}
op.try_as_mplace()
};
let val = match normalized_op {
Err(MemPlace { ptr, align, meta }) => {
// extract alloc-offset pair
assert!(meta.is_none());
let ptr = ptr.to_ptr()?;
let alloc = ecx.memory.get(ptr.alloc_id)?;
assert!(alloc.align >= align);
assert!(alloc.bytes.len() as u64 - ptr.offset.bytes() >= op.layout.size.bytes());
let mut alloc = alloc.clone();
alloc.align = align;
// FIXME shouldn't it be the case that `mark_static_initialized` has already
// interned this? I thought that is the entire point of that `FinishStatic` stuff?
let alloc = ecx.tcx.intern_const_alloc(alloc);
ConstValue::ByRef(ptr.alloc_id, alloc, ptr.offset)
},
Ok(Immediate::Scalar(x)) =>
Ok(mplace) => return mplace_to_const(ecx, mplace),
Err(Immediate::Scalar(x)) =>
ConstValue::Scalar(x.not_undef()?),
Ok(Immediate::ScalarPair(a, b)) =>
Err(Immediate::ScalarPair(a, b)) =>
ConstValue::Slice(a.not_undef()?, b.to_usize(ecx)?),
};
Ok(ty::Const { val, ty: op.layout.ty })
Expand Down Expand Up @@ -476,7 +477,7 @@ pub fn const_field<'a, 'tcx>(
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env);
let result = (|| {
// get the operand again
let op = ecx.lazy_const_to_op(ty::LazyConst::Evaluated(value), value.ty)?;
let op = ecx.const_to_op(value, None)?;
// downcast
let down = match variant {
None => op,
Expand All @@ -486,7 +487,7 @@ pub fn const_field<'a, 'tcx>(
let field = ecx.operand_field(down, field.index() as u64)?;
// and finally move back to the const world, always normalizing because
// this is not called for statics.
op_to_const(&ecx, field, true)
op_to_const(&ecx, field)
})();
result.map_err(|error| {
let err = error_to_const_error(&ecx, error);
Expand All @@ -502,7 +503,7 @@ pub fn const_variant_index<'a, 'tcx>(
) -> EvalResult<'tcx, VariantIdx> {
trace!("const_variant_index: {:?}", val);
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env);
let op = ecx.lazy_const_to_op(ty::LazyConst::Evaluated(val), val.ty)?;
let op = ecx.const_to_op(val, None)?;
Ok(ecx.read_discriminant(op)?.1)
}

Expand All @@ -523,22 +524,23 @@ fn validate_and_turn_into_const<'a, 'tcx>(
let cid = key.value;
let ecx = mk_eval_cx(tcx, tcx.def_span(key.value.instance.def_id()), key.param_env);
let val = (|| {
let op = ecx.raw_const_to_mplace(constant)?.into();
// FIXME: Once the visitor infrastructure landed, change validation to
// work directly on `MPlaceTy`.
let mut ref_tracking = RefTracking::new(op);
while let Some((op, path)) = ref_tracking.todo.pop() {
let mplace = ecx.raw_const_to_mplace(constant)?;
let mut ref_tracking = RefTracking::new(mplace);
while let Some((mplace, path)) = ref_tracking.todo.pop() {
ecx.validate_operand(
op,
mplace.into(),
path,
Some(&mut ref_tracking),
true, // const mode
)?;
}
// Now that we validated, turn this into a proper constant.
let def_id = cid.instance.def.def_id();
let normalize = tcx.is_static(def_id).is_none() && cid.promoted.is_none();
op_to_const(&ecx, op, normalize)
if tcx.is_static(def_id).is_some() || cid.promoted.is_some() {
mplace_to_const(&ecx, mplace)
} else {
op_to_const(&ecx, mplace.into())
}
})();

val.map_err(|error| {
Expand Down
12 changes: 5 additions & 7 deletions src/librustc_mir/hair/pattern/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ use rustc::ty::{self, Ty, TyCtxt, TypeFoldable, Const};
use rustc::ty::layout::{Integer, IntegerExt, VariantIdx, Size};

use rustc::mir::Field;
use rustc::mir::interpret::{ConstValue, Pointer, Scalar};
use rustc::mir::interpret::{ConstValue, Scalar};
use rustc::util::common::ErrorReported;

use syntax::attr::{SignedInt, UnsignedInt};
Expand Down Expand Up @@ -214,9 +214,8 @@ impl<'a, 'tcx> LiteralExpander<'a, 'tcx> {
match (val, &crty.sty, &rty.sty) {
// the easy case, deref a reference
(ConstValue::Scalar(Scalar::Ptr(p)), x, y) if x == y => ConstValue::ByRef(
p.alloc_id,
p,
self.tcx.alloc_map.lock().unwrap_memory(p.alloc_id),
p.offset,
),
// 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)) => {
Expand Down Expand Up @@ -1428,15 +1427,14 @@ fn slice_pat_covered_by_const<'tcx>(
suffix: &[Pattern<'tcx>]
) -> Result<bool, ErrorReported> {
let data: &[u8] = match (const_val.val, &const_val.ty.sty) {
(ConstValue::ByRef(id, alloc, offset), ty::Array(t, n)) => {
(ConstValue::ByRef(ptr, alloc), ty::Array(t, n)) => {
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);
}
let ptr = Pointer::new(id, offset);
let n = n.assert_usize(tcx).unwrap();
alloc.get_bytes(&tcx, ptr, Size::from_bytes(n)).unwrap()
},
Expand Down Expand Up @@ -1778,8 +1776,8 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
let (opt_ptr, n, ty) = match value.ty.sty {
ty::TyKind::Array(t, n) => {
match value.val {
ConstValue::ByRef(id, alloc, offset) => (
Some((Pointer::new(id, offset), alloc)),
ConstValue::ByRef(ptr, alloc) => (
Some((ptr, alloc)),
n.unwrap_usize(cx.tcx),
t,
),
Expand Down
Loading