Rollup merge of #64503 - RalfJung:miri-retag, r=oli-obk
rename Allocation::retag -> with_tags_and_extra
This is more consistent with `Pointer::with_tag`. Also, "retag" is a [term from Stacked Borrows](https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md#retagging) with a [corresponding Machine hook](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/interpret/machine/trait.Machine.html#method.retag), and this function has nothing to do with that other use of the term.
r? @oli-obk
diff --git a/Cargo.lock b/Cargo.lock
index b717460..326f3b1 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -201,9 +201,7 @@
name = "build-manifest"
version = "0.1.0"
dependencies = [
- "reqwest",
"serde",
- "serde_json",
"toml",
]
diff --git a/RELEASES.md b/RELEASES.md
index f26f6e6..d634feb 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,108 @@
+Version 1.38.0 (2019-09-26)
+==========================
+
+Language
+--------
+- [The `#[global_allocator]` attribute can now be used in submodules.][62735]
+- [The `#[deprecated]` attribute can now be used on macros.][62042]
+
+Compiler
+--------
+- [Added pipelined compilation support to `rustc`.][62766] This will
+ improve compilation times in some cases. For further information please refer
+ to the [_"Evaluating pipelined rustc compilation"_][pipeline-internals] thread.
+- [Added tier 3\* support for the `aarch64-uwp-windows-msvc`, `i686-uwp-windows-gnu`,
+ `i686-uwp-windows-msvc`, `x86_64-uwp-windows-gnu`, and
+ `x86_64-uwp-windows-msvc` targets.][60260]
+- [Added tier 3 support for the `armv7-unknown-linux-gnueabi` and
+ `armv7-unknown-linux-musleabi` targets.][63107]
+- [Added tier 3 support for the `hexagon-unknown-linux-musl` target.][62814]
+- [Added tier 3 support for the `riscv32i-unknown-none-elf` target.][62784]
+
+\* Refer to Rust's [platform support page][forge-platform-support] for more
+information on Rust's tiered platform support.
+
+Libraries
+---------
+- [`ascii::EscapeDefault` now implements `Clone` and `Display`.][63421]
+- [Derive macros for prelude traits (e.g. `Clone`, `Debug`, `Hash`) are now
+ available at the same path as the trait.][63056] (e.g. The `Clone` derive macro
+ is available at `std::clone::Clone`). This also makes all built-in macros
+ available in `std`/`core` root. e.g. `std::include_bytes!`.
+- [`str::Chars` now implements `Debug`.][63000]
+- [`slice::{concat, connect, join}` now accepts `&[T]` in addition to `&T`.][62528]
+- [`*const T` and `*mut T` now implement `marker::Unpin`.][62583]
+- [`Arc<[T]>` and `Rc<[T]>` now implement `FromIterator<T>`.][61953]
+- [Added euclidean remainder and division operations (`div_euclid`,
+ `rem_euclid`) to all numeric primitives.][61884] Additionally `checked`,
+ `overflowing`, and `wrapping` versions are available for all
+ integer primitives.
+- [`thread::AccessError` now implements `Clone`, `Copy`, `Eq`, `Error`, and
+ `PartialEq`.][61491]
+- [`iter::{StepBy, Peekable, Take}` now implement `DoubleEndedIterator`.][61457]
+
+Stabilized APIs
+---------------
+- [`<*const T>::cast`]
+- [`<*mut T>::cast`]
+- [`Duration::as_secs_f32`]
+- [`Duration::as_secs_f64`]
+- [`Duration::div_duration_f32`]
+- [`Duration::div_duration_f64`]
+- [`Duration::div_f32`]
+- [`Duration::div_f64`]
+- [`Duration::from_secs_f32`]
+- [`Duration::from_secs_f64`]
+- [`Duration::mul_f32`]
+- [`Duration::mul_f64`]
+- [`any::type_name`]
+
+Cargo
+-----
+- [Added pipelined compilation support to `cargo`.][cargo/7143]
+- [You can now pass the `--features` option multiple times to enable
+ multiple features.][cargo/7084]
+
+Misc
+----
+- [`rustc` will now warn about some incorrect uses of
+ `mem::{uninitialized, zeroed}` that are known to cause undefined behaviour.][63346]
+
+[60260]: https://github.com/rust-lang/rust/pull/60260/
+[61457]: https://github.com/rust-lang/rust/pull/61457/
+[61491]: https://github.com/rust-lang/rust/pull/61491/
+[61884]: https://github.com/rust-lang/rust/pull/61884/
+[61953]: https://github.com/rust-lang/rust/pull/61953/
+[62042]: https://github.com/rust-lang/rust/pull/62042/
+[62528]: https://github.com/rust-lang/rust/pull/62528/
+[62583]: https://github.com/rust-lang/rust/pull/62583/
+[62735]: https://github.com/rust-lang/rust/pull/62735/
+[62766]: https://github.com/rust-lang/rust/pull/62766/
+[62784]: https://github.com/rust-lang/rust/pull/62784/
+[62814]: https://github.com/rust-lang/rust/pull/62814/
+[63000]: https://github.com/rust-lang/rust/pull/63000/
+[63056]: https://github.com/rust-lang/rust/pull/63056/
+[63107]: https://github.com/rust-lang/rust/pull/63107/
+[63346]: https://github.com/rust-lang/rust/pull/63346/
+[63421]: https://github.com/rust-lang/rust/pull/63421/
+[cargo/7084]: https://github.com/rust-lang/cargo/pull/7084/
+[cargo/7143]: https://github.com/rust-lang/cargo/pull/7143/
+[`<*const T>::cast`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.cast
+[`<*mut T>::cast`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.cast
+[`Duration::as_secs_f32`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.as_secs_f32
+[`Duration::as_secs_f64`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.as_secs_f64
+[`Duration::div_duration_f32`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.div_duration_f32
+[`Duration::div_duration_f64`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.div_duration_f64
+[`Duration::div_f32`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.div_f32
+[`Duration::div_f64`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.div_f64
+[`Duration::from_secs_f32`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.from_secs_f32
+[`Duration::from_secs_f64`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.from_secs_f64
+[`Duration::mul_f32`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.mul_f32
+[`Duration::mul_f64`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.mul_f64
+[`any::type_name`]: https://doc.rust-lang.org/std/any/fn.type_name.html
+[forge-platform-support]: https://forge.rust-lang.org/platform-support.html
+[pipeline-internals]: https://internals.rust-lang.org/t/evaluating-pipelined-rustc-compilation/10199
+
Version 1.37.0 (2019-08-15)
==========================
diff --git a/src/ci/azure-pipelines/auto.yml b/src/ci/azure-pipelines/auto.yml
index 77c9cda..1656066 100644
--- a/src/ci/azure-pipelines/auto.yml
+++ b/src/ci/azure-pipelines/auto.yml
@@ -236,10 +236,16 @@
MSYS_BITS: 32
RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc
SCRIPT: make ci-subset-1
+ # FIXME(#59637)
+ NO_DEBUG_ASSERTIONS: 1
+ NO_LLVM_ASSERTIONS: 1
i686-msvc-2:
MSYS_BITS: 32
RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc
SCRIPT: make ci-subset-2
+ # FIXME(#59637)
+ NO_DEBUG_ASSERTIONS: 1
+ NO_LLVM_ASSERTIONS: 1
# MSVC aux tests
x86_64-msvc-aux:
MSYS_BITS: 64
@@ -250,6 +256,9 @@
SCRIPT: python x.py test src/tools/cargotest src/tools/cargo
RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc
VCVARS_BAT: vcvars64.bat
+ # FIXME(#59637)
+ NO_DEBUG_ASSERTIONS: 1
+ NO_LLVM_ASSERTIONS: 1
# MSVC tools tests
x86_64-msvc-tools:
MSYS_BITS: 64
diff --git a/src/ci/docker/i686-gnu-nopt/Dockerfile b/src/ci/docker/i686-gnu-nopt/Dockerfile
index 2041ba5..517b59c 100644
--- a/src/ci/docker/i686-gnu-nopt/Dockerfile
+++ b/src/ci/docker/i686-gnu-nopt/Dockerfile
@@ -19,3 +19,6 @@
ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu --disable-optimize-tests
ENV SCRIPT python2.7 ../x.py test
+
+# FIXME(#59637) takes too long on CI right now
+ENV NO_LLVM_ASSERTIONS=1 NO_DEBUG_ASSERTIONS=1
diff --git a/src/ci/docker/i686-gnu/Dockerfile b/src/ci/docker/i686-gnu/Dockerfile
index 17441dd..03db3ba 100644
--- a/src/ci/docker/i686-gnu/Dockerfile
+++ b/src/ci/docker/i686-gnu/Dockerfile
@@ -25,3 +25,6 @@
--exclude src/test/rustdoc-js \
--exclude src/tools/error_index_generator \
--exclude src/tools/linkchecker
+
+# FIXME(#59637) takes too long on CI right now
+ENV NO_LLVM_ASSERTIONS=1 NO_DEBUG_ASSERTIONS=1
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index d145f22..ecff40a 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -845,21 +845,26 @@
///
/// ```
/// let store = [0, 1, 2, 3];
- /// let mut v_orig = store.iter().collect::<Vec<&i32>>();
+ /// let v_orig = store.iter().collect::<Vec<&i32>>();
+ ///
+ /// // clone the vector as we will reuse them later
+ /// let v_clone = v_orig.clone();
///
/// // Using transmute: this is Undefined Behavior, and a bad idea.
/// // However, it is no-copy.
/// let v_transmuted = unsafe {
- /// std::mem::transmute::<Vec<&i32>, Vec<Option<&i32>>>(
- /// v_orig.clone())
+ /// std::mem::transmute::<Vec<&i32>, Vec<Option<&i32>>>(v_clone)
/// };
///
+ /// let v_clone = v_orig.clone();
+ ///
/// // This is the suggested, safe way.
/// // It does copy the entire vector, though, into a new array.
- /// let v_collected = v_orig.clone()
- /// .into_iter()
- /// .map(|r| Some(r))
- /// .collect::<Vec<Option<&i32>>>();
+ /// let v_collected = v_clone.into_iter()
+ /// .map(Some)
+ /// .collect::<Vec<Option<&i32>>>();
+ ///
+ /// let v_clone = v_orig.clone();
///
/// // The no-copy, unsafe way, still using transmute, but not UB.
/// // This is equivalent to the original, but safer, and reuses the
@@ -869,11 +874,12 @@
/// // the original inner type (`&i32`) to the converted inner type
/// // (`Option<&i32>`), so read the nomicon pages linked above.
/// let v_from_raw = unsafe {
- /// Vec::from_raw_parts(v_orig.as_mut_ptr() as *mut Option<&i32>,
- /// v_orig.len(),
- /// v_orig.capacity())
+ /// // Ensure the original vector is not dropped.
+ /// let mut v_clone = std::mem::ManuallyDrop::new(v_clone);
+ /// Vec::from_raw_parts(v_clone.as_mut_ptr() as *mut Option<&i32>,
+ /// v_clone.len(),
+ /// v_clone.capacity())
/// };
- /// std::mem::forget(v_orig);
/// ```
///
/// Implementing `split_at_mut`:
diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs
index be59e83..1dc6d54 100644
--- a/src/libcore/pin.rs
+++ b/src/libcore/pin.rs
@@ -584,6 +584,27 @@
/// the pointee cannot move after `Pin<Pointer<T>>` got created.
/// "Malicious" implementations of `Pointer::DerefMut` are likewise
/// ruled out by the contract of `Pin::new_unchecked`.
+ ///
+ /// This method is useful when doing multiple calls to functions that consume the pinned type.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::pin::Pin;
+ ///
+ /// # struct Type {}
+ /// impl Type {
+ /// fn method(self: Pin<&mut Self>) {
+ /// // do something
+ /// }
+ ///
+ /// fn call_method_twice(mut self: Pin<&mut Self>) {
+ /// // `method` consumes `self`, so reborrow the `Pin<&mut Self>` via `as_mut`.
+ /// self.as_mut().method();
+ /// self.as_mut().method();
+ /// }
+ /// }
+ /// ```
#[stable(feature = "pin", since = "1.33.0")]
#[inline(always)]
pub fn as_mut(&mut self) -> Pin<&mut P::Target> {
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 58789a1..48f7fc4 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -2682,12 +2682,8 @@
bounds.iter().map(|bound| self.lower_param_bound(bound, itctx.reborrow())).collect()
}
- fn lower_block_with_stmts(
- &mut self,
- b: &Block,
- targeted_by_break: bool,
- mut stmts: Vec<hir::Stmt>,
- ) -> P<hir::Block> {
+ fn lower_block(&mut self, b: &Block, targeted_by_break: bool) -> P<hir::Block> {
+ let mut stmts = vec![];
let mut expr = None;
for (index, stmt) in b.stmts.iter().enumerate() {
@@ -2712,8 +2708,11 @@
})
}
- fn lower_block(&mut self, b: &Block, targeted_by_break: bool) -> P<hir::Block> {
- self.lower_block_with_stmts(b, targeted_by_break, vec![])
+ /// Lowers a block directly to an expression, presuming that it
+ /// has no attributes and is not targeted by a `break`.
+ fn lower_block_expr(&mut self, b: &Block) -> hir::Expr {
+ let block = self.lower_block(b, false);
+ self.expr_block(block, ThinVec::new())
}
fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
diff --git a/src/librustc/hir/lowering/expr.rs b/src/librustc/hir/lowering/expr.rs
index a46cdab..990728f 100644
--- a/src/librustc/hir/lowering/expr.rs
+++ b/src/librustc/hir/lowering/expr.rs
@@ -90,10 +90,7 @@
),
ExprKind::Async(capture_clause, closure_node_id, ref block) => {
self.make_async_expr(capture_clause, closure_node_id, None, block.span, |this| {
- this.with_new_scopes(|this| {
- let block = this.lower_block(block, false);
- this.expr_block(block, ThinVec::new())
- })
+ this.with_new_scopes(|this| this.lower_block_expr(block))
})
}
ExprKind::Await(ref expr) => self.lower_expr_await(e.span, expr),
@@ -284,8 +281,7 @@
let else_arm = self.arm(hir_vec![else_pat], P(else_expr));
// Handle then + scrutinee:
- let then_blk = self.lower_block(then, false);
- let then_expr = self.expr_block(then_blk, ThinVec::new());
+ let then_expr = self.lower_block_expr(then);
let (then_pat, scrutinee, desugar) = match cond.node {
// `<pat> => <then>`:
ExprKind::Let(ref pat, ref scrutinee) => {
@@ -335,8 +331,7 @@
};
// Handle then + scrutinee:
- let then_blk = self.lower_block(body, false);
- let then_expr = self.expr_block(then_blk, ThinVec::new());
+ let then_expr = self.lower_block_expr(body);
let (then_pat, scrutinee, desugar, source) = match cond.node {
ExprKind::Let(ref pat, ref scrutinee) => {
// to:
@@ -356,7 +351,7 @@
//
// ```
// 'label: loop {
- // match DropTemps($cond) {
+ // match drop-temps { $cond } {
// true => $body,
// _ => break,
// }
@@ -1310,7 +1305,7 @@
/// `{ let _t = $expr; _t }` but should provide better compile-time performance.
///
/// The drop order can be important in e.g. `if expr { .. }`.
- fn expr_drop_temps(
+ pub(super) fn expr_drop_temps(
&mut self,
span: Span,
expr: P<hir::Expr>,
diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs
index 5f82e42..61be40a 100644
--- a/src/librustc/hir/lowering/item.rs
+++ b/src/librustc/hir/lowering/item.rs
@@ -1071,10 +1071,7 @@
}
fn lower_fn_body_block(&mut self, decl: &FnDecl, body: &Block) -> hir::BodyId {
- self.lower_fn_body(decl, |this| {
- let body = this.lower_block(body, false);
- this.expr_block(body, ThinVec::new())
- })
+ self.lower_fn_body(decl, |this| this.lower_block_expr(body))
}
pub(super) fn lower_const_body(&mut self, expr: &Expr) -> hir::BodyId {
@@ -1102,8 +1099,7 @@
// from:
//
// async fn foo(<pattern>: <ty>, <pattern>: <ty>, <pattern>: <ty>) {
- // async move {
- // }
+ // <body>
// }
//
// into:
@@ -1116,11 +1112,19 @@
// let <pattern> = __arg1;
// let __arg0 = __arg0;
// let <pattern> = __arg0;
+ // drop-temps { <body> } // see comments later in fn for details
// }
// }
//
// If `<pattern>` is a simple ident, then it is lowered to a single
// `let <pattern> = <pattern>;` statement as an optimization.
+ //
+ // Note that the body is embedded in `drop-temps`; an
+ // equivalent desugaring would be `return { <body>
+ // };`. The key point is that we wish to drop all the
+ // let-bound variables and temporaries created in the body
+ // (and its tail expression!) before we drop the
+ // parameters (c.f. rust-lang/rust#64512).
for (index, parameter) in decl.inputs.iter().enumerate() {
let parameter = this.lower_param(parameter);
let span = parameter.pat.span;
@@ -1219,8 +1223,36 @@
let async_expr = this.make_async_expr(
CaptureBy::Value, closure_id, None, body.span,
|this| {
- let body = this.lower_block_with_stmts(body, false, statements);
- this.expr_block(body, ThinVec::new())
+ // Create a block from the user's function body:
+ let user_body = this.lower_block_expr(body);
+
+ // Transform into `drop-temps { <user-body> }`, an expression:
+ let desugared_span = this.mark_span_with_reason(
+ DesugaringKind::Async,
+ user_body.span,
+ None,
+ );
+ let user_body = this.expr_drop_temps(
+ desugared_span,
+ P(user_body),
+ ThinVec::new(),
+ );
+
+ // As noted above, create the final block like
+ //
+ // ```
+ // {
+ // let $param_pattern = $raw_param;
+ // ...
+ // drop-temps { <user-body> }
+ // }
+ // ```
+ let body = this.block_all(
+ desugared_span,
+ statements.into(),
+ Some(P(user_body)),
+ );
+ this.expr_block(P(body), ThinVec::new())
});
(HirVec::from(parameters), this.expr(body.span, async_expr, ThinVec::new()))
})
diff --git a/src/librustc/infer/equate.rs b/src/librustc/infer/equate.rs
index 5dfa0d2..96d40bc 100644
--- a/src/librustc/infer/equate.rs
+++ b/src/librustc/infer/equate.rs
@@ -97,7 +97,7 @@
self.tag(),
a,
b);
- let origin = Subtype(self.fields.trace.clone());
+ let origin = Subtype(box self.fields.trace.clone());
self.fields.infcx.borrow_region_constraints()
.make_eqregion(origin, a, b);
Ok(a)
diff --git a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs
index 19bd38b..bfa8353 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs
@@ -30,7 +30,7 @@
Some(RegionResolutionError::SubSupConflict(
vid,
_,
- SubregionOrigin::Subtype(TypeTrace {
+ SubregionOrigin::Subtype(box TypeTrace {
cause,
values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
}),
@@ -50,7 +50,7 @@
Some(RegionResolutionError::SubSupConflict(
vid,
_,
- SubregionOrigin::Subtype(TypeTrace {
+ SubregionOrigin::Subtype(box TypeTrace {
cause,
values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
}),
@@ -70,7 +70,7 @@
Some(RegionResolutionError::SubSupConflict(
vid,
_,
- SubregionOrigin::Subtype(TypeTrace {
+ SubregionOrigin::Subtype(box TypeTrace {
cause,
values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
}),
@@ -92,7 +92,7 @@
_,
_,
_,
- SubregionOrigin::Subtype(TypeTrace {
+ SubregionOrigin::Subtype(box TypeTrace {
cause,
values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
}),
@@ -108,7 +108,7 @@
)),
Some(RegionResolutionError::ConcreteFailure(
- SubregionOrigin::Subtype(TypeTrace {
+ SubregionOrigin::Subtype(box TypeTrace {
cause,
values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
}),
@@ -125,7 +125,7 @@
)),
Some(RegionResolutionError::ConcreteFailure(
- SubregionOrigin::Subtype(TypeTrace {
+ SubregionOrigin::Subtype(box TypeTrace {
cause,
values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
}),
@@ -142,7 +142,7 @@
)),
Some(RegionResolutionError::ConcreteFailure(
- SubregionOrigin::Subtype(TypeTrace {
+ SubregionOrigin::Subtype(box TypeTrace {
cause,
values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
}),
diff --git a/src/librustc/infer/error_reporting/note.rs b/src/librustc/infer/error_reporting/note.rs
index caed428..115ffea 100644
--- a/src/librustc/infer/error_reporting/note.rs
+++ b/src/librustc/infer/error_reporting/note.rs
@@ -138,7 +138,7 @@
sup: Region<'tcx>)
-> DiagnosticBuilder<'tcx> {
match origin {
- infer::Subtype(trace) => {
+ infer::Subtype(box trace) => {
let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
let mut err = self.report_and_explain_type_error(trace, &terr);
self.tcx.note_and_explain_region(region_scope_tree, &mut err, "", sup, "...");
@@ -450,7 +450,7 @@
) -> DiagnosticBuilder<'tcx> {
// I can't think how to do better than this right now. -nikomatsakis
match placeholder_origin {
- infer::Subtype(trace) => {
+ infer::Subtype(box trace) => {
let terr = TypeError::RegionsPlaceholderMismatch;
self.report_and_explain_type_error(trace, &terr)
}
diff --git a/src/librustc/infer/glb.rs b/src/librustc/infer/glb.rs
index 2cef521..10e4532 100644
--- a/src/librustc/infer/glb.rs
+++ b/src/librustc/infer/glb.rs
@@ -57,7 +57,7 @@
a,
b);
- let origin = Subtype(self.fields.trace.clone());
+ let origin = Subtype(box self.fields.trace.clone());
Ok(self.fields.infcx.borrow_region_constraints().glb_regions(self.tcx(), origin, a, b))
}
diff --git a/src/librustc/infer/lub.rs b/src/librustc/infer/lub.rs
index e20372f..8b64cda 100644
--- a/src/librustc/infer/lub.rs
+++ b/src/librustc/infer/lub.rs
@@ -57,7 +57,7 @@
a,
b);
- let origin = Subtype(self.fields.trace.clone());
+ let origin = Subtype(box self.fields.trace.clone());
Ok(self.fields.infcx.borrow_region_constraints().lub_regions(self.tcx(), origin, a, b))
}
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index 8638f42..a886c44 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -254,7 +254,7 @@
#[derive(Clone, Debug)]
pub enum SubregionOrigin<'tcx> {
/// Arose from a subtyping relation
- Subtype(TypeTrace<'tcx>),
+ Subtype(Box<TypeTrace<'tcx>>),
/// Stack-allocated closures cannot outlive innermost loop
/// or function so as to ensure we only require finite stack
@@ -340,6 +340,10 @@
},
}
+// `SubregionOrigin` is used a lot. Make sure it doesn't unintentionally get bigger.
+#[cfg(target_arch = "x86_64")]
+static_assert_size!(SubregionOrigin<'_>, 32);
+
/// Places that type/region parameters can appear.
#[derive(Clone, Copy, Debug)]
pub enum ParameterOrigin {
diff --git a/src/librustc/infer/sub.rs b/src/librustc/infer/sub.rs
index cd1d206..76db55e 100644
--- a/src/librustc/infer/sub.rs
+++ b/src/librustc/infer/sub.rs
@@ -130,7 +130,7 @@
// FIXME -- we have more fine-grained information available
// from the "cause" field, we could perhaps give more tailored
// error messages.
- let origin = SubregionOrigin::Subtype(self.fields.trace.clone());
+ let origin = SubregionOrigin::Subtype(box self.fields.trace.clone());
self.fields.infcx.borrow_region_constraints()
.make_subregion(origin, a, b);
diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs
index 09c822f..ac99ccd 100644
--- a/src/librustc/mir/interpret/error.rs
+++ b/src/librustc/mir/interpret/error.rs
@@ -213,6 +213,15 @@
eprintln!("\n\nAn error occurred in miri:\n{:?}", backtrace);
}
+impl From<ErrorHandled> for InterpErrorInfo<'tcx> {
+ fn from(err: ErrorHandled) -> Self {
+ match err {
+ ErrorHandled::Reported => err_inval!(ReferencedConstant),
+ ErrorHandled::TooGeneric => err_inval!(TooGeneric),
+ }.into()
+ }
+}
+
impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> {
fn from(kind: InterpError<'tcx>) -> Self {
let backtrace = match env::var("RUSTC_CTFE_BACKTRACE") {
@@ -313,6 +322,9 @@
}
}
+/// Error information for when the program we executed turned out not to actually be a valid
+/// program. This cannot happen in stand-alone Miri, but it can happen during CTFE/ConstProp
+/// where we work on generic code or execution does not have all information available.
#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
pub enum InvalidProgramInfo<'tcx> {
/// Resolution can fail if we are in a too generic context.
@@ -342,6 +354,7 @@
}
}
+/// Error information for when the program caused Undefined Behavior.
#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
pub enum UndefinedBehaviorInfo {
/// Free-form case. Only for errors that are never caught!
@@ -364,12 +377,19 @@
}
}
+/// Error information for when the program did something that might (or might not) be correct
+/// to do according to the Rust spec, but due to limitations in the interpreter, the
+/// operation could not be carried out. These limitations can differ between CTFE and the
+/// Miri engine, e.g., CTFE does not support casting pointers to "real" integers.
+///
+/// Currently, we also use this as fall-back error kind for errors that have not been
+/// categorized yet.
#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
pub enum UnsupportedOpInfo<'tcx> {
/// Free-form case. Only for errors that are never caught!
Unsupported(String),
- // -- Everything below is not classified yet --
+ // -- Everything below is not categorized yet --
FunctionAbiMismatch(Abi, Abi),
FunctionArgMismatch(Ty<'tcx>, Ty<'tcx>),
FunctionRetMismatch(Ty<'tcx>, Ty<'tcx>),
@@ -536,6 +556,8 @@
}
}
+/// Error information for when the program exhausted the resources granted to it
+/// by the interpreter.
#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
pub enum ResourceExhaustionInfo {
/// The stack grew too big.
diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs
index 4ebc2e7..c726094 100644
--- a/src/librustc/query/mod.rs
+++ b/src/librustc/query/mod.rs
@@ -462,15 +462,6 @@
no_force
desc { "extract field of const" }
}
-
- /// Produces an absolute path representation of the given type. See also the documentation
- /// on `std::any::type_name`.
- query type_name(key: Ty<'tcx>) -> &'tcx ty::Const<'tcx> {
- eval_always
- no_force
- desc { "get absolute path of type" }
- }
-
}
TypeChecking {
diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs
index 5fbfe91..3f3c5ac1 100644
--- a/src/librustc_codegen_llvm/intrinsic.rs
+++ b/src/librustc_codegen_llvm/intrinsic.rs
@@ -15,6 +15,7 @@
use rustc_codegen_ssa::base::{to_immediate, wants_msvc_seh, compare_simd_types};
use rustc::ty::{self, Ty};
use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, Primitive};
+use rustc::mir::interpret::GlobalId;
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
use rustc::hir;
use syntax::ast::{self, FloatTy};
@@ -81,13 +82,14 @@
impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
fn codegen_intrinsic_call(
&mut self,
- callee_ty: Ty<'tcx>,
+ instance: ty::Instance<'tcx>,
fn_ty: &FnType<'tcx, Ty<'tcx>>,
args: &[OperandRef<'tcx, &'ll Value>],
llresult: &'ll Value,
span: Span,
) {
let tcx = self.tcx;
+ let callee_ty = instance.ty(tcx);
let (def_id, substs) = match callee_ty.sty {
ty::FnDef(def_id, substs) => (def_id, substs),
@@ -133,10 +135,6 @@
let llfn = self.get_intrinsic(&("llvm.debugtrap"));
self.call(llfn, &[], None)
}
- "size_of" => {
- let tp_ty = substs.type_at(0);
- self.const_usize(self.size_of(tp_ty).bytes())
- }
"va_start" => {
self.va_start(args[0].immediate())
}
@@ -188,10 +186,6 @@
self.const_usize(self.size_of(tp_ty).bytes())
}
}
- "min_align_of" => {
- let tp_ty = substs.type_at(0);
- self.const_usize(self.align_of(tp_ty).bytes())
- }
"min_align_of_val" => {
let tp_ty = substs.type_at(0);
if let OperandValue::Pair(_, meta) = args[0].val {
@@ -201,18 +195,19 @@
self.const_usize(self.align_of(tp_ty).bytes())
}
}
- "pref_align_of" => {
- let tp_ty = substs.type_at(0);
- self.const_usize(self.layout_of(tp_ty).align.pref.bytes())
- }
+ "size_of" |
+ "pref_align_of" |
+ "min_align_of" |
+ "needs_drop" |
+ "type_id" |
"type_name" => {
- let tp_ty = substs.type_at(0);
- let ty_name = self.tcx.type_name(tp_ty);
+ let gid = GlobalId {
+ instance,
+ promoted: None,
+ };
+ let ty_name = self.tcx.const_eval(ty::ParamEnv::reveal_all().and(gid)).unwrap();
OperandRef::from_const(self, ty_name).immediate_or_packed_pair(self)
}
- "type_id" => {
- self.const_u64(self.tcx.type_id_hash(substs.type_at(0)))
- }
"init" => {
let ty = substs.type_at(0);
if !self.layout_of(ty).is_zst() {
@@ -235,11 +230,6 @@
"uninit" | "forget" => {
return;
}
- "needs_drop" => {
- let tp_ty = substs.type_at(0);
-
- self.const_bool(self.type_needs_drop(tp_ty))
- }
"offset" => {
let ptr = args[0].immediate();
let offset = args[1].immediate();
diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs
index 8829a33..1bb0ea5 100644
--- a/src/librustc_codegen_ssa/mir/block.rs
+++ b/src/librustc_codegen_ssa/mir/block.rs
@@ -667,8 +667,7 @@
}).collect();
- let callee_ty = instance.as_ref().unwrap().ty(bx.tcx());
- bx.codegen_intrinsic_call(callee_ty, &fn_ty, &args, dest,
+ bx.codegen_intrinsic_call(*instance.as_ref().unwrap(), &fn_ty, &args, dest,
terminator.source_info.span);
if let ReturnDest::IndirectOperand(dst, _) = ret_dest {
diff --git a/src/librustc_codegen_ssa/traits/intrinsic.rs b/src/librustc_codegen_ssa/traits/intrinsic.rs
index ede30a0..7c79cd6 100644
--- a/src/librustc_codegen_ssa/traits/intrinsic.rs
+++ b/src/librustc_codegen_ssa/traits/intrinsic.rs
@@ -1,6 +1,6 @@
use super::BackendTypes;
use crate::mir::operand::OperandRef;
-use rustc::ty::Ty;
+use rustc::ty::{self, Ty};
use rustc_target::abi::call::FnType;
use syntax_pos::Span;
@@ -10,7 +10,7 @@
/// add them to librustc_codegen_llvm/context.rs
fn codegen_intrinsic_call(
&mut self,
- callee_ty: Ty<'tcx>,
+ instance: ty::Instance<'tcx>,
fn_ty: &FnType<'tcx, Ty<'tcx>>,
args: &[OperandRef<'tcx, Self::Value>],
llresult: Self::Value,
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index c4d3ad9..fa9504e 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -326,6 +326,7 @@
}
fn post(&self, s: &mut pprust::State<'_>, node: pprust::AnnNode<'_>) {
match node {
+ pprust::AnnNode::Crate(_) |
pprust::AnnNode::Ident(_) |
pprust::AnnNode::Name(_) => {},
@@ -431,14 +432,18 @@
match node {
pprust::AnnNode::Ident(&ast::Ident { name, span }) => {
s.s.space();
- // FIXME #16420: this doesn't display the connections
- // between syntax contexts
s.synth_comment(format!("{}{:?}", name.as_u32(), span.ctxt()))
}
pprust::AnnNode::Name(&name) => {
s.s.space();
s.synth_comment(name.as_u32().to_string())
}
+ pprust::AnnNode::Crate(_) => {
+ s.s.hardbreak();
+ let verbose = self.sess.verbose();
+ s.synth_comment(syntax_pos::hygiene::debug_hygiene_data(verbose));
+ s.s.hardbreak_if_not_bol();
+ }
_ => {}
}
}
diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs
index 6660836..d238de2 100644
--- a/src/librustc_errors/emitter.rs
+++ b/src/librustc_errors/emitter.rs
@@ -1144,15 +1144,18 @@
buffer.prepend(0, " ", Style::NoStyle);
}
draw_note_separator(&mut buffer, 0, max_line_num_len + 1);
- let level_str = level.to_string();
- if !level_str.is_empty() {
- buffer.append(0, &level_str, Style::MainHeaderMsg);
- buffer.append(0, ": ", Style::NoStyle);
+ if *level != Level::FailureNote {
+ let level_str = level.to_string();
+ if !level_str.is_empty() {
+ buffer.append(0, &level_str, Style::MainHeaderMsg);
+ buffer.append(0, ": ", Style::NoStyle);
+ }
}
self.msg_to_buffer(&mut buffer, msg, max_line_num_len, "note", None);
} else {
let level_str = level.to_string();
- if !level_str.is_empty() {
+ // The failure note level itself does not provide any useful diagnostic information
+ if *level != Level::FailureNote && !level_str.is_empty() {
buffer.append(0, &level_str, Style::Level(level.clone()));
}
// only render error codes, not lint codes
@@ -1161,7 +1164,7 @@
buffer.append(0, &code, Style::Level(level.clone()));
buffer.append(0, "]", Style::Level(level.clone()));
}
- if !level_str.is_empty() {
+ if *level != Level::FailureNote && !level_str.is_empty() {
buffer.append(0, ": ", header_style);
}
for &(ref text, _) in msg.iter() {
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index c1fba41..8b543be 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -833,7 +833,7 @@
Warning => "warning",
Note => "note",
Help => "help",
- FailureNote => "",
+ FailureNote => "failure-note",
Cancelled => panic!("Shouldn't call on cancelled error"),
}
}
diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs
index 3f53f84..4351598 100644
--- a/src/librustc_mir/const_eval.rs
+++ b/src/librustc_mir/const_eval.rs
@@ -15,6 +15,7 @@
use rustc::ty::layout::{self, LayoutOf, VariantIdx};
use rustc::traits::Reveal;
use rustc_data_structures::fx::FxHashMap;
+use crate::interpret::eval_nullary_intrinsic;
use syntax::source_map::{Span, DUMMY_SP};
@@ -602,6 +603,23 @@
other => return other,
}
}
+
+ // We call `const_eval` for zero arg intrinsics, too, in order to cache their value.
+ // Catch such calls and evaluate them instead of trying to load a constant's MIR.
+ if let ty::InstanceDef::Intrinsic(def_id) = key.value.instance.def {
+ let ty = key.value.instance.ty(tcx);
+ let substs = match ty.sty {
+ ty::FnDef(_, substs) => substs,
+ _ => bug!("intrinsic with type {:?}", ty),
+ };
+ return eval_nullary_intrinsic(tcx, key.param_env, def_id, substs)
+ .map_err(|error| {
+ let span = tcx.def_span(def_id);
+ let error = ConstEvalErr { error: error.kind, stacktrace: vec![], span };
+ error.report_as_error(tcx.at(span), "could not evaluate nullary intrinsic")
+ })
+ }
+
tcx.const_eval_raw(key).and_then(|val| {
validate_and_turn_into_const(tcx, val, key)
})
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 054b65f..78996ed 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -14,7 +14,6 @@
use rustc::ty::query::TyCtxtAt;
use rustc_data_structures::indexed_vec::IndexVec;
use rustc::mir::interpret::{
- ErrorHandled,
GlobalId, Scalar, Pointer, FrameInfo, AllocId,
InterpResult, truncate, sign_extend,
};
@@ -672,14 +671,7 @@
// Our result will later be validated anyway, and there seems no good reason
// to have to fail early here. This is also more consistent with
// `Memory::get_static_alloc` which has to use `const_eval_raw` to avoid cycles.
- let val = self.tcx.const_eval_raw(param_env.and(gid)).map_err(|err| {
- match err {
- ErrorHandled::Reported =>
- err_inval!(ReferencedConstant),
- ErrorHandled::TooGeneric =>
- err_inval!(TooGeneric),
- }
- })?;
+ let val = self.tcx.const_eval_raw(param_env.and(gid))?;
self.raw_const_to_mplace(val)
}
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs
index 0f2305e..ec09e69 100644
--- a/src/librustc_mir/interpret/intrinsics.rs
+++ b/src/librustc_mir/interpret/intrinsics.rs
@@ -5,17 +5,18 @@
use syntax::symbol::Symbol;
use rustc::ty;
use rustc::ty::layout::{LayoutOf, Primitive, Size};
+use rustc::ty::subst::SubstsRef;
+use rustc::hir::def_id::DefId;
+use rustc::ty::TyCtxt;
use rustc::mir::BinOp;
-use rustc::mir::interpret::{InterpResult, Scalar};
+use rustc::mir::interpret::{InterpResult, Scalar, GlobalId, ConstValue};
use super::{
- Machine, PlaceTy, OpTy, InterpCx, Immediate,
+ Machine, PlaceTy, OpTy, InterpCx,
};
mod type_name;
-pub use type_name::*;
-
fn numeric_intrinsic<'tcx, Tag>(
name: &str,
bits: u128,
@@ -37,6 +38,50 @@
Ok(Scalar::from_uint(bits_out, size))
}
+/// The logic for all nullary intrinsics is implemented here. These intrinsics don't get evaluated
+/// inside an `InterpCx` and instead have their value computed directly from rustc internal info.
+crate fn eval_nullary_intrinsic<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+ def_id: DefId,
+ substs: SubstsRef<'tcx>,
+) -> InterpResult<'tcx, &'tcx ty::Const<'tcx>> {
+ let tp_ty = substs.type_at(0);
+ let name = &*tcx.item_name(def_id).as_str();
+ Ok(match name {
+ "type_name" => {
+ let alloc = type_name::alloc_type_name(tcx, tp_ty);
+ tcx.mk_const(ty::Const {
+ val: ConstValue::Slice {
+ data: alloc,
+ start: 0,
+ end: alloc.len(),
+ },
+ ty: tcx.mk_static_str(),
+ })
+ },
+ "needs_drop" => ty::Const::from_bool(tcx, tp_ty.needs_drop(tcx, param_env)),
+ "size_of" |
+ "min_align_of" |
+ "pref_align_of" => {
+ let layout = tcx.layout_of(param_env.and(tp_ty)).map_err(|e| err_inval!(Layout(e)))?;
+ let n = match name {
+ "pref_align_of" => layout.align.pref.bytes(),
+ "min_align_of" => layout.align.abi.bytes(),
+ "size_of" => layout.size.bytes(),
+ _ => bug!(),
+ };
+ ty::Const::from_usize(tcx, n)
+ },
+ "type_id" => ty::Const::from_bits(
+ tcx,
+ tcx.type_id_hash(tp_ty).into(),
+ param_env.and(tcx.types.u64),
+ ),
+ other => bug!("`{}` is not a zero arg intrinsic", other),
+ })
+}
+
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
/// Returns `true` if emulation happened.
pub fn emulate_intrinsic(
@@ -49,41 +94,19 @@
let intrinsic_name = &self.tcx.item_name(instance.def_id()).as_str()[..];
match intrinsic_name {
- "min_align_of" => {
- let elem_ty = substs.type_at(0);
- let elem_align = self.layout_of(elem_ty)?.align.abi.bytes();
- let align_val = Scalar::from_uint(elem_align, dest.layout.size);
- self.write_scalar(align_val, dest)?;
- }
-
- "needs_drop" => {
- let ty = substs.type_at(0);
- let ty_needs_drop = ty.needs_drop(self.tcx.tcx, self.param_env);
- let val = Scalar::from_bool(ty_needs_drop);
- self.write_scalar(val, dest)?;
- }
-
- "size_of" => {
- let ty = substs.type_at(0);
- let size = self.layout_of(ty)?.size.bytes() as u128;
- let size_val = Scalar::from_uint(size, dest.layout.size);
- self.write_scalar(size_val, dest)?;
- }
-
- "type_id" => {
- let ty = substs.type_at(0);
- let type_id = self.tcx.type_id_hash(ty) as u128;
- let id_val = Scalar::from_uint(type_id, dest.layout.size);
- self.write_scalar(id_val, dest)?;
- }
-
+ "min_align_of" |
+ "pref_align_of" |
+ "needs_drop" |
+ "size_of" |
+ "type_id" |
"type_name" => {
- let alloc = alloc_type_name(self.tcx.tcx, substs.type_at(0));
- let name_id = self.tcx.alloc_map.lock().create_memory_alloc(alloc);
- let id_ptr = self.memory.tag_static_base_pointer(name_id.into());
- let alloc_len = alloc.size.bytes();
- let name_val = Immediate::new_slice(Scalar::Ptr(id_ptr), alloc_len, self);
- self.write_immediate(name_val, dest)?;
+ let gid = GlobalId {
+ instance,
+ promoted: None,
+ };
+ let val = self.tcx.const_eval(self.param_env.and(gid))?;
+ let val = self.eval_const_to_op(val, None)?;
+ self.copy_op(val, dest)?;
}
| "ctpop"
diff --git a/src/librustc_mir/interpret/intrinsics/type_name.rs b/src/librustc_mir/interpret/intrinsics/type_name.rs
index 032d16a..1e765a4 100644
--- a/src/librustc_mir/interpret/intrinsics/type_name.rs
+++ b/src/librustc_mir/interpret/intrinsics/type_name.rs
@@ -7,7 +7,7 @@
use rustc::hir::map::{DefPathData, DisambiguatedDefPathData};
use rustc::hir::def_id::CrateNum;
use std::fmt::Write;
-use rustc::mir::interpret::{Allocation, ConstValue};
+use rustc::mir::interpret::Allocation;
struct AbsolutePathPrinter<'tcx> {
tcx: TyCtxt<'tcx>,
@@ -213,22 +213,11 @@
}
}
-/// Produces an absolute path representation of the given type. See also the documentation on
-/// `std::any::type_name`
-pub fn type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> &'tcx ty::Const<'tcx> {
- let alloc = alloc_type_name(tcx, ty);
- tcx.mk_const(ty::Const {
- val: ConstValue::Slice {
- data: alloc,
- start: 0,
- end: alloc.len(),
- },
- ty: tcx.mk_static_str(),
- })
-}
-
/// Directly returns an `Allocation` containing an absolute path representation of the given type.
-pub(super) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> &'tcx Allocation {
+crate fn alloc_type_name<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ ty: Ty<'tcx>
+) -> &'tcx Allocation {
let path = AbsolutePathPrinter { tcx, path: String::new() }.print_type(ty).unwrap().path;
let alloc = Allocation::from_byte_aligned_bytes(path.into_bytes());
tcx.intern_const_alloc(alloc)
diff --git a/src/librustc_mir/interpret/mod.rs b/src/librustc_mir/interpret/mod.rs
index 45d2434..0c61be2 100644
--- a/src/librustc_mir/interpret/mod.rs
+++ b/src/librustc_mir/interpret/mod.rs
@@ -34,6 +34,6 @@
pub use self::validity::RefTracking;
-pub(super) use self::intrinsics::type_name;
-
pub use self::intern::intern_const_alloc_recursive;
+
+crate use self::intrinsics::eval_nullary_intrinsic;
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index f27db35..034ad5b 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -59,5 +59,4 @@
let (param_env, (value, field)) = param_env_and_value.into_parts();
const_eval::const_field(tcx, param_env, None, field, value)
};
- providers.type_name = interpret::type_name;
}
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index 0386dbd..be364a1 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -2326,10 +2326,10 @@
/// An iterator over the contents of an instance of `BufRead` split on a
/// particular byte.
///
-/// This struct is generally created by calling [`split`][split] on a
-/// `BufRead`. Please see the documentation of `split()` for more details.
+/// This struct is generally created by calling [`split`] on a `BufRead`.
+/// Please see the documentation of [`split`] for more details.
///
-/// [split]: trait.BufRead.html#method.split
+/// [`split`]: trait.BufRead.html#method.split
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Debug)]
pub struct Split<B> {
@@ -2358,10 +2358,10 @@
/// An iterator over the lines of an instance of `BufRead`.
///
-/// This struct is generally created by calling [`lines`][lines] on a
-/// `BufRead`. Please see the documentation of `lines()` for more details.
+/// This struct is generally created by calling [`lines`] on a `BufRead`.
+/// Please see the documentation of [`lines`] for more details.
///
-/// [lines]: trait.BufRead.html#method.lines
+/// [`lines`]: trait.BufRead.html#method.lines
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Debug)]
pub struct Lines<B> {
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index bcbc0a1..b634dcc 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -2387,7 +2387,7 @@
),
/// A macro invocation.
///
- /// E.g., `macro_rules! foo { .. }` or `foo!(..)`.
+ /// E.g., `foo!(..)`.
Mac(Mac),
/// A macro definition.
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 5d8498f..bf36c0d 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -35,6 +35,7 @@
SubItem(ast::NodeId),
Expr(&'a ast::Expr),
Pat(&'a ast::Pat),
+ Crate(&'a ast::Crate),
}
pub trait PpAnn {
@@ -140,6 +141,7 @@
s.print_mod(&krate.module, &krate.attrs);
s.print_remaining_comments();
+ s.ann.post(&mut s, AnnNode::Crate(krate));
s.s.eof()
}
@@ -1369,8 +1371,12 @@
}
}
ast::ItemKind::MacroDef(ref macro_def) => {
- let (kw, has_bang) =
- if macro_def.legacy { ("macro_rules", true) } else { ("macro", false) };
+ let (kw, has_bang) = if macro_def.legacy {
+ ("macro_rules", true)
+ } else {
+ self.print_visibility(&item.vis);
+ ("macro", false)
+ };
self.print_mac_common(
Some(MacHeader::Keyword(kw)),
has_bang,
diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs
index 8971638..e28d932 100644
--- a/src/libsyntax_pos/hygiene.rs
+++ b/src/libsyntax_pos/hygiene.rs
@@ -343,6 +343,38 @@
}))
}
+pub fn debug_hygiene_data(verbose: bool) -> String {
+ HygieneData::with(|data| {
+ if verbose {
+ format!("{:#?}", data)
+ } else {
+ let mut s = String::from("");
+ s.push_str("Expansions:");
+ data.expn_data.iter().enumerate().for_each(|(id, expn_info)| {
+ let expn_info = expn_info.as_ref().expect("no expansion data for an expansion ID");
+ s.push_str(&format!(
+ "\n{}: parent: {:?}, call_site_ctxt: {:?}, kind: {:?}",
+ id,
+ expn_info.parent,
+ expn_info.call_site.ctxt(),
+ expn_info.kind,
+ ));
+ });
+ s.push_str("\n\nSyntaxContexts:");
+ data.syntax_context_data.iter().enumerate().for_each(|(id, ctxt)| {
+ s.push_str(&format!(
+ "\n#{}: parent: {:?}, outer_mark: ({:?}, {:?})",
+ id,
+ ctxt.parent,
+ ctxt.outer_expn,
+ ctxt.outer_transparency,
+ ));
+ });
+ s
+ }
+ })
+}
+
impl SyntaxContext {
#[inline]
pub const fn root() -> Self {
diff --git a/src/test/ui/issues/issue-44415.rs b/src/test/compile-fail/issue-44415.rs
similarity index 100%
rename from src/test/ui/issues/issue-44415.rs
rename to src/test/compile-fail/issue-44415.rs
diff --git a/src/test/pretty/macro.rs b/src/test/pretty/macro.rs
index 39677d1..1e1e1db 100644
--- a/src/test/pretty/macro.rs
+++ b/src/test/pretty/macro.rs
@@ -2,6 +2,6 @@
#![feature(decl_macro)]
-macro mac { ($ arg : expr) => { $ arg + $ arg } }
+pub(crate) macro mac { ($ arg : expr) => { $ arg + $ arg } }
fn main() { }
diff --git a/src/test/ui/async-await/drop-order/drop-order-for-temporary-in-tail-return-expr.rs b/src/test/ui/async-await/drop-order/drop-order-for-temporary-in-tail-return-expr.rs
new file mode 100644
index 0000000..e40acff
--- /dev/null
+++ b/src/test/ui/async-await/drop-order/drop-order-for-temporary-in-tail-return-expr.rs
@@ -0,0 +1,95 @@
+// aux-build:arc_wake.rs
+// edition:2018
+// run-pass
+
+#![allow(unused_variables)]
+
+// Test the drop order for parameters relative to local variables and
+// temporaries created in the tail return expression of the function
+// body. In particular, check that this drop order is the same between
+// a `async fn` and an ordinary `fn`. See #64512.
+
+extern crate arc_wake;
+
+use arc_wake::ArcWake;
+use std::cell::RefCell;
+use std::future::Future;
+use std::sync::Arc;
+use std::rc::Rc;
+use std::task::Context;
+
+struct EmptyWaker;
+
+impl ArcWake for EmptyWaker {
+ fn wake(self: Arc<Self>) {}
+}
+
+#[derive(Debug, Eq, PartialEq)]
+enum DropOrder {
+ Function,
+ Val(&'static str),
+}
+
+type DropOrderListPtr = Rc<RefCell<Vec<DropOrder>>>;
+
+struct D(&'static str, DropOrderListPtr);
+
+impl Drop for D {
+ fn drop(&mut self) {
+ self.1.borrow_mut().push(DropOrder::Val(self.0));
+ }
+}
+
+/// Check drop order of temporary "temp" as compared to `x`, `y`, and `z`.
+///
+/// Expected order:
+/// - `z`
+/// - temp
+/// - `y`
+/// - `x`
+async fn foo_async(x: D, _y: D) {
+ let l = x.1.clone();
+ let z = D("z", l.clone());
+ l.borrow_mut().push(DropOrder::Function);
+ helper_async(&D("temp", l)).await
+}
+
+async fn helper_async(v: &D) { }
+
+fn foo_sync(x: D, _y: D) {
+ let l = x.1.clone();
+ let z = D("z", l.clone());
+ l.borrow_mut().push(DropOrder::Function);
+ helper_sync(&D("temp", l))
+}
+
+fn helper_sync(v: &D) { }
+
+fn assert_drop_order_after_poll<Fut: Future<Output = ()>>(
+ f: impl FnOnce(DropOrderListPtr) -> Fut,
+ g: impl FnOnce(DropOrderListPtr),
+) {
+ let empty = Arc::new(EmptyWaker);
+ let waker = ArcWake::into_waker(empty);
+ let mut cx = Context::from_waker(&waker);
+
+ let actual_order = Rc::new(RefCell::new(Vec::new()));
+ let mut fut = Box::pin(f(actual_order.clone()));
+ let r = fut.as_mut().poll(&mut cx);
+
+ assert!(match r {
+ std::task::Poll::Ready(()) => true,
+ _ => false,
+ });
+
+ let expected_order = Rc::new(RefCell::new(Vec::new()));
+ g(expected_order.clone());
+
+ assert_eq!(*actual_order.borrow(), *expected_order.borrow());
+}
+
+fn main() {
+ // Free functions (see doc comment on function for what it tests).
+ assert_drop_order_after_poll(|l| foo_async(D("x", l.clone()), D("_y", l.clone())),
+ |l| foo_sync(D("x", l.clone()), D("_y", l.clone())));
+}
diff --git a/src/test/ui/async-await/issue-64391.rs b/src/test/ui/async-await/issue-64391.rs
new file mode 100644
index 0000000..c6faad3
--- /dev/null
+++ b/src/test/ui/async-await/issue-64391.rs
@@ -0,0 +1,14 @@
+// Regression test for Issue #64391. The goal here is that this
+// function compiles. In the past, due to incorrect drop order for
+// temporaries in the tail expression, we failed to compile this
+// example. The drop order itself is directly tested in
+// `drop-order/drop-order-for-temporary-in-tail-return-expr.rs`.
+//
+// check-pass
+// edition:2018
+
+async fn add(x: u32, y: u32) -> u32 {
+ async { x + y }.await
+}
+
+fn main() { }
diff --git a/src/test/ui/consts/const-size_of-cycle.stderr b/src/test/ui/consts/const-size_of-cycle.stderr
index fdba359..1ae39e7 100644
--- a/src/test/ui/consts/const-size_of-cycle.stderr
+++ b/src/test/ui/consts/const-size_of-cycle.stderr
@@ -14,6 +14,11 @@
|
LL | intrinsics::size_of::<T>()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires const-evaluating + checking `std::intrinsics::size_of`...
+ --> $SRC_DIR/libcore/intrinsics.rs:LL:COL
+ |
+LL | pub fn size_of<T>() -> usize;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: ...which requires computing layout of `Foo`...
= note: ...which requires normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: All, def_id: None }, value: [u8; _] }`...
= note: ...which again requires const-evaluating + checking `Foo::bytes::{{constant}}#0`, completing the cycle
diff --git a/src/test/ui/hygiene/unpretty-debug.stdout b/src/test/ui/hygiene/unpretty-debug.stdout
index beac4c1..6971873 100644
--- a/src/test/ui/hygiene/unpretty-debug.stdout
+++ b/src/test/ui/hygiene/unpretty-debug.stdout
@@ -13,3 +13,13 @@
fn bar /* 0#0 */() { let x /* 0#0 */ = 1; y /* 0#1 */ + x /* 0#0 */ }
fn y /* 0#0 */() { }
+
+/*
+Expansions:
+0: parent: ExpnId(0), call_site_ctxt: #0, kind: Root
+1: parent: ExpnId(0), call_site_ctxt: #0, kind: Macro(Bang, foo)
+
+SyntaxContexts:
+#0: parent: #0, outer_mark: (ExpnId(0), Opaque)
+#1: parent: #0, outer_mark: (ExpnId(1), SemiTransparent)
+*/
diff --git a/src/test/ui/issues/issue-44415.stderr b/src/test/ui/issues/issue-44415.stderr
deleted file mode 100644
index 8008e53..0000000
--- a/src/test/ui/issues/issue-44415.stderr
+++ /dev/null
@@ -1,28 +0,0 @@
-error[E0391]: cycle detected when const-evaluating + checking `Foo::bytes::{{constant}}#0`
- --> $DIR/issue-44415.rs:6:17
- |
-LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
- | ^^^^^^
- |
-note: ...which requires const-evaluating + checking `Foo::bytes::{{constant}}#0`...
- --> $DIR/issue-44415.rs:6:17
- |
-LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
- | ^^^^^^
-note: ...which requires const-evaluating `Foo::bytes::{{constant}}#0`...
- --> $DIR/issue-44415.rs:6:26
- |
-LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: ...which requires computing layout of `Foo`...
- = note: ...which requires normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: All, def_id: None }, value: [u8; _] }`...
- = note: ...which again requires const-evaluating + checking `Foo::bytes::{{constant}}#0`, completing the cycle
-note: cycle used when processing `Foo`
- --> $DIR/issue-44415.rs:5:1
- |
-LL | struct Foo {
- | ^^^^^^^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/json-short.stderr b/src/test/ui/json-short.stderr
index 86cb2f0..0a1fb56 100644
--- a/src/test/ui/json-short.stderr
+++ b/src/test/ui/json-short.stderr
@@ -15,5 +15,5 @@
"}
{"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to previous error
"}
-{"message":"For more information about this error, try `rustc --explain E0601`.","code":null,"level":"","spans":[],"children":[],"rendered":"For more information about this error, try `rustc --explain E0601`.
+{"message":"For more information about this error, try `rustc --explain E0601`.","code":null,"level":"failure-note","spans":[],"children":[],"rendered":"For more information about this error, try `rustc --explain E0601`.
"}
diff --git a/src/test/ui/lint/use_suggestion_json.stderr b/src/test/ui/lint/use_suggestion_json.stderr
index c7c53ab..678c888 100644
--- a/src/test/ui/lint/use_suggestion_json.stderr
+++ b/src/test/ui/lint/use_suggestion_json.stderr
@@ -412,7 +412,7 @@
{
"message": "For more information about this error, try `rustc --explain E0412`.",
"code": null,
- "level": "",
+ "level": "failure-note",
"spans": [],
"children": [],
"rendered": "\u001b[0m\u001b[1mFor more information about this error, try `rustc --explain E0412`.\u001b[0m
diff --git a/src/tools/build-manifest/Cargo.toml b/src/tools/build-manifest/Cargo.toml
index 63ae445..c364479 100644
--- a/src/tools/build-manifest/Cargo.toml
+++ b/src/tools/build-manifest/Cargo.toml
@@ -7,5 +7,3 @@
[dependencies]
toml = "0.5"
serde = { version = "1.0", features = ["derive"] }
-serde_json = "1.0"
-reqwest = "0.9"
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index c2d642b..eab23f3 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -10,10 +10,9 @@
use std::collections::BTreeMap;
use std::env;
use std::fs;
-use std::io::{self, Read, Write, BufRead, BufReader};
+use std::io::{self, Read, Write};
use std::path::{PathBuf, Path};
use std::process::{Command, Stdio};
-use std::collections::HashMap;
static HOSTS: &[&str] = &[
"aarch64-unknown-linux-gnu",
@@ -153,9 +152,6 @@
"x86_64-pc-windows-gnu",
];
-static TOOLSTATE: &str =
- "https://raw.githubusercontent.com/rust-lang-nursery/rust-toolstate/master/history/linux.tsv";
-
#[derive(Serialize)]
#[serde(rename_all = "kebab-case")]
struct Manifest {
@@ -364,7 +360,6 @@
self.lldb_git_commit_hash = self.git_commit_hash("lldb", "x86_64-unknown-linux-gnu");
self.miri_git_commit_hash = self.git_commit_hash("miri", "x86_64-unknown-linux-gnu");
- self.check_toolstate();
self.digest_and_sign();
let manifest = self.build_manifest();
self.write_channel_files(&self.rust_release, &manifest);
@@ -374,36 +369,6 @@
}
}
- /// If a tool does not pass its tests, don't ship it.
- /// Right now, we do this only for Miri.
- fn check_toolstate(&mut self) {
- // Get the toolstate for this rust revision.
- let rev = self.rust_git_commit_hash.as_ref().expect("failed to determine rust git hash");
- let toolstates = reqwest::get(TOOLSTATE).expect("failed to get toolstates");
- let toolstates = BufReader::new(toolstates);
- let toolstate = toolstates.lines()
- .find_map(|line| {
- let line = line.expect("failed to read toolstate lines");
- let mut pieces = line.splitn(2, '\t');
- let commit = pieces.next().expect("malformed toolstate line");
- if commit != rev {
- // Not the right commit.
- return None;
- }
- // Return the 2nd piece, the JSON.
- Some(pieces.next().expect("malformed toolstate line").to_owned())
- })
- .expect("failed to find toolstate for rust commit");
- let toolstate: HashMap<String, String> =
- serde_json::from_str(&toolstate).expect("toolstate is malformed JSON");
- // Mark some tools as missing based on toolstate.
- if toolstate.get("miri").map(|s| &*s as &str) != Some("test-pass") {
- println!("Miri tests are not passing, removing component");
- self.miri_version = None;
- self.miri_git_commit_hash = None;
- }
- }
-
/// Hash all files, compute their signatures, and collect the hashes in `self.digests`.
fn digest_and_sign(&mut self) {
for file in t!(self.input.read_dir()).map(|e| t!(e).path()) {
diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py
index 4060b90..7cf3cc7 100755
--- a/src/tools/publish_toolstate.py
+++ b/src/tools/publish_toolstate.py
@@ -201,7 +201,9 @@
new = s.get(tool, old)
status[os] = new
maintainers = ' '.join('@'+name for name in MAINTAINERS[tool])
- if new > old: # comparing the strings, but they are ordered appropriately!
+ # comparing the strings, but they are ordered appropriately:
+ # "test-pass" > "test-fail" > "build-fail"
+ if new > old:
# things got fixed or at least the status quo improved
changed = True
message += '🎉 {} on {}: {} → {} (cc {}, @rust-lang/infra).\n' \
@@ -213,10 +215,17 @@
.format(tool, os, old, new)
message += '{} (cc {}, @rust-lang/infra).\n' \
.format(title, maintainers)
- # Most tools only create issues for build failures.
- # Other failures can be spurious.
- if new == 'build-fail' or (tool == 'miri' and new == 'test-fail'):
- create_issue_for_status = new
+ # See if we need to create an issue.
+ if tool == 'miri':
+ # Create issue if tests used to pass before. Don't open a *second*
+ # issue when we regress from "test-fail" to "build-fail".
+ if old == 'test-pass':
+ create_issue_for_status = new
+ else:
+ # Create issue if things no longer build.
+ # (No issue for mere test failures to avoid spurious issues.)
+ if new == 'build-fail':
+ create_issue_for_status = new
if create_issue_for_status is not None:
try: