about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-01-24 21:23:11 +0000
committerbors <bors@rust-lang.org>2019-01-24 21:23:11 +0000
commit278067d34d1535a840cf9c99bcb8b538bf5b109a (patch)
tree7d3bd558b1a01bef4485dba03117107a7e132635
parent01f8e25b15f4ab157c8e7c9c56054df7595ec0e1 (diff)
parent5fa1016f93d77e43c3ed69b1155308616095cfcb (diff)
downloadrust-278067d34d1535a840cf9c99bcb8b538bf5b109a.tar.gz
rust-278067d34d1535a840cf9c99bcb8b538bf5b109a.zip
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
-rw-r--r--src/ci/docker/dist-various-2/Dockerfile2
-rw-r--r--src/libcore/num/mod.rs24
-rw-r--r--src/librustc_codegen_ssa/back/linker.rs3
-rw-r--r--src/librustc_codegen_ssa/mir/constant.rs1
-rw-r--r--src/librustc_mir/const_eval.rs80
-rw-r--r--src/librustc_mir/hair/pattern/_match.rs23
-rw-r--r--src/librustc_mir/hair/pattern/mod.rs4
-rw-r--r--src/librustc_mir/interpret/cast.rs6
-rw-r--r--src/librustc_mir/interpret/eval_context.rs46
-rw-r--r--src/librustc_mir/interpret/operand.rs2
-rw-r--r--src/librustc_mir/interpret/place.rs5
-rw-r--r--src/librustc_mir/interpret/step.rs4
-rw-r--r--src/librustc_mir/transform/const_prop.rs6
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs8
-rw-r--r--src/libstd/future.rs2
-rw-r--r--src/libstd/os/fortanix_sgx/mod.rs2
-rw-r--r--src/libstd/sys/sgx/ext/ffi.rs109
-rw-r--r--src/libstd/sys/sgx/ext/mod.rs1
-rw-r--r--src/libstd/sys/sgx/rwlock.rs15
-rw-r--r--src/libstd/sys/windows/time.rs118
-rw-r--r--src/libstd/time.rs9
-rw-r--r--src/libsyntax/parse/parser.rs18
-rw-r--r--src/test/rustdoc/proc-macro.rs5
-rw-r--r--src/test/ui/consts/match_ice.rs10
-rw-r--r--src/test/ui/consts/match_ice.stderr9
-rw-r--r--src/test/ui/issues/issue-57684.fixed37
-rw-r--r--src/test/ui/issues/issue-57684.rs37
-rw-r--r--src/test/ui/issues/issue-57684.stderr18
28 files changed, 432 insertions, 172 deletions
diff --git a/src/ci/docker/dist-various-2/Dockerfile b/src/ci/docker/dist-various-2/Dockerfile
index 906255533ad..952c1ba2ccb 100644
--- a/src/ci/docker/dist-various-2/Dockerfile
+++ b/src/ci/docker/dist-various-2/Dockerfile
@@ -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
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 41caa1788fb..423b800d585 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -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;
diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs
index 06d4f940436..ad61f8f01d8 100644
--- a/src/librustc_codegen_ssa/back/linker.rs
+++ b/src/librustc_codegen_ssa/back/linker.rs
@@ -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");
diff --git a/src/librustc_codegen_ssa/mir/constant.rs b/src/librustc_codegen_ssa/mir/constant.rs
index e6d6ef1d7a3..56d4342e6e1 100644
--- a/src/librustc_codegen_ssa/mir/constant.rs
+++ b/src/librustc_codegen_ssa/mir/constant.rs
@@ -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,
diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs
index 105856fecc7..45c6c1b4249 100644
--- a/src/librustc_mir/const_eval.rs
+++ b/src/librustc_mir/const_eval.rs
@@ -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
diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs
index 188a1120442..9cc5c93de41 100644
--- a/src/librustc_mir/hair/pattern/_match.rs
+++ b/src/librustc_mir/hair/pattern/_match.rs
@@ -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 {
diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs
index 8991a90737c..cdaffe5d456 100644
--- a/src/librustc_mir/hair/pattern/mod.rs
+++ b/src/librustc_mir/hair/pattern/mod.rs
@@ -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(),
diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs
index 190a381cf52..c3b71be8354 100644
--- a/src/librustc_mir/interpret/cast.rs
+++ b/src/librustc_mir/interpret/cast.rs
@@ -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,
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index b2d3328a73f..132b753eb9a 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -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));
         }
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index b2648480f20..8741571342f 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -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)?;
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index 962e0b7a742..f3a948a6ca3 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -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,
diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs
index 2de8b3c1afd..25f3e4c1f77 100644
--- a/src/librustc_mir/interpret/step.rs
+++ b/src/librustc_mir/interpret/step.rs
@@ -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)?;
             }
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index 03d6d3868c9..dc556a15cd8 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -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,
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 3d6096b07ce..13ad05101e4 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -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)) {
diff --git a/src/libstd/future.rs b/src/libstd/future.rs
index a7b9895177f..22900c3067b 100644
--- a/src/libstd/future.rs
+++ b/src/libstd/future.rs
@@ -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.....]>`).
diff --git a/src/libstd/os/fortanix_sgx/mod.rs b/src/libstd/os/fortanix_sgx/mod.rs
index 47c7b5dcbe6..810965fc1b8 100644
--- a/src/libstd/os/fortanix_sgx/mod.rs
+++ b/src/libstd/os/fortanix_sgx/mod.rs
@@ -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};
diff --git a/src/libstd/sys/sgx/ext/ffi.rs b/src/libstd/sys/sgx/ext/ffi.rs
new file mode 100644
index 00000000000..7b0ffea49ae
--- /dev/null
+++ b/src/libstd/sys/sgx/ext/ffi.rs
@@ -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
+    }
+}
diff --git a/src/libstd/sys/sgx/ext/mod.rs b/src/libstd/sys/sgx/ext/mod.rs
index 5489f6f5694..51b2659da83 100644
--- a/src/libstd/sys/sgx/ext/mod.rs
+++ b/src/libstd/sys/sgx/ext/mod.rs
@@ -2,3 +2,4 @@
 
 pub mod arch;
 pub mod io;
+pub mod ffi;
diff --git a/src/libstd/sys/sgx/rwlock.rs b/src/libstd/sys/sgx/rwlock.rs
index 47874158ed9..43ceae7d33b 100644
--- a/src/libstd/sys/sgx/rwlock.rs
+++ b/src/libstd/sys/sgx/rwlock.rs
@@ -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 {
 
diff --git a/src/libstd/sys/windows/time.rs b/src/libstd/sys/windows/time.rs
index 8e8e9195cf4..8a8159af2f1 100644
--- a/src/libstd/sys/windows/time.rs
+++ b/src/libstd/sys/windows/time.rs
@@ -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;
+
+    pub struct PerformanceCounterInstant {
+        ts: c::LARGE_INTEGER
+    }
+    impl PerformanceCounterInstant {
+        pub fn now() -> Self {
+            Self {
+                ts: query()
+            }
+        }
 
-    unsafe {
-        ONCE.call_once(|| {
-            cvt(c::QueryPerformanceFrequency(&mut FREQUENCY)).unwrap();
-        });
-        FREQUENCY
+        // 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
     }
 }
diff --git a/src/libstd/time.rs b/src/libstd/time.rs
index 507ea395c6c..23924559fcc 100644
--- a/src/libstd/time.rs
+++ b/src/libstd/time.rs
@@ -611,6 +611,15 @@ mod tests {
     }
 
     #[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() {
         let a = Instant::now();
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index e4950d1b5a1..fb832afb748 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -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 {
diff --git a/src/test/rustdoc/proc-macro.rs b/src/test/rustdoc/proc-macro.rs
index d4d70d04f5b..1e396f1be0e 100644
--- a/src/test/rustdoc/proc-macro.rs
+++ b/src/test/rustdoc/proc-macro.rs
@@ -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;
diff --git a/src/test/ui/consts/match_ice.rs b/src/test/ui/consts/match_ice.rs
new file mode 100644
index 00000000000..53c5782a4c7
--- /dev/null
+++ b/src/test/ui/consts/match_ice.rs
@@ -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
+    }
+}
diff --git a/src/test/ui/consts/match_ice.stderr b/src/test/ui/consts/match_ice.stderr
new file mode 100644
index 00000000000..e6e04e2c462
--- /dev/null
+++ b/src/test/ui/consts/match_ice.stderr
@@ -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`.
diff --git a/src/test/ui/issues/issue-57684.fixed b/src/test/ui/issues/issue-57684.fixed
new file mode 100644
index 00000000000..4a432206d51
--- /dev/null
+++ b/src/test/ui/issues/issue-57684.fixed
@@ -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,
+    };
+}
diff --git a/src/test/ui/issues/issue-57684.rs b/src/test/ui/issues/issue-57684.rs
new file mode 100644
index 00000000000..7a62785e32f
--- /dev/null
+++ b/src/test/ui/issues/issue-57684.rs
@@ -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,
+    };
+}
diff --git a/src/test/ui/issues/issue-57684.stderr b/src/test/ui/issues/issue-57684.stderr
new file mode 100644
index 00000000000..514bbffde6b
--- /dev/null
+++ b/src/test/ui/issues/issue-57684.stderr
@@ -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
+