diff --git a/src/ci/docker/asmjs/Dockerfile b/src/ci/docker/asmjs/Dockerfile
index 9eaffbf83eb4e..01d6fce34186a 100644
--- a/src/ci/docker/asmjs/Dockerfile
+++ b/src/ci/docker/asmjs/Dockerfile
@@ -37,3 +37,11 @@ ENV SCRIPT python2.7 ../x.py test --target $TARGETS \
src/libstd \
src/liballoc \
src/libcore
+
+# Debug assertions in rustc are largely covered by other builders, and LLVM
+# assertions cause this builder to slow down by quite a large amount and don't
+# buy us a huge amount over other builders (not sure if we've ever seen an
+# asmjs-specific backend assertion trip), so disable assertions for these
+# tests.
+ENV NO_LLVM_ASSERTIONS=1
+ENV NO_DEBUG_ASSERTIONS=1
diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs
index 4ced860948bee..c5247e134c86a 100644
--- a/src/libcore/pin.rs
+++ b/src/libcore/pin.rs
@@ -1,10 +1,10 @@
//! Types that pin data to its location in memory.
//!
-//! It is sometimes useful to have objects that are guaranteed to not move,
+//! It is sometimes useful to have objects that are guaranteed not to move,
//! in the sense that their placement in memory does not change, and can thus be relied upon.
//! A prime example of such a scenario would be building self-referential structs,
-//! since moving an object with pointers to itself will invalidate them,
-//! which could cause undefined behavior.
+//! as moving an object with pointers to itself will invalidate them, which could cause undefined
+//! behavior.
//!
//! A [`Pin
`] ensures that the pointee of any pointer type `P` has a stable location in memory,
//! meaning it cannot be moved elsewhere and its memory cannot be deallocated
@@ -15,9 +15,10 @@
//! moving the values they contain: you can move out of a `Box`, or you can use [`mem::swap`].
//! [`Pin`] wraps a pointer type `P`, so `Pin>` functions much like a regular `Box`:
//! when a `Pin>` gets dropped, so do its contents, and the memory gets deallocated.
-//! Similarily, `Pin<&mut T>` is a lot like `&mut T`. However, [`Pin`] does not let clients
+//! Similarly, `Pin<&mut T>` is a lot like `&mut T`. However, [`Pin
`] does not let clients
//! actually obtain a `Box` or `&mut T` to pinned data, which implies that you cannot use
//! operations such as [`mem::swap`]:
+//!
//! ```
//! use std::pin::Pin;
//! fn swap_pins(x: Pin<&mut T>, y: Pin<&mut T>) {
@@ -39,19 +40,19 @@
//! as a "`P`-style pointer" to a pinned `P::Target` -- so, a `Pin>` is
//! an owned pointer to a pinned `T`, and a `Pin>` is a reference-counted
//! pointer to a pinned `T`.
-//! For correctness, [`Pin`] relies on the [`Deref`] and [`DerefMut`] implementations
-//! to not move out of their `self` parameter, and to only ever return a pointer
-//! to pinned data when they are called on a pinned pointer.
+//! For correctness, [`Pin
`] relies on the implementations of [`Deref`] and
+//! [`DerefMut`] not to move out of their `self` parameter, and only ever to
+//! return a pointer to pinned data when they are called on a pinned pointer.
//!
//! # `Unpin`
//!
-//! However, these restrictions are usually not necessary. Many types are always freely
-//! movable, even when pinned, because they do not rely on having a stable address.
-//! This includes all the basic types (like `bool`, `i32`, references)
-//! as well as types consisting solely of these types.
-//! Types that do not care about pinning implement the [`Unpin`] auto-trait, which
-//! cancels the effect of [`Pin
`]. For `T: Unpin`, `Pin>` and `Box` function
-//! identically, as do `Pin<&mut T>` and `&mut T`.
+//! Many types are always freely movable, even when pinned, because they do not
+//! rely on having a stable address. This includes all the basic types (like
+//! `bool`, `i32`, and references) as well as types consisting solely of these
+//! types. Types that do not care about pinning implement the [`Unpin`]
+//! auto-trait, which cancels the effect of [`Pin`]. For `T: Unpin`,
+//! `Pin>` and `Box` function identically, as do `Pin<&mut T>` and
+//! `&mut T`.
//!
//! Note that pinning and `Unpin` only affect the pointed-to type `P::Target`, not the pointer
//! type `P` itself that got wrapped in `Pin`. For example, whether or not `Box` is
@@ -65,11 +66,11 @@
//! use std::marker::PhantomPinned;
//! use std::ptr::NonNull;
//!
-//! // This is a self-referential struct since the slice field points to the data field.
+//! // This is a self-referential struct because the slice field points to the data field.
//! // We cannot inform the compiler about that with a normal reference,
-//! // since this pattern cannot be described with the usual borrowing rules.
-//! // Instead we use a raw pointer, though one which is known to not be null,
-//! // since we know it's pointing at the string.
+//! // as this pattern cannot be described with the usual borrowing rules.
+//! // Instead we use a raw pointer, though one which is known not to be null,
+//! // as we know it's pointing at the string.
//! struct Unmovable {
//! data: String,
//! slice: NonNull,
@@ -146,7 +147,7 @@
//! section needs to function correctly.
//!
//! Notice that this guarantee does *not* mean that memory does not leak! It is still
-//! completely okay not to ever call `drop` on a pinned element (e.g., you can still
+//! completely okay not ever to call `drop` on a pinned element (e.g., you can still
//! call [`mem::forget`] on a `Pin>`). In the example of the doubly-linked
//! list, that element would just stay in the list. However you may not free or reuse the storage
//! *without calling `drop`*.
@@ -192,7 +193,7 @@
//! `Unpin`. This is the default, but `Unpin` is a safe trait, so as the author of
//! the wrapper it is your responsibility *not* to add something like
//! `impl Unpin for Wrapper`. (Notice that adding a projection operation
-//! requires unsafe code, so the fact that `Unpin` is a safe trait does not break
+//! requires unsafe code, so the fact that `Unpin` is a safe trait does not break
//! the principle that you only have to worry about any of this if you use `unsafe`.)
//! 2. The destructor of the wrapper must not move structural fields out of its argument. This
//! is the exact point that was raised in the [previous section][drop-impl]: `drop` takes
diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs
index b4615aeb0db15..e324abd8e2f32 100644
--- a/src/librustc/mir/interpret/error.rs
+++ b/src/librustc/mir/interpret/error.rs
@@ -179,10 +179,15 @@ pub fn struct_error<'a, 'gcx, 'tcx>(
struct_span_err!(tcx.sess, tcx.span, E0080, "{}", msg)
}
+/// Packages the kind of error we got from the const code interpreter
+/// up with a Rust-level backtrace of where the error occured.
+/// Thsese should always be constructed by calling `.into()` on
+/// a `InterpError`. In `librustc_mir::interpret`, we have the `err!`
+/// macro for this
#[derive(Debug, Clone)]
pub struct EvalError<'tcx> {
pub kind: InterpError<'tcx, u64>,
- pub backtrace: Option>,
+ backtrace: Option>,
}
impl<'tcx> EvalError<'tcx> {
diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/move_errors.rs
index f892c1597057b..c421839513c01 100644
--- a/src/librustc_mir/borrow_check/move_errors.rs
+++ b/src/librustc_mir/borrow_check/move_errors.rs
@@ -503,32 +503,12 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
move_from,
..
} => {
- let try_remove_deref = match move_from {
- Place::Projection(box Projection {
- elem: ProjectionElem::Deref,
- ..
- }) => true,
- _ => false,
- };
- if try_remove_deref && snippet.starts_with('*') {
- // The snippet doesn't start with `*` in (e.g.) index
- // expressions `a[b]`, which roughly desugar to
- // `*Index::index(&a, b)` or
- // `*IndexMut::index_mut(&mut a, b)`.
- err.span_suggestion(
- span,
- "consider removing the `*`",
- snippet[1..].to_owned(),
- Applicability::Unspecified,
- );
- } else {
- err.span_suggestion(
- span,
- "consider borrowing here",
- format!("&{}", snippet),
- Applicability::Unspecified,
- );
- }
+ err.span_suggestion(
+ span,
+ "consider borrowing here",
+ format!("&{}", snippet),
+ Applicability::Unspecified,
+ );
if binds_to.is_empty() {
let place_ty = move_from.ty(self.mir, self.infcx.tcx).ty;
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index fac9665d968e2..a3297666113d4 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -663,6 +663,23 @@ where
Ok(())
}
+ /// Write an `Immediate` to memory.
+ #[inline(always)]
+ pub fn write_immediate_to_mplace(
+ &mut self,
+ src: Immediate,
+ dest: MPlaceTy<'tcx, M::PointerTag>,
+ ) -> EvalResult<'tcx> {
+ self.write_immediate_to_mplace_no_validate(src, dest)?;
+
+ if M::enforce_validity(self) {
+ // Data got changed, better make sure it matches the type!
+ self.validate_operand(dest.into(), vec![], None, /*const_mode*/ false)?;
+ }
+
+ Ok(())
+ }
+
/// Write an immediate to a place.
/// If you use this you are responsible for validating that things got copied at the
/// right type.
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index dbaa4e557c66f..0d389b31f9075 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -17,8 +17,7 @@ use syntax_pos::{Span, DUMMY_SP};
use rustc::ty::subst::InternalSubsts;
use rustc_data_structures::indexed_vec::IndexVec;
use rustc::ty::layout::{
- LayoutOf, TyLayout, LayoutError,
- HasTyCtxt, TargetDataLayout, HasDataLayout,
+ LayoutOf, TyLayout, LayoutError, HasTyCtxt, TargetDataLayout, HasDataLayout, Size,
};
use crate::interpret::{
@@ -333,6 +332,12 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
this.ecx.operand_field(eval, field.index() as u64)
})?;
},
+ ProjectionElem::Deref => {
+ trace!("processing deref");
+ eval = self.use_ecx(source_info, |this| {
+ this.ecx.deref_operand(eval)
+ })?.into();
+ }
// We could get more projections by using e.g., `operand_projection`,
// but we do not even have the stack frame set up properly so
// an `Index` projection would throw us off-track.
@@ -363,8 +368,12 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
Rvalue::Use(ref op) => {
self.eval_operand(op, source_info)
},
+ Rvalue::Ref(_, _, ref place) => {
+ let src = self.eval_place(place, source_info)?;
+ let mplace = src.try_as_mplace().ok()?;
+ Some(ImmTy::from_scalar(mplace.ptr.into(), place_layout).into())
+ },
Rvalue::Repeat(..) |
- Rvalue::Ref(..) |
Rvalue::Aggregate(..) |
Rvalue::NullaryOp(NullOp::Box, _) |
Rvalue::Discriminant(..) => None,
@@ -376,10 +385,30 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
this.ecx.cast(op, kind, dest.into())?;
Ok(dest.into())
})
- }
+ },
+ Rvalue::Len(ref place) => {
+ let place = self.eval_place(&place, source_info)?;
+ let mplace = place.try_as_mplace().ok()?;
+
+ if let ty::Slice(_) = mplace.layout.ty.sty {
+ let len = mplace.meta.unwrap().to_usize(&self.ecx).unwrap();
- // FIXME(oli-obk): evaluate static/constant slice lengths
- Rvalue::Len(_) => None,
+ Some(ImmTy {
+ imm: Immediate::Scalar(
+ Scalar::from_uint(
+ len,
+ Size::from_bits(
+ self.tcx.sess.target.usize_ty.bit_width().unwrap() as u64
+ )
+ ).into(),
+ ),
+ layout: self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).ok()?,
+ }.into())
+ } else {
+ trace!("not slice: {:?}", mplace.layout.ty.sty);
+ None
+ }
+ },
Rvalue::NullaryOp(NullOp::SizeOf, ty) => {
type_size_of(self.tcx, self.param_env, ty).and_then(|n| Some(
ImmTy {
@@ -525,12 +554,10 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
source_info: SourceInfo,
) {
trace!("attepting to replace {:?} with {:?}", rval, value);
- self.ecx.validate_operand(
- value,
- vec![],
- None,
- true,
- ).expect("value should already be a valid const");
+ if let Err(e) = self.ecx.validate_operand(value, vec![], None, true) {
+ trace!("validation error, attempt failed: {:?}", e);
+ return;
+ }
// FIXME> figure out what tho do when try_read_immediate fails
let imm = self.use_ecx(source_info, |this| {
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 03d16feb483a9..a717ef20a8444 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -2768,7 +2768,10 @@ impl Clean for hir::Ty {
};
let length = match cx.tcx.const_eval(param_env.and(cid)) {
Ok(length) => print_const(cx, length),
- Err(_) => "_".to_string(),
+ Err(_) => cx.sess()
+ .source_map()
+ .span_to_snippet(cx.tcx.def_span(def_id))
+ .unwrap_or_else(|_| "_".to_string()),
};
Array(box ty.clean(cx), length)
},
diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml
index 9abad83fdb039..30e23f1007f20 100644
--- a/src/libstd/Cargo.toml
+++ b/src/libstd/Cargo.toml
@@ -87,3 +87,5 @@ std_detect_dlsym_getauxval = []
[package.metadata.fortanix-sgx]
# Maximum possible number of threads when testing
threads = 125
+# Maximum heap size
+heap_size = 0x8000000
diff --git a/src/test/mir-opt/const_prop/ref_deref.rs b/src/test/mir-opt/const_prop/ref_deref.rs
new file mode 100644
index 0000000000000..2d04822c0e789
--- /dev/null
+++ b/src/test/mir-opt/const_prop/ref_deref.rs
@@ -0,0 +1,21 @@
+fn main() {
+ *(&4);
+}
+
+// END RUST SOURCE
+// START rustc.main.ConstProp.before.mir
+// bb0: {
+// ...
+// _2 = &(promoted[0]: i32);
+// _1 = (*_2);
+// ...
+//}
+// END rustc.main.ConstProp.before.mir
+// START rustc.main.ConstProp.after.mir
+// bb0: {
+// ...
+// _2 = const Scalar(AllocId(0).0x0) : &i32;
+// _1 = const 4i32;
+// ...
+// }
+// END rustc.main.ConstProp.after.mir
diff --git a/src/test/mir-opt/const_prop/reify_fn_ptr.rs b/src/test/mir-opt/const_prop/reify_fn_ptr.rs
new file mode 100644
index 0000000000000..809eb19ade899
--- /dev/null
+++ b/src/test/mir-opt/const_prop/reify_fn_ptr.rs
@@ -0,0 +1,25 @@
+fn main() {
+ let _ = main as usize as *const fn();
+}
+
+// END RUST SOURCE
+// START rustc.main.ConstProp.before.mir
+// bb0: {
+// ...
+// _3 = const main as fn() (Pointer(ReifyFnPointer));
+// _2 = move _3 as usize (Misc);
+// ...
+// _1 = move _2 as *const fn() (Misc);
+// ...
+// }
+// END rustc.main.ConstProp.before.mir
+// START rustc.main.ConstProp.after.mir
+// bb0: {
+// ...
+// _3 = const Scalar(AllocId(1).0x0) : fn();
+// _2 = move _3 as usize (Misc);
+// ...
+// _1 = const Scalar(AllocId(1).0x0) : *const fn();
+// ...
+// }
+// END rustc.main.ConstProp.after.mir
diff --git a/src/test/mir-opt/const_prop/slice_len.rs b/src/test/mir-opt/const_prop/slice_len.rs
index 3435ca07f4cd8..5babeb195a826 100644
--- a/src/test/mir-opt/const_prop/slice_len.rs
+++ b/src/test/mir-opt/const_prop/slice_len.rs
@@ -1,22 +1,22 @@
-fn test() -> &'static [u32] {
- &[1, 2]
-}
-
fn main() {
- let x = test()[0];
+ (&[1u32, 2, 3] as &[u32])[1];
}
// END RUST SOURCE
// START rustc.main.ConstProp.before.mir
-// bb1: {
+// bb0: {
// ...
-// _3 = const 0usize;
-// _4 = Len((*_2));
-// _5 = Lt(_3, _4);
-// assert(move _5, "index out of bounds: the len is move _4 but the index is _3") -> bb2;
+// _4 = &(promoted[0]: [u32; 3]);
+// _3 = _4;
+// _2 = move _3 as &[u32] (Pointer(Unsize));
+// ...
+// _6 = const 1usize;
+// _7 = Len((*_2));
+// _8 = Lt(_6, _7);
+// assert(move _8, "index out of bounds: the len is move _7 but the index is _6") -> bb1;
// }
-// bb2: {
-// _1 = (*_2)[_3];
+// bb1: {
+// _1 = (*_2)[_6];
// ...
// return;
// }
@@ -24,13 +24,17 @@ fn main() {
// START rustc.main.ConstProp.after.mir
// bb0: {
// ...
-// _3 = const 0usize;
-// _4 = Len((*_2));
-// _5 = Lt(_3, _4);
-// assert(move _5, "index out of bounds: the len is move _4 but the index is _3") -> bb2;
+// _4 = const Scalar(AllocId(0).0x0) : &[u32; 3];
+// _3 = const Scalar(AllocId(0).0x0) : &[u32; 3];
+// _2 = move _3 as &[u32] (Pointer(Unsize));
+// ...
+// _6 = const 1usize;
+// _7 = const 3usize;
+// _8 = const true;
+// assert(const true, "index out of bounds: the len is move _7 but the index is _6") -> bb1;
// }
-// bb2: {
-// _1 = (*_2)[_3];
+// bb1: {
+// _1 = (*_2)[_6];
// ...
// return;
// }
diff --git a/src/test/rustdoc/const-generics/const-generic-slice.rs b/src/test/rustdoc/const-generics/const-generic-slice.rs
new file mode 100644
index 0000000000000..60d96770f7eae
--- /dev/null
+++ b/src/test/rustdoc/const-generics/const-generic-slice.rs
@@ -0,0 +1,12 @@
+#![crate_name = "foo"]
+#![feature(const_generics)]
+
+pub trait Array {
+ type Item;
+}
+
+// @has foo/trait.Array.html
+// @has - '//h3[@class="impl"]' 'impl Array for [T; N]'
+impl Array for [T; N] {
+ type Item = T;
+}
diff --git a/src/test/ui/access-mode-in-closures.stderr b/src/test/ui/access-mode-in-closures.stderr
index 424d7ebb37444..349e3f4a836a0 100644
--- a/src/test/ui/access-mode-in-closures.stderr
+++ b/src/test/ui/access-mode-in-closures.stderr
@@ -6,7 +6,7 @@ LL | match *s { S(v) => v }
| | |
| | data moved here
| | move occurs because `v` has type `std::vec::Vec`, which does not implement the `Copy` trait
- | help: consider removing the `*`: `s`
+ | help: consider borrowing here: `&*s`
error: aborting due to previous error
diff --git a/src/test/ui/borrowck/borrowck-issue-2657-2.stderr b/src/test/ui/borrowck/borrowck-issue-2657-2.stderr
index 908b2c0ff5ee8..5880a1abb818c 100644
--- a/src/test/ui/borrowck/borrowck-issue-2657-2.stderr
+++ b/src/test/ui/borrowck/borrowck-issue-2657-2.stderr
@@ -5,7 +5,7 @@ LL | let _b = *y;
| ^^
| |
| move occurs because `*y` has type `std::boxed::Box`, which does not implement the `Copy` trait
- | help: consider removing the `*`: `y`
+ | help: consider borrowing here: `&*y`
error: aborting due to previous error
diff --git a/src/test/ui/borrowck/borrowck-move-error-with-note.stderr b/src/test/ui/borrowck/borrowck-move-error-with-note.stderr
index 13d3faab6508a..d56b9f562c932 100644
--- a/src/test/ui/borrowck/borrowck-move-error-with-note.stderr
+++ b/src/test/ui/borrowck/borrowck-move-error-with-note.stderr
@@ -2,7 +2,7 @@ error[E0507]: cannot move out of `f.0` which is behind a shared reference
--> $DIR/borrowck-move-error-with-note.rs:11:11
|
LL | match *f {
- | ^^ help: consider removing the `*`: `f`
+ | ^^ help: consider borrowing here: `&*f`
LL | Foo::Foo1(num1,
| ---- data moved here
LL | num2) => (),
diff --git a/src/test/ui/borrowck/borrowck-move-from-unsafe-ptr.stderr b/src/test/ui/borrowck/borrowck-move-from-unsafe-ptr.stderr
index 6c806e0896b37..7dfae33920e1c 100644
--- a/src/test/ui/borrowck/borrowck-move-from-unsafe-ptr.stderr
+++ b/src/test/ui/borrowck/borrowck-move-from-unsafe-ptr.stderr
@@ -5,7 +5,7 @@ LL | let y = *x;
| ^^
| |
| move occurs because `*x` has type `std::boxed::Box`, which does not implement the `Copy` trait
- | help: consider removing the `*`: `x`
+ | help: consider borrowing here: `&*x`
error: aborting due to previous error
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-overloaded-deref.stderr b/src/test/ui/borrowck/borrowck-move-out-of-overloaded-deref.stderr
index da3e5c54b75f7..1501644fac758 100644
--- a/src/test/ui/borrowck/borrowck-move-out-of-overloaded-deref.stderr
+++ b/src/test/ui/borrowck/borrowck-move-out-of-overloaded-deref.stderr
@@ -5,7 +5,7 @@ LL | let _x = *Rc::new("hi".to_string());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| move occurs because value has type `std::string::String`, which does not implement the `Copy` trait
- | help: consider removing the `*`: `Rc::new("hi".to_string())`
+ | help: consider borrowing here: `&*Rc::new("hi".to_string())`
error: aborting due to previous error
diff --git a/src/test/ui/borrowck/issue-54597-reject-move-out-of-borrow-via-pat.stderr b/src/test/ui/borrowck/issue-54597-reject-move-out-of-borrow-via-pat.stderr
index 6ba801b9714bf..78d44f3206199 100644
--- a/src/test/ui/borrowck/issue-54597-reject-move-out-of-borrow-via-pat.stderr
+++ b/src/test/ui/borrowck/issue-54597-reject-move-out-of-borrow-via-pat.stderr
@@ -5,7 +5,7 @@ LL | *array
| ^^^^^^
| |
| move occurs because `*array` has type `std::vec::Vec`, which does not implement the `Copy` trait
- | help: consider removing the `*`: `array`
+ | help: consider borrowing here: `&*array`
error: aborting due to previous error
diff --git a/src/test/ui/consts/const-eval/promoted_errors.stderr b/src/test/ui/consts/const-eval/promoted_errors.stderr
index c9d5ede61ade4..c9f3a7659f9cd 100644
--- a/src/test/ui/consts/const-eval/promoted_errors.stderr
+++ b/src/test/ui/consts/const-eval/promoted_errors.stderr
@@ -16,6 +16,12 @@ warning: attempt to divide by zero
LL | println!("{}", 1/(1-1));
| ^^^^^^^
+warning: this expression will panic at runtime
+ --> $DIR/promoted_errors.rs:9:20
+ |
+LL | println!("{}", 1/(1-1));
+ | ^^^^^^^ attempt to divide by zero
+
warning: attempt to divide by zero
--> $DIR/promoted_errors.rs:11:14
|
@@ -34,6 +40,12 @@ warning: attempt to divide by zero
LL | println!("{}", 1/(false as u32));
| ^^^^^^^^^^^^^^^^
+warning: this expression will panic at runtime
+ --> $DIR/promoted_errors.rs:14:20
+ |
+LL | println!("{}", 1/(false as u32));
+ | ^^^^^^^^^^^^^^^^ attempt to divide by zero
+
warning: attempt to divide by zero
--> $DIR/promoted_errors.rs:16:14
|
diff --git a/src/test/ui/issues/issue-20801.stderr b/src/test/ui/issues/issue-20801.stderr
index 1bbd874a44802..d276231dc0c96 100644
--- a/src/test/ui/issues/issue-20801.stderr
+++ b/src/test/ui/issues/issue-20801.stderr
@@ -5,7 +5,7 @@ LL | let a = unsafe { *mut_ref() };
| ^^^^^^^^^^
| |
| move occurs because value has type `T`, which does not implement the `Copy` trait
- | help: consider removing the `*`: `mut_ref()`
+ | help: consider borrowing here: `&*mut_ref()`
error[E0507]: cannot move out of a shared reference
--> $DIR/issue-20801.rs:29:22
@@ -14,7 +14,7 @@ LL | let b = unsafe { *imm_ref() };
| ^^^^^^^^^^
| |
| move occurs because value has type `T`, which does not implement the `Copy` trait
- | help: consider removing the `*`: `imm_ref()`
+ | help: consider borrowing here: `&*imm_ref()`
error[E0507]: cannot move out of a raw pointer
--> $DIR/issue-20801.rs:32:22
@@ -23,7 +23,7 @@ LL | let c = unsafe { *mut_ptr() };
| ^^^^^^^^^^
| |
| move occurs because value has type `T`, which does not implement the `Copy` trait
- | help: consider removing the `*`: `mut_ptr()`
+ | help: consider borrowing here: `&*mut_ptr()`
error[E0507]: cannot move out of a raw pointer
--> $DIR/issue-20801.rs:35:22
@@ -32,7 +32,7 @@ LL | let d = unsafe { *const_ptr() };
| ^^^^^^^^^^^^
| |
| move occurs because value has type `T`, which does not implement the `Copy` trait
- | help: consider removing the `*`: `const_ptr()`
+ | help: consider borrowing here: `&*const_ptr()`
error: aborting due to 4 previous errors
diff --git a/src/test/ui/nll/cannot-move-block-spans.stderr b/src/test/ui/nll/cannot-move-block-spans.stderr
index 4a9635b060db3..7db5d731acd17 100644
--- a/src/test/ui/nll/cannot-move-block-spans.stderr
+++ b/src/test/ui/nll/cannot-move-block-spans.stderr
@@ -5,7 +5,7 @@ LL | let x = { *r };
| ^^
| |
| move occurs because `*r` has type `std::string::String`, which does not implement the `Copy` trait
- | help: consider removing the `*`: `r`
+ | help: consider borrowing here: `&*r`
error[E0507]: cannot move out of `*r` which is behind a shared reference
--> $DIR/cannot-move-block-spans.rs:6:22
@@ -14,7 +14,7 @@ LL | let y = unsafe { *r };
| ^^
| |
| move occurs because `*r` has type `std::string::String`, which does not implement the `Copy` trait
- | help: consider removing the `*`: `r`
+ | help: consider borrowing here: `&*r`
error[E0507]: cannot move out of `*r` which is behind a shared reference
--> $DIR/cannot-move-block-spans.rs:7:26
@@ -23,7 +23,7 @@ LL | let z = loop { break *r; };
| ^^
| |
| move occurs because `*r` has type `std::string::String`, which does not implement the `Copy` trait
- | help: consider removing the `*`: `r`
+ | help: consider borrowing here: `&*r`
error[E0508]: cannot move out of type `[std::string::String; 2]`, a non-copy array
--> $DIR/cannot-move-block-spans.rs:11:15
@@ -62,7 +62,7 @@ LL | let x = { let mut u = 0; u += 1; *r };
| ^^
| |
| move occurs because `*r` has type `std::string::String`, which does not implement the `Copy` trait
- | help: consider removing the `*`: `r`
+ | help: consider borrowing here: `&*r`
error[E0507]: cannot move out of `*r` which is behind a shared reference
--> $DIR/cannot-move-block-spans.rs:18:45
@@ -71,7 +71,7 @@ LL | let y = unsafe { let mut u = 0; u += 1; *r };
| ^^
| |
| move occurs because `*r` has type `std::string::String`, which does not implement the `Copy` trait
- | help: consider removing the `*`: `r`
+ | help: consider borrowing here: `&*r`
error[E0507]: cannot move out of `*r` which is behind a shared reference
--> $DIR/cannot-move-block-spans.rs:19:49
@@ -80,7 +80,7 @@ LL | let z = loop { let mut u = 0; u += 1; break *r; u += 2; };
| ^^
| |
| move occurs because `*r` has type `std::string::String`, which does not implement the `Copy` trait
- | help: consider removing the `*`: `r`
+ | help: consider borrowing here: `&*r`
error: aborting due to 9 previous errors
diff --git a/src/test/ui/nll/move-errors.stderr b/src/test/ui/nll/move-errors.stderr
index 086f7bcdc4f27..7139617a97a4f 100644
--- a/src/test/ui/nll/move-errors.stderr
+++ b/src/test/ui/nll/move-errors.stderr
@@ -5,7 +5,7 @@ LL | let b = *a;
| ^^
| |
| move occurs because `*a` has type `A`, which does not implement the `Copy` trait
- | help: consider removing the `*`: `a`
+ | help: consider borrowing here: `&*a`
error[E0508]: cannot move out of type `[A; 1]`, a non-copy array
--> $DIR/move-errors.rs:12:13
@@ -24,7 +24,7 @@ LL | let s = **r;
| ^^^
| |
| move occurs because `**r` has type `A`, which does not implement the `Copy` trait
- | help: consider removing the `*`: `*r`
+ | help: consider borrowing here: `&**r`
error[E0507]: cannot move out of an `Rc`
--> $DIR/move-errors.rs:27:13
@@ -33,7 +33,7 @@ LL | let s = *r;
| ^^
| |
| move occurs because value has type `A`, which does not implement the `Copy` trait
- | help: consider removing the `*`: `r`
+ | help: consider borrowing here: `&*r`
error[E0508]: cannot move out of type `[A; 1]`, a non-copy array
--> $DIR/move-errors.rs:32:13
@@ -49,7 +49,7 @@ error[E0507]: cannot move out of `a.0` which is behind a shared reference
--> $DIR/move-errors.rs:38:16
|
LL | let A(s) = *a;
- | - ^^ help: consider removing the `*`: `a`
+ | - ^^ help: consider borrowing here: `&*a`
| |
| data moved here
| move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
@@ -148,7 +148,7 @@ error[E0507]: cannot move out of `x.0` which is behind a shared reference
--> $DIR/move-errors.rs:110:11
|
LL | match *x {
- | ^^ help: consider removing the `*`: `x`
+ | ^^ help: consider borrowing here: `&*x`
LL |
LL | Ok(s) | Err(s) => (),
| -
diff --git a/src/test/ui/std-uncopyable-atomics.stderr b/src/test/ui/std-uncopyable-atomics.stderr
index 189a27db382cd..9db9fcf40f82c 100644
--- a/src/test/ui/std-uncopyable-atomics.stderr
+++ b/src/test/ui/std-uncopyable-atomics.stderr
@@ -5,7 +5,7 @@ LL | let x = *&x;
| ^^^
| |
| move occurs because value has type `std::sync::atomic::AtomicBool`, which does not implement the `Copy` trait
- | help: consider removing the `*`: `&x`
+ | help: consider borrowing here: `&*&x`
error[E0507]: cannot move out of a shared reference
--> $DIR/std-uncopyable-atomics.rs:11:13
@@ -14,7 +14,7 @@ LL | let x = *&x;
| ^^^
| |
| move occurs because value has type `std::sync::atomic::AtomicIsize`, which does not implement the `Copy` trait
- | help: consider removing the `*`: `&x`
+ | help: consider borrowing here: `&*&x`
error[E0507]: cannot move out of a shared reference
--> $DIR/std-uncopyable-atomics.rs:13:13
@@ -23,7 +23,7 @@ LL | let x = *&x;
| ^^^
| |
| move occurs because value has type `std::sync::atomic::AtomicUsize`, which does not implement the `Copy` trait
- | help: consider removing the `*`: `&x`
+ | help: consider borrowing here: `&*&x`
error[E0507]: cannot move out of a shared reference
--> $DIR/std-uncopyable-atomics.rs:15:13
@@ -32,7 +32,7 @@ LL | let x = *&x;
| ^^^
| |
| move occurs because value has type `std::sync::atomic::AtomicPtr`, which does not implement the `Copy` trait
- | help: consider removing the `*`: `&x`
+ | help: consider borrowing here: `&*&x`
error: aborting due to 4 previous errors
diff --git a/src/test/ui/suggestions/dont-suggest-ref/simple.rs b/src/test/ui/suggestions/dont-suggest-ref/simple.rs
index 31ab1a6639acc..69b303a66237e 100644
--- a/src/test/ui/suggestions/dont-suggest-ref/simple.rs
+++ b/src/test/ui/suggestions/dont-suggest-ref/simple.rs
@@ -37,26 +37,26 @@ pub fn main() {
let X(_t) = *s;
//~^ ERROR cannot move
- //~| HELP consider removing the `*`
+ //~| HELP consider borrowing here
//~| SUGGESTION s
if let Either::One(_t) = *r { }
//~^ ERROR cannot move
- //~| HELP consider removing the `*`
+ //~| HELP consider borrowing here
//~| SUGGESTION r
while let Either::One(_t) = *r { }
//~^ ERROR cannot move
- //~| HELP consider removing the `*`
+ //~| HELP consider borrowing here
//~| SUGGESTION r
match *r {
//~^ ERROR cannot move
- //~| HELP consider removing the `*`
+ //~| HELP consider borrowing here
//~| SUGGESTION r
Either::One(_t)
| Either::Two(_t) => (),
}
match *r {
//~^ ERROR cannot move
- //~| HELP consider removing the `*`
+ //~| HELP consider borrowing here
//~| SUGGESTION r
Either::One(_t) => (),
Either::Two(ref _t) => (),
@@ -65,26 +65,26 @@ pub fn main() {
let X(_t) = *sm;
//~^ ERROR cannot move
- //~| HELP consider removing the `*`
+ //~| HELP consider borrowing here
//~| SUGGESTION sm
if let Either::One(_t) = *rm { }
//~^ ERROR cannot move
- //~| HELP consider removing the `*`
+ //~| HELP consider borrowing here
//~| SUGGESTION rm
while let Either::One(_t) = *rm { }
//~^ ERROR cannot move
- //~| HELP consider removing the `*`
+ //~| HELP consider borrowing here
//~| SUGGESTION rm
match *rm {
//~^ ERROR cannot move
- //~| HELP consider removing the `*`
+ //~| HELP consider borrowing here
//~| SUGGESTION rm
Either::One(_t)
| Either::Two(_t) => (),
}
match *rm {
//~^ ERROR cannot move
- //~| HELP consider removing the `*`
+ //~| HELP consider borrowing here
//~| SUGGESTION rm
Either::One(_t) => (),
Either::Two(ref _t) => (),
@@ -92,7 +92,7 @@ pub fn main() {
}
match *rm {
//~^ ERROR cannot move
- //~| HELP consider removing the `*`
+ //~| HELP consider borrowing here
//~| SUGGESTION rm
Either::One(_t) => (),
Either::Two(ref mut _t) => (),
diff --git a/src/test/ui/suggestions/dont-suggest-ref/simple.stderr b/src/test/ui/suggestions/dont-suggest-ref/simple.stderr
index bde3afa3840a2..cb3ce5991aeee 100644
--- a/src/test/ui/suggestions/dont-suggest-ref/simple.stderr
+++ b/src/test/ui/suggestions/dont-suggest-ref/simple.stderr
@@ -2,7 +2,7 @@ error[E0507]: cannot move out of `s.0` which is behind a shared reference
--> $DIR/simple.rs:38:17
|
LL | let X(_t) = *s;
- | -- ^^ help: consider removing the `*`: `s`
+ | -- ^^ help: consider borrowing here: `&*s`
| |
| data moved here
| move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
@@ -11,7 +11,7 @@ error[E0507]: cannot move out of `r.0` which is behind a shared reference
--> $DIR/simple.rs:42:30
|
LL | if let Either::One(_t) = *r { }
- | -- ^^ help: consider removing the `*`: `r`
+ | -- ^^ help: consider borrowing here: `&*r`
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
@@ -20,7 +20,7 @@ error[E0507]: cannot move out of `r.0` which is behind a shared reference
--> $DIR/simple.rs:46:33
|
LL | while let Either::One(_t) = *r { }
- | -- ^^ help: consider removing the `*`: `r`
+ | -- ^^ help: consider borrowing here: `&*r`
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
@@ -29,7 +29,7 @@ error[E0507]: cannot move out of `r.0` which is behind a shared reference
--> $DIR/simple.rs:50:11
|
LL | match *r {
- | ^^ help: consider removing the `*`: `r`
+ | ^^ help: consider borrowing here: `&*r`
...
LL | Either::One(_t)
| --
@@ -41,7 +41,7 @@ error[E0507]: cannot move out of `r.0` which is behind a shared reference
--> $DIR/simple.rs:57:11
|
LL | match *r {
- | ^^ help: consider removing the `*`: `r`
+ | ^^ help: consider borrowing here: `&*r`
...
LL | Either::One(_t) => (),
| --
@@ -53,7 +53,7 @@ error[E0507]: cannot move out of `sm.0` which is behind a mutable reference
--> $DIR/simple.rs:66:17
|
LL | let X(_t) = *sm;
- | -- ^^^ help: consider removing the `*`: `sm`
+ | -- ^^^ help: consider borrowing here: `&*sm`
| |
| data moved here
| move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
@@ -62,7 +62,7 @@ error[E0507]: cannot move out of `rm.0` which is behind a mutable reference
--> $DIR/simple.rs:70:30
|
LL | if let Either::One(_t) = *rm { }
- | -- ^^^ help: consider removing the `*`: `rm`
+ | -- ^^^ help: consider borrowing here: `&*rm`
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
@@ -71,7 +71,7 @@ error[E0507]: cannot move out of `rm.0` which is behind a mutable reference
--> $DIR/simple.rs:74:33
|
LL | while let Either::One(_t) = *rm { }
- | -- ^^^ help: consider removing the `*`: `rm`
+ | -- ^^^ help: consider borrowing here: `&*rm`
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
@@ -80,7 +80,7 @@ error[E0507]: cannot move out of `rm.0` which is behind a mutable reference
--> $DIR/simple.rs:78:11
|
LL | match *rm {
- | ^^^ help: consider removing the `*`: `rm`
+ | ^^^ help: consider borrowing here: `&*rm`
...
LL | Either::One(_t)
| --
@@ -92,7 +92,7 @@ error[E0507]: cannot move out of `rm.0` which is behind a mutable reference
--> $DIR/simple.rs:85:11
|
LL | match *rm {
- | ^^^ help: consider removing the `*`: `rm`
+ | ^^^ help: consider borrowing here: `&*rm`
...
LL | Either::One(_t) => (),
| --
@@ -104,7 +104,7 @@ error[E0507]: cannot move out of `rm.0` which is behind a mutable reference
--> $DIR/simple.rs:93:11
|
LL | match *rm {
- | ^^^ help: consider removing the `*`: `rm`
+ | ^^^ help: consider borrowing here: `&*rm`
...
LL | Either::One(_t) => (),
| --