Auto merge of #57879 - Centril:rollup, r=Centril

Rollup of 9 pull requests

Successful merges:

 - #57380 (Fix Instant/Duration math precision & associativity on Windows)
 - #57606 (Get rid of the fake stack frame for reading from constants)
 - #57803 (Several changes to libunwind for SGX target)
 - #57846 (rustdoc: fix ICE from loading proc-macro stubs)
 - #57860 (Add os::fortanix_sgx::ffi module)
 - #57861 (Don't export table by default in wasm)
 - #57863 (Add suggestion for incorrect field syntax.)
 - #57867 (Fix std::future::from_generator documentation)
 - #57873 (Stabilize no_panic_pow)

Failed merges:

r? @ghost
This commit is contained in:
bors 2019-01-24 21:23:11 +00:00
commit 278067d34d
28 changed files with 432 additions and 172 deletions

View File

@ -32,7 +32,7 @@ RUN /tmp/build-solaris-toolchain.sh sparcv9 sparcv9 solaris-sparc
COPY dist-various-2/build-x86_64-fortanix-unknown-sgx-toolchain.sh /tmp/
# We pass the commit id of the port of LLVM's libunwind to the build script.
# Any update to the commit id here, should cause the container image to be re-built from this point on.
RUN /tmp/build-x86_64-fortanix-unknown-sgx-toolchain.sh "bbe23902411be88d7388f381becefadd6e3ef819"
RUN /tmp/build-x86_64-fortanix-unknown-sgx-toolchain.sh "13fad13f8ea83a8da58d04a5faa45943151b3398"
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh

View File

@ -847,13 +847,12 @@ overflow occurred.
Basic usage:
```
#![feature(no_panic_pow)]
", $Feature, "assert_eq!(8", stringify!($SelfT), ".checked_pow(2), Some(64));
assert_eq!(", stringify!($SelfT), "::max_value().checked_pow(2), None);",
$EndFeature, "
```"),
#[unstable(feature = "no_panic_pow", issue = "48320")]
#[stable(feature = "no_panic_pow", since = "1.34.0")]
#[inline]
pub fn checked_pow(self, mut exp: u32) -> Option<Self> {
let mut base = self;
@ -966,7 +965,6 @@ saturating at the numeric bounds instead of overflowing.
Basic usage:
```
#![feature(no_panic_pow)]
", $Feature, "use std::", stringify!($SelfT), ";
assert_eq!((-4", stringify!($SelfT), ").saturating_pow(3), -64);
@ -974,7 +972,7 @@ assert_eq!(", stringify!($SelfT), "::MIN.saturating_pow(2), ", stringify!($SelfT
assert_eq!(", stringify!($SelfT), "::MIN.saturating_pow(3), ", stringify!($SelfT), "::MIN);",
$EndFeature, "
```"),
#[unstable(feature = "no_panic_pow", issue = "48320")]
#[stable(feature = "no_panic_pow", since = "1.34.0")]
#[inline]
pub fn saturating_pow(self, exp: u32) -> Self {
match self.checked_pow(exp) {
@ -1297,13 +1295,12 @@ wrapping around at the boundary of the type.
Basic usage:
```
#![feature(no_panic_pow)]
", $Feature, "assert_eq!(3", stringify!($SelfT), ".wrapping_pow(4), 81);
assert_eq!(3i8.wrapping_pow(5), -13);
assert_eq!(3i8.wrapping_pow(6), -39);",
$EndFeature, "
```"),
#[unstable(feature = "no_panic_pow", issue = "48320")]
#[stable(feature = "no_panic_pow", since = "1.34.0")]
#[inline]
pub fn wrapping_pow(self, mut exp: u32) -> Self {
let mut base = self;
@ -1669,12 +1666,11 @@ whether an overflow happened.
Basic usage:
```
#![feature(no_panic_pow)]
", $Feature, "assert_eq!(3", stringify!($SelfT), ".overflowing_pow(4), (81, false));
assert_eq!(3i8.overflowing_pow(5), (-13, true));",
$EndFeature, "
```"),
#[unstable(feature = "no_panic_pow", issue = "48320")]
#[stable(feature = "no_panic_pow", since = "1.34.0")]
#[inline]
pub fn overflowing_pow(self, mut exp: u32) -> (Self, bool) {
let mut base = self;
@ -2789,11 +2785,10 @@ overflow occurred.
Basic usage:
```
#![feature(no_panic_pow)]
", $Feature, "assert_eq!(2", stringify!($SelfT), ".checked_pow(5), Some(32));
assert_eq!(", stringify!($SelfT), "::max_value().checked_pow(2), None);", $EndFeature, "
```"),
#[unstable(feature = "no_panic_pow", issue = "48320")]
#[stable(feature = "no_panic_pow", since = "1.34.0")]
#[inline]
pub fn checked_pow(self, mut exp: u32) -> Option<Self> {
let mut base = self;
@ -2893,14 +2888,13 @@ saturating at the numeric bounds instead of overflowing.
Basic usage:
```
#![feature(no_panic_pow)]
", $Feature, "use std::", stringify!($SelfT), ";
assert_eq!(4", stringify!($SelfT), ".saturating_pow(3), 64);
assert_eq!(", stringify!($SelfT), "::MAX.saturating_pow(2), ", stringify!($SelfT), "::MAX);",
$EndFeature, "
```"),
#[unstable(feature = "no_panic_pow", issue = "48320")]
#[stable(feature = "no_panic_pow", since = "1.34.0")]
#[inline]
pub fn saturating_pow(self, exp: u32) -> Self {
match self.checked_pow(exp) {
@ -3178,11 +3172,10 @@ wrapping around at the boundary of the type.
Basic usage:
```
#![feature(no_panic_pow)]
", $Feature, "assert_eq!(3", stringify!($SelfT), ".wrapping_pow(5), 243);
assert_eq!(3u8.wrapping_pow(6), 217);", $EndFeature, "
```"),
#[unstable(feature = "no_panic_pow", issue = "48320")]
#[stable(feature = "no_panic_pow", since = "1.34.0")]
#[inline]
pub fn wrapping_pow(self, mut exp: u32) -> Self {
let mut base = self;
@ -3497,11 +3490,10 @@ whether an overflow happened.
Basic usage:
```
#![feature(no_panic_pow)]
", $Feature, "assert_eq!(3", stringify!($SelfT), ".overflowing_pow(5), (243, false));
assert_eq!(3u8.overflowing_pow(6), (217, true));", $EndFeature, "
```"),
#[unstable(feature = "no_panic_pow", issue = "48320")]
#[stable(feature = "no_panic_pow", since = "1.34.0")]
#[inline]
pub fn overflowing_pow(self, mut exp: u32) -> (Self, bool) {
let mut base = self;

View File

@ -911,9 +911,6 @@ impl<'a> WasmLd<'a> {
// For now we just never have an entry symbol
cmd.arg("--no-entry");
// Make the default table accessible
cmd.arg("--export-table");
// Rust code should never have warnings, and warnings are often
// indicative of bugs, let's prevent them.
cmd.arg("--fatal-warnings");

View File

@ -59,7 +59,6 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let field = const_field(
bx.tcx(),
ty::ParamEnv::reveal_all(),
self.instance,
None,
mir::Field::new(field as usize),
c,

View File

@ -10,11 +10,10 @@ use rustc::hir::{self, def_id::DefId};
use rustc::hir::def::Def;
use rustc::mir::interpret::{ConstEvalErr, ErrorHandled};
use rustc::mir;
use rustc::ty::{self, TyCtxt, Instance, query::TyCtxtAt};
use rustc::ty::{self, TyCtxt, query::TyCtxtAt};
use rustc::ty::layout::{self, LayoutOf, TyLayout, VariantIdx};
use rustc::ty::subst::Subst;
use rustc::traits::Reveal;
use rustc_data_structures::indexed_vec::IndexVec;
use rustc_data_structures::fx::FxHashMap;
use rustc::util::common::ErrorReported;
@ -35,56 +34,6 @@ const STEPS_UNTIL_DETECTOR_ENABLED: isize = 1_000_000;
/// Should be a power of two for performance reasons.
const DETECTOR_SNAPSHOT_PERIOD: isize = 256;
/// Warning: do not use this function if you expect to start interpreting the given `Mir`.
/// The `EvalContext` is only meant to be used to query values from constants and statics.
///
/// This function is used during const propagation. We cannot use `mk_eval_cx`, because copy
/// propagation happens *during* the computation of the MIR of the current function. So if we
/// tried to call the `optimized_mir` query, we'd get a cycle error because we are (transitively)
/// inside the `optimized_mir` query of the `Instance` given.
///
/// Since we are looking at the MIR of the function in an abstract manner, we don't have a
/// `ParamEnv` available to us. This function creates a `ParamEnv` for the given instance.
pub fn mk_borrowck_eval_cx<'a, 'mir, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
instance: Instance<'tcx>,
mir: &'mir mir::Mir<'tcx>,
span: Span,
) -> EvalResult<'tcx, CompileTimeEvalContext<'a, 'mir, 'tcx>> {
debug!("mk_borrowck_eval_cx: {:?}", instance);
let param_env = tcx.param_env(instance.def_id());
mk_eval_cx_inner(tcx, instance, mir, span, param_env)
}
/// This is just a helper function to reduce code duplication between `mk_borrowck_eval_cx` and
/// `mk_eval_cx`. Do not call this function directly.
fn mk_eval_cx_inner<'a, 'mir, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
instance: Instance<'tcx>,
mir: &'mir mir::Mir<'tcx>,
span: Span,
param_env: ty::ParamEnv<'tcx>,
) -> EvalResult<'tcx, CompileTimeEvalContext<'a, 'mir, 'tcx>> {
let mut ecx = EvalContext::new(tcx.at(span), param_env, CompileTimeInterpreter::new());
// Insert a stack frame so any queries have the correct substs.
// We also avoid all the extra work performed by push_stack_frame,
// like initializing local variables
ecx.stack.push(interpret::Frame {
block: mir::START_BLOCK,
locals: IndexVec::new(),
local_layouts: IndexVec::new(),
instance,
span,
mir,
return_place: None,
return_to_block: StackPopCleanup::Goto(None), // never pop
stmt: 0,
extra: (),
});
Ok(ecx)
}
/// Warning: do not use this function if you expect to start interpreting the given `Mir`.
/// The `EvalContext` is only meant to be used to do field and index projections into constants for
/// `simd_shuffle` and const patterns in match arms.
///
@ -92,15 +41,13 @@ fn mk_eval_cx_inner<'a, 'mir, 'tcx>(
/// that inform us about the generic bounds of the constant. E.g. using an associated constant
/// of a function's generic parameter will require knowledge about the bounds on the generic
/// parameter. These bounds are passed to `mk_eval_cx` via the `ParamEnv` argument.
fn mk_eval_cx<'a, 'tcx>(
pub(crate) fn mk_eval_cx<'a, 'mir, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
instance: Instance<'tcx>,
span: Span,
param_env: ty::ParamEnv<'tcx>,
) -> EvalResult<'tcx, CompileTimeEvalContext<'a, 'tcx, 'tcx>> {
debug!("mk_eval_cx: {:?}, {:?}", instance, param_env);
let span = tcx.def_span(instance.def_id());
let mir = tcx.optimized_mir(instance.def.def_id());
mk_eval_cx_inner(tcx, instance, mir, span, param_env)
) -> CompileTimeEvalContext<'a, 'mir, 'tcx> {
debug!("mk_eval_cx: {:?}", param_env);
EvalContext::new(tcx.at(span), param_env, CompileTimeInterpreter::new())
}
pub(crate) fn eval_promoted<'a, 'mir, 'tcx>(
@ -109,7 +56,8 @@ pub(crate) fn eval_promoted<'a, 'mir, 'tcx>(
mir: &'mir mir::Mir<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
let mut ecx = mk_borrowck_eval_cx(tcx, cid.instance, mir, DUMMY_SP).unwrap();
let span = tcx.def_span(cid.instance.def_id());
let mut ecx = mk_eval_cx(tcx, span, param_env);
eval_body_using_ecx(&mut ecx, cid, Some(mir), param_env)
}
@ -530,13 +478,12 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx>
pub fn const_field<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
instance: ty::Instance<'tcx>,
variant: Option<VariantIdx>,
field: mir::Field,
value: ty::Const<'tcx>,
) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> {
trace!("const_field: {:?}, {:?}, {:?}", instance, field, value);
let ecx = mk_eval_cx(tcx, instance, param_env).unwrap();
trace!("const_field: {:?}, {:?}", field, value);
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env);
let result = (|| {
// get the operand again
let op = lazy_const_to_op(&ecx, ty::LazyConst::Evaluated(value), value.ty)?;
@ -561,11 +508,10 @@ pub fn const_field<'a, 'tcx>(
pub fn const_variant_index<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
instance: ty::Instance<'tcx>,
val: ty::Const<'tcx>,
) -> EvalResult<'tcx, VariantIdx> {
trace!("const_variant_index: {:?}, {:?}", instance, val);
let ecx = mk_eval_cx(tcx, instance, param_env).unwrap();
trace!("const_variant_index: {:?}", val);
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env);
let op = lazy_const_to_op(&ecx, ty::LazyConst::Evaluated(val), val.ty)?;
Ok(ecx.read_discriminant(op)?.1)
}
@ -585,7 +531,7 @@ fn validate_and_turn_into_const<'a, 'tcx>(
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> {
let cid = key.value;
let ecx = mk_eval_cx(tcx, cid.instance, key.param_env).unwrap();
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

View File

@ -427,13 +427,24 @@ pub enum Constructor<'tcx> {
}
impl<'tcx> Constructor<'tcx> {
fn variant_index_for_adt(&self, adt: &'tcx ty::AdtDef) -> VariantIdx {
fn variant_index_for_adt<'a>(
&self,
cx: &MatchCheckCtxt<'a, 'tcx>,
adt: &'tcx ty::AdtDef,
) -> VariantIdx {
match self {
&Variant(vid) => adt.variant_index_with_id(vid),
&Single => {
assert!(!adt.is_enum());
VariantIdx::new(0)
}
&ConstantValue(c) => {
::const_eval::const_variant_index(
cx.tcx,
cx.param_env,
c,
).unwrap()
},
_ => bug!("bad constructor {:?} for adt {:?}", self, adt)
}
}
@ -567,7 +578,7 @@ impl<'tcx> Witness<'tcx> {
PatternKind::Variant {
adt_def: adt,
substs,
variant_index: ctor.variant_index_for_adt(adt),
variant_index: ctor.variant_index_for_adt(cx, adt),
subpatterns: pats
}
} else {
@ -1329,7 +1340,7 @@ fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt<'_, 'tcx>,
///
/// For instance, a tuple pattern (_, 42, Some([])) has the arity of 3.
/// A struct pattern's arity is the number of fields it contains, etc.
fn constructor_arity(_cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> u64 {
fn constructor_arity(cx: &MatchCheckCtxt<'a, 'tcx>, ctor: &Constructor<'tcx>, ty: Ty<'tcx>) -> u64 {
debug!("constructor_arity({:#?}, {:?})", ctor, ty);
match ty.sty {
ty::Tuple(ref fs) => fs.len() as u64,
@ -1340,7 +1351,7 @@ fn constructor_arity(_cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> u64 {
},
ty::Ref(..) => 1,
ty::Adt(adt, _) => {
adt.variants[ctor.variant_index_for_adt(adt)].fields.len() as u64
adt.variants[ctor.variant_index_for_adt(cx, adt)].fields.len() as u64
}
_ => 0
}
@ -1351,7 +1362,7 @@ fn constructor_arity(_cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> u64 {
///
/// For instance, a tuple pattern (43u32, 'a') has sub pattern types [u32, char].
fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>,
ctor: &Constructor,
ctor: &Constructor<'tcx>,
ty: Ty<'tcx>) -> Vec<Ty<'tcx>>
{
debug!("constructor_sub_pattern_tys({:#?}, {:?})", ctor, ty);
@ -1368,7 +1379,7 @@ fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>,
// Use T as the sub pattern type of Box<T>.
vec![substs.type_at(0)]
} else {
adt.variants[ctor.variant_index_for_adt(adt)].fields.iter().map(|field| {
adt.variants[ctor.variant_index_for_adt(cx, adt)].fields.iter().map(|field| {
let is_visible = adt.is_enum()
|| field.vis.is_accessible_from(cx.module, cx.tcx);
if is_visible {

View File

@ -885,7 +885,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
let adt_subpattern = |i, variant_opt| {
let field = Field::new(i);
let val = const_field(
self.tcx, self.param_env, instance,
self.tcx, self.param_env,
variant_opt, field, cv,
).expect("field access failed");
self.const_to_pat(instance, val, id, span)
@ -928,7 +928,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
},
ty::Adt(adt_def, substs) if adt_def.is_enum() => {
let variant_index = const_variant_index(
self.tcx, self.param_env, instance, cv
self.tcx, self.param_env, cv
).expect("const_variant_index failed");
let subpatterns = adt_subpatterns(
adt_def.variants[variant_index].fields.len(),

View File

@ -109,11 +109,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
// The src operand does not matter, just its type
match src.layout.ty.sty {
ty::Closure(def_id, substs) => {
let substs = self.tcx.subst_and_normalize_erasing_regions(
self.substs(),
ty::ParamEnv::reveal_all(),
&substs,
);
let substs = self.subst_and_normalize_erasing_regions(substs)?;
let instance = ty::Instance::resolve_closure(
*self.tcx,
def_id,

View File

@ -216,11 +216,21 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
self.frame().mir
}
pub fn substs(&self) -> &'tcx Substs<'tcx> {
if let Some(frame) = self.stack.last() {
frame.instance.substs
} else {
Substs::empty()
pub(super) fn subst_and_normalize_erasing_regions<T: TypeFoldable<'tcx>>(
&self,
substs: T,
) -> EvalResult<'tcx, T> {
match self.stack.last() {
Some(frame) => Ok(self.tcx.subst_and_normalize_erasing_regions(
frame.instance.substs,
self.param_env,
&substs,
)),
None => if substs.needs_subst() {
err!(TooGeneric).into()
} else {
Ok(substs)
},
}
}
@ -230,13 +240,9 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
substs: &'tcx Substs<'tcx>
) -> EvalResult<'tcx, ty::Instance<'tcx>> {
trace!("resolve: {:?}, {:#?}", def_id, substs);
trace!("substs: {:#?}", self.substs());
trace!("param_env: {:#?}", self.param_env);
let substs = self.tcx.subst_and_normalize_erasing_regions(
self.substs(),
self.param_env,
&substs,
);
let substs = self.subst_and_normalize_erasing_regions(substs)?;
trace!("substs: {:#?}", substs);
ty::Instance::resolve(
*self.tcx,
self.param_env,
@ -276,7 +282,21 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
}
}
pub fn monomorphize<T: TypeFoldable<'tcx> + Subst<'tcx>>(
pub(super) fn monomorphize<T: TypeFoldable<'tcx> + Subst<'tcx>>(
&self,
t: T,
) -> EvalResult<'tcx, T> {
match self.stack.last() {
Some(frame) => Ok(self.monomorphize_with_substs(t, frame.instance.substs)),
None => if t.needs_subst() {
err!(TooGeneric).into()
} else {
Ok(t)
},
}
}
fn monomorphize_with_substs<T: TypeFoldable<'tcx> + Subst<'tcx>>(
&self,
t: T,
substs: &'tcx Substs<'tcx>
@ -295,7 +315,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
let cell = &frame.local_layouts[local];
if cell.get().is_none() {
let local_ty = frame.mir.local_decls[local].ty;
let local_ty = self.monomorphize(local_ty, frame.instance.substs);
let local_ty = self.monomorphize_with_substs(local_ty, frame.instance.substs);
let layout = self.layout_of(local_ty)?;
cell.set(Some(layout));
}

View File

@ -508,7 +508,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
Constant(ref constant) => {
let layout = from_known_layout(layout, || {
let ty = self.monomorphize(mir_op.ty(self.mir(), *self.tcx), self.substs());
let ty = self.monomorphize(mir_op.ty(self.mir(), *self.tcx))?;
self.layout_of(ty)
})?;
let op = self.const_value_to_op(*constant.literal)?;

View File

@ -9,6 +9,7 @@ use rustc::hir;
use rustc::mir;
use rustc::ty::{self, Ty};
use rustc::ty::layout::{self, Size, Align, LayoutOf, TyLayout, HasDataLayout, VariantIdx};
use rustc::ty::TypeFoldable;
use super::{
GlobalId, AllocId, Allocation, Scalar, EvalResult, Pointer, PointerArithmetic,
@ -583,8 +584,8 @@ where
}
Static(ref static_) => {
let ty = self.monomorphize(static_.ty, self.substs());
let layout = self.layout_of(ty)?;
assert!(!static_.ty.needs_subst());
let layout = self.layout_of(static_.ty)?;
let instance = ty::Instance::mono(*self.tcx, static_.def_id);
let cid = GlobalId {
instance,

View File

@ -248,7 +248,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
}
NullaryOp(mir::NullOp::SizeOf, ty) => {
let ty = self.monomorphize(ty, self.substs());
let ty = self.monomorphize(ty)?;
let layout = self.layout_of(ty)?;
assert!(!layout.is_unsized(),
"SizeOf nullary MIR operator called for unsized type");
@ -260,7 +260,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
}
Cast(kind, ref operand, cast_ty) => {
debug_assert_eq!(self.monomorphize(cast_ty, self.substs()), dest.layout.ty);
debug_assert_eq!(self.monomorphize(cast_ty)?, dest.layout.ty);
let src = self.eval_operand(operand, None)?;
self.cast(src, kind, dest)?;
}

View File

@ -20,7 +20,7 @@ use rustc::ty::layout::{
use interpret::{self, EvalContext, ScalarMaybeUndef, Immediate, OpTy, MemoryKind};
use const_eval::{
CompileTimeInterpreter, error_to_const_error, eval_promoted, mk_borrowck_eval_cx,
CompileTimeInterpreter, error_to_const_error, eval_promoted, mk_eval_cx,
lazy_const_to_op,
};
use transform::{MirPass, MirSource};
@ -110,9 +110,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
source: MirSource,
) -> ConstPropagator<'a, 'mir, 'tcx> {
let param_env = tcx.param_env(source.def_id);
let substs = Substs::identity_for_item(tcx, source.def_id);
let instance = Instance::new(source.def_id, substs);
let ecx = mk_borrowck_eval_cx(tcx, instance, mir, DUMMY_SP).unwrap();
let ecx = mk_eval_cx(tcx, tcx.def_span(source.def_id), param_env);
ConstPropagator {
ecx,
mir,

View File

@ -431,8 +431,12 @@ fn macro_resolve(cx: &DocContext, path_str: &str) -> Option<Def> {
let parent_scope = resolver.dummy_parent_scope();
if let Ok(def) = resolver.resolve_macro_to_def_inner(&path, MacroKind::Bang,
&parent_scope, false, false) {
if let SyntaxExtension::DeclMacro { .. } = *resolver.get_macro(def) {
return Some(def);
if let Def::Macro(_, MacroKind::ProcMacroStub) = def {
// skip proc-macro stubs, they'll cause `get_macro` to crash
} else {
if let SyntaxExtension::DeclMacro { .. } = *resolver.get_macro(def) {
return Some(def);
}
}
}
if let Some(def) = resolver.all_macros.get(&Symbol::intern(path_str)) {

View File

@ -11,7 +11,7 @@ use core::ops::{Drop, Generator, GeneratorState};
#[doc(inline)]
pub use core::future::*;
/// Wrap a future in a generator.
/// Wrap a generator in a future.
///
/// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give
/// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`).

View File

@ -56,4 +56,4 @@ pub mod mem {
pub use sys::abi::mem::*;
}
pub use sys::ext::{io, arch};
pub use sys::ext::{io, arch, ffi};

View File

@ -0,0 +1,109 @@
//! SGX-specific extension to the primitives in the `std::ffi` module
#![unstable(feature = "sgx_platform", issue = "56975")]
use ffi::{OsStr, OsString};
use mem;
use sys::os_str::Buf;
use sys_common::{FromInner, IntoInner, AsInner};
/// SGX-specific extensions to [`OsString`].
///
/// [`OsString`]: ../../../../std/ffi/struct.OsString.html
#[unstable(feature = "sgx_platform", issue = "56975")]
pub trait OsStringExt {
/// Creates an [`OsString`] from a byte vector.
///
/// # Examples
///
/// ```
/// use std::ffi::OsString;
/// use std::os::unix::ffi::OsStringExt;
///
/// let bytes = b"foo".to_vec();
/// let os_string = OsString::from_vec(bytes);
/// assert_eq!(os_string.to_str(), Some("foo"));
/// ```
///
/// [`OsString`]: ../../../ffi/struct.OsString.html
#[unstable(feature = "sgx_platform", issue = "56975")]
fn from_vec(vec: Vec<u8>) -> Self;
/// Yields the underlying byte vector of this [`OsString`].
///
/// # Examples
///
/// ```
/// use std::ffi::OsString;
/// use std::os::unix::ffi::OsStringExt;
///
/// let mut os_string = OsString::new();
/// os_string.push("foo");
/// let bytes = os_string.into_vec();
/// assert_eq!(bytes, b"foo");
/// ```
///
/// [`OsString`]: ../../../ffi/struct.OsString.html
#[unstable(feature = "sgx_platform", issue = "56975")]
fn into_vec(self) -> Vec<u8>;
}
#[unstable(feature = "sgx_platform", issue = "56975")]
impl OsStringExt for OsString {
fn from_vec(vec: Vec<u8>) -> OsString {
FromInner::from_inner(Buf { inner: vec })
}
fn into_vec(self) -> Vec<u8> {
self.into_inner().inner
}
}
/// SGX-specific extensions to [`OsStr`].
///
/// [`OsStr`]: ../../../../std/ffi/struct.OsStr.html
#[unstable(feature = "sgx_platform", issue = "56975")]
pub trait OsStrExt {
#[unstable(feature = "sgx_platform", issue = "56975")]
/// Creates an [`OsStr`] from a byte slice.
///
/// # Examples
///
/// ```
/// use std::ffi::OsStr;
/// use std::os::unix::ffi::OsStrExt;
///
/// let bytes = b"foo";
/// let os_str = OsStr::from_bytes(bytes);
/// assert_eq!(os_str.to_str(), Some("foo"));
/// ```
///
/// [`OsStr`]: ../../../ffi/struct.OsStr.html
fn from_bytes(slice: &[u8]) -> &Self;
/// Gets the underlying byte view of the [`OsStr`] slice.
///
/// # Examples
///
/// ```
/// use std::ffi::OsStr;
/// use std::os::unix::ffi::OsStrExt;
///
/// let mut os_str = OsStr::new("foo");
/// let bytes = os_str.as_bytes();
/// assert_eq!(bytes, b"foo");
/// ```
///
/// [`OsStr`]: ../../../ffi/struct.OsStr.html
#[unstable(feature = "sgx_platform", issue = "56975")]
fn as_bytes(&self) -> &[u8];
}
#[unstable(feature = "sgx_platform", issue = "56975")]
impl OsStrExt for OsStr {
fn from_bytes(slice: &[u8]) -> &OsStr {
unsafe { mem::transmute(slice) }
}
fn as_bytes(&self) -> &[u8] {
&self.as_inner().inner
}
}

View File

@ -2,3 +2,4 @@
pub mod arch;
pub mod io;
pub mod ffi;

View File

@ -1,3 +1,4 @@
use alloc::{self, Layout};
use num::NonZeroUsize;
use slice;
use str;
@ -147,6 +148,7 @@ impl RWLock {
self.__write_unlock(rguard, wguard);
}
// only used by __rust_rwlock_unlock below
#[inline]
unsafe fn unlock(&self) {
let rguard = self.readers.lock();
@ -164,6 +166,7 @@ impl RWLock {
const EINVAL: i32 = 22;
// used by libunwind port
#[no_mangle]
pub unsafe extern "C" fn __rust_rwlock_rdlock(p: *mut RWLock) -> i32 {
if p.is_null() {
@ -190,6 +193,8 @@ pub unsafe extern "C" fn __rust_rwlock_unlock(p: *mut RWLock) -> i32 {
return 0;
}
// the following functions are also used by the libunwind port. They're
// included here to make sure parallel codegen and LTO don't mess things up.
#[no_mangle]
pub unsafe extern "C" fn __rust_print_err(m: *mut u8, s: i32) {
if s < 0 {
@ -206,6 +211,16 @@ pub unsafe extern "C" fn __rust_abort() {
::sys::abort_internal();
}
#[no_mangle]
pub unsafe extern "C" fn __rust_c_alloc(size: usize, align: usize) -> *mut u8 {
alloc::alloc(Layout::from_size_align_unchecked(size, align))
}
#[no_mangle]
pub unsafe extern "C" fn __rust_c_dealloc(ptr: *mut u8, size: usize, align: usize) {
alloc::dealloc(ptr, Layout::from_size_align_unchecked(size, align))
}
#[cfg(test)]
mod tests {

View File

@ -1,10 +1,7 @@
use cmp::Ordering;
use fmt;
use mem;
use sync::Once;
use sys::c;
use sys::cvt;
use sys_common::mul_div_u64;
use time::Duration;
use convert::TryInto;
use core::hash::{Hash, Hasher};
@ -14,7 +11,9 @@ const INTERVALS_PER_SEC: u64 = NANOS_PER_SEC / 100;
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub struct Instant {
t: c::LARGE_INTEGER,
// This duration is relative to an arbitrary microsecond epoch
// from the winapi QueryPerformanceCounter function.
t: Duration,
}
#[derive(Copy, Clone)]
@ -33,11 +32,12 @@ pub const UNIX_EPOCH: SystemTime = SystemTime {
impl Instant {
pub fn now() -> Instant {
let mut t = Instant { t: 0 };
cvt(unsafe {
c::QueryPerformanceCounter(&mut t.t)
}).unwrap();
t
// High precision timing on windows operates in "Performance Counter"
// units, as returned by the WINAPI QueryPerformanceCounter function.
// These relate to seconds by a factor of QueryPerformanceFrequency.
// In order to keep unit conversions out of normal interval math, we
// measure in QPC units and immediately convert to nanoseconds.
perf_counter::PerformanceCounterInstant::now().into()
}
pub fn actually_monotonic() -> bool {
@ -45,47 +45,31 @@ impl Instant {
}
pub const fn zero() -> Instant {
Instant { t: 0 }
Instant { t: Duration::from_secs(0) }
}
pub fn sub_instant(&self, other: &Instant) -> Duration {
// Values which are +- 1 need to be considered as basically the same
// units in time due to various measurement oddities, according to
// Windows [1]
//
// [1]:
// https://msdn.microsoft.com/en-us/library/windows/desktop
// /dn553408%28v=vs.85%29.aspx#guidance
if other.t > self.t && other.t - self.t == 1 {
// On windows there's a threshold below which we consider two timestamps
// equivalent due to measurement error. For more details + doc link,
// check the docs on epsilon.
let epsilon =
perf_counter::PerformanceCounterInstant::epsilon();
if other.t > self.t && other.t - self.t <= epsilon {
return Duration::new(0, 0)
}
let diff = (self.t as u64).checked_sub(other.t as u64)
.expect("specified instant was later than \
self");
let nanos = mul_div_u64(diff, NANOS_PER_SEC, frequency() as u64);
Duration::new(nanos / NANOS_PER_SEC, (nanos % NANOS_PER_SEC) as u32)
self.t.checked_sub(other.t)
.expect("specified instant was later than self")
}
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
let freq = frequency() as u64;
let t = other.as_secs()
.checked_mul(freq)?
.checked_add(mul_div_u64(other.subsec_nanos() as u64, freq, NANOS_PER_SEC))?
.checked_add(self.t as u64)?;
Some(Instant {
t: t as c::LARGE_INTEGER,
t: self.t.checked_add(*other)?
})
}
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
let freq = frequency() as u64;
let t = other.as_secs().checked_mul(freq).and_then(|i| {
(self.t as u64).checked_sub(i)
}).and_then(|i| {
i.checked_sub(mul_div_u64(other.subsec_nanos() as u64, freq, NANOS_PER_SEC))
})?;
Some(Instant {
t: t as c::LARGE_INTEGER,
t: self.t.checked_sub(*other)?
})
}
}
@ -186,14 +170,60 @@ fn intervals2dur(intervals: u64) -> Duration {
((intervals % INTERVALS_PER_SEC) * 100) as u32)
}
fn frequency() -> c::LARGE_INTEGER {
static mut FREQUENCY: c::LARGE_INTEGER = 0;
static ONCE: Once = Once::new();
mod perf_counter {
use super::{NANOS_PER_SEC};
use sync::Once;
use sys_common::mul_div_u64;
use sys::c;
use sys::cvt;
use time::Duration;
unsafe {
ONCE.call_once(|| {
cvt(c::QueryPerformanceFrequency(&mut FREQUENCY)).unwrap();
});
FREQUENCY
pub struct PerformanceCounterInstant {
ts: c::LARGE_INTEGER
}
impl PerformanceCounterInstant {
pub fn now() -> Self {
Self {
ts: query()
}
}
// Per microsoft docs, the margin of error for cross-thread time comparisons
// using QueryPerformanceCounter is 1 "tick" -- defined as 1/frequency().
// Reference: https://docs.microsoft.com/en-us/windows/desktop/SysInfo
// /acquiring-high-resolution-time-stamps
pub fn epsilon() -> Duration {
let epsilon = NANOS_PER_SEC / (frequency() as u64);
Duration::from_nanos(epsilon)
}
}
impl From<PerformanceCounterInstant> for super::Instant {
fn from(other: PerformanceCounterInstant) -> Self {
let freq = frequency() as u64;
let instant_nsec = mul_div_u64(other.ts as u64, NANOS_PER_SEC, freq);
Self {
t: Duration::from_nanos(instant_nsec)
}
}
}
fn frequency() -> c::LARGE_INTEGER {
static mut FREQUENCY: c::LARGE_INTEGER = 0;
static ONCE: Once = Once::new();
unsafe {
ONCE.call_once(|| {
cvt(c::QueryPerformanceFrequency(&mut FREQUENCY)).unwrap();
});
FREQUENCY
}
}
fn query() -> c::LARGE_INTEGER {
let mut qpc_value: c::LARGE_INTEGER = 0;
cvt(unsafe {
c::QueryPerformanceCounter(&mut qpc_value)
}).unwrap();
qpc_value
}
}

View File

@ -610,6 +610,15 @@ mod tests {
assert_eq!(a + year, a.checked_add(year).unwrap());
}
#[test]
fn instant_math_is_associative() {
let now = Instant::now();
let offset = Duration::from_millis(5);
// Changing the order of instant math shouldn't change the results,
// especially when the expression reduces to X + identity.
assert_eq!((now + offset) - now, (now - now) + offset);
}
#[test]
#[should_panic]
fn instant_duration_panic() {

View File

@ -2319,8 +2319,24 @@ impl<'a> Parser<'a> {
let lo = self.span;
// Check if a colon exists one ahead. This means we're parsing a fieldname.
let (fieldname, expr, is_shorthand) = if self.look_ahead(1, |t| t == &token::Colon) {
let (fieldname, expr, is_shorthand) = if self.look_ahead(1, |t| {
t == &token::Colon || t == &token::Eq
}) {
let fieldname = self.parse_field_name()?;
// Check for an equals token. This means the source incorrectly attempts to
// initialize a field with an eq rather than a colon.
if self.token == token::Eq {
self.diagnostic()
.struct_span_err(self.span, "expected `:`, found `=`")
.span_suggestion_with_applicability(
fieldname.span.shrink_to_hi().to(self.span),
"replace equals symbol with a colon",
":".to_string(),
Applicability::MachineApplicable,
)
.emit();
}
self.bump(); // `:`
(fieldname, self.parse_expr()?, false)
} else {

View File

@ -4,6 +4,11 @@
#![crate_type="proc-macro"]
#![crate_name="some_macros"]
// @has some_macros/index.html
// @has - '//a/[@href="attr.some_proc_attr.html"]' 'some_proc_attr'
//! include a link to [some_proc_attr] to make sure it works.
extern crate proc_macro;
use proc_macro::TokenStream;

View File

@ -0,0 +1,10 @@
// https://github.com/rust-lang/rust/issues/53708
struct S;
fn main() {
const C: &S = &S;
match C { //~ ERROR non-exhaustive
C => {} // this is a common bug around constants and references in patterns
}
}

View File

@ -0,0 +1,9 @@
error[E0004]: non-exhaustive patterns: `&S` not covered
--> $DIR/match_ice.rs:7:11
|
LL | match C { //~ ERROR non-exhaustive
| ^ pattern `&S` not covered
error: aborting due to previous error
For more information about this error, try `rustc --explain E0004`.

View File

@ -0,0 +1,37 @@
// run-rustfix
#![allow(warnings)]
// This test checks that the following error is emitted when a `=` character is used to initialize
// a struct field when a `:` is expected.
//
// ```
// error: struct fields are initialized with a colon
// --> $DIR/issue-57684.rs:12:20
// |
// LL | let _ = X { f1 = 5 };
// | ^ help: replace equals symbol with a colon: `:`
// ```
struct X {
f1: i32,
}
struct Y {
f1: i32,
f2: i32,
f3: i32,
}
fn main() {
let _ = X { f1: 5 };
//~^ ERROR expected `:`, found `=`
let f3 = 3;
let _ = Y {
f1: 5,
//~^ ERROR expected `:`, found `=`
f2: 4,
f3,
};
}

View File

@ -0,0 +1,37 @@
// run-rustfix
#![allow(warnings)]
// This test checks that the following error is emitted when a `=` character is used to initialize
// a struct field when a `:` is expected.
//
// ```
// error: struct fields are initialized with a colon
// --> $DIR/issue-57684.rs:12:20
// |
// LL | let _ = X { f1 = 5 };
// | ^ help: replace equals symbol with a colon: `:`
// ```
struct X {
f1: i32,
}
struct Y {
f1: i32,
f2: i32,
f3: i32,
}
fn main() {
let _ = X { f1 = 5 };
//~^ ERROR expected `:`, found `=`
let f3 = 3;
let _ = Y {
f1 = 5,
//~^ ERROR expected `:`, found `=`
f2: 4,
f3,
};
}

View File

@ -0,0 +1,18 @@
error: expected `:`, found `=`
--> $DIR/issue-57684.rs:27:20
|
LL | let _ = X { f1 = 5 };
| -^
| |
| help: replace equals symbol with a colon: `:`
error: expected `:`, found `=`
--> $DIR/issue-57684.rs:32:12
|
LL | f1 = 5,
| -^
| |
| help: replace equals symbol with a colon: `:`
error: aborting due to 2 previous errors