Skip to content

Rollup of 9 pull requests #61201

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
May 26, 2019
Merged
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
274b7e4
Suggest borrowing for loop head on move error
estebank May 25, 2019
fd19989
Fix spelling in release notes
aristocles-deploy May 25, 2019
72145ea
MaybeUninit doctest: remove unnecessary type ascription
RalfJung May 25, 2019
9d82826
add test checking that Vec push/pop does not invalidate pointers
RalfJung May 25, 2019
428ab7e
shadow as_ptr as as_mut_ptr in Vec to avoid going through Deref
RalfJung May 25, 2019
a5e9d82
Auto-derive Encode and Decode implementations
fabric-and-ink May 25, 2019
9bfbbd2
Add additional trace statements to the const propagator
wesleywiser May 25, 2019
9765418
Tweak `self` arg not as first argument of a method diagnostic
estebank May 23, 2019
d1364d5
Move some methods to `diagnostics.rs` away from `parser.rs`
estebank May 23, 2019
4e68ddc
review comments: move back some methods and clean up wording
estebank May 23, 2019
a15df94
Turn ICE on type arguments on variables into an error
oli-obk May 25, 2019
e6aa4b8
Add comment to explain why we change the layout for Projection
spastorino May 25, 2019
24cc368
Rollup merge of #61087 - estebank:parsepalooza, r=Centril
Centril May 26, 2019
f185ee5
Rollup merge of #61114 - RalfJung:vec, r=Gankro
Centril May 26, 2019
b4a3d44
Rollup merge of #61144 - estebank:issue-61108, r=matthewjasper
Centril May 26, 2019
fadd738
Rollup merge of #61149 - vishalsodani:master, r=Centril
Centril May 26, 2019
7b8b23c
Rollup merge of #61161 - RalfJung:maybe-uninit, r=Centril
Centril May 26, 2019
f530f90
Rollup merge of #61173 - fabric-and-ink:minor-cleanup, r=varkor
Centril May 26, 2019
d8b828b
Rollup merge of #61184 - wesleywiser:const_prop_tracing, r=oli-obk
Centril May 26, 2019
6ae3c2b
Rollup merge of #61189 - oli-obk:turbofish_ice, r=varkor
Centril May 26, 2019
8d247e7
Rollup merge of #61193 - spastorino:add-comment, r=RalfJung
Centril May 26, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion RELEASES.md
Original file line number Diff line number Diff line change
@@ -157,7 +157,7 @@ Libraries
produce a warning if their returning type is unused.
- [The methods `checked_pow`, `saturating_pow`, `wrapping_pow`, and
`overflowing_pow` are now available for all numeric types.][57873] These are
equivalvent to methods such as `wrapping_add` for the `pow` operation.
equivalent to methods such as `wrapping_add` for the `pow` operation.


Stabilized APIs
21 changes: 21 additions & 0 deletions src/liballoc/tests/vec.rs
Original file line number Diff line number Diff line change
@@ -1152,3 +1152,24 @@ fn test_try_reserve_exact() {
}

}

#[test]
fn test_stable_push_pop() {
// Test that, if we reserved enough space, adding and removing elements does not
// invalidate references into the vector (such as `v0`). This test also
// runs in Miri, which would detect such problems.
let mut v = Vec::with_capacity(10);
v.push(13);

// laundering the lifetime -- we take care that `v` does not reallocate, so that's okay.
let v0 = unsafe { &*(&v[0] as *const _) };

// Now do a bunch of things and occasionally use `v0` again to assert it is still valid.
v.push(1);
v.push(2);
v.insert(1, 1);
assert_eq!(*v0, 13);
v.remove(1);
v.pop().unwrap();
assert_eq!(*v0, 13);
}
78 changes: 71 additions & 7 deletions src/liballoc/vec.rs
Original file line number Diff line number Diff line change
@@ -735,6 +735,75 @@ impl<T> Vec<T> {
self
}

/// Returns a raw pointer to the vector's buffer.
///
/// The caller must ensure that the vector outlives the pointer this
/// function returns, or else it will end up pointing to garbage.
/// Modifying the vector may cause its buffer to be reallocated,
/// which would also make any pointers to it invalid.
///
/// The caller must also ensure that the memory the pointer (non-transitively) points to
/// is never written to (except inside an `UnsafeCell`) using this pointer or any pointer
/// derived from it. If you need to mutate the contents of the slice, use [`as_mut_ptr`].
///
/// # Examples
///
/// ```
/// let x = vec![1, 2, 4];
/// let x_ptr = x.as_ptr();
///
/// unsafe {
/// for i in 0..x.len() {
/// assert_eq!(*x_ptr.add(i), 1 << i);
/// }
/// }
/// ```
///
/// [`as_mut_ptr`]: #method.as_mut_ptr
#[stable(feature = "vec_as_ptr", since = "1.37.0")]
#[inline]
pub fn as_ptr(&self) -> *const T {
// We shadow the slice method of the same name to avoid going through
// `deref`, which creates an intermediate reference.
let ptr = self.buf.ptr();
unsafe { assume(!ptr.is_null()); }
ptr
}

/// Returns an unsafe mutable pointer to the vector's buffer.
///
/// The caller must ensure that the vector outlives the pointer this
/// function returns, or else it will end up pointing to garbage.
/// Modifying the vector may cause its buffer to be reallocated,
/// which would also make any pointers to it invalid.
///
/// # Examples
///
/// ```
/// // Allocate vector big enough for 4 elements.
/// let size = 4;
/// let mut x: Vec<i32> = Vec::with_capacity(size);
/// let x_ptr = x.as_mut_ptr();
///
/// // Initialize elements via raw pointer writes, then set length.
/// unsafe {
/// for i in 0..size {
/// *x_ptr.add(i) = i as i32;
/// }
/// x.set_len(size);
/// }
/// assert_eq!(&*x, &[0,1,2,3]);
/// ```
#[stable(feature = "vec_as_ptr", since = "1.37.0")]
#[inline]
pub fn as_mut_ptr(&mut self) -> *mut T {
// We shadow the slice method of the same name to avoid going through
// `deref_mut`, which creates an intermediate reference.
let ptr = self.buf.ptr();
unsafe { assume(!ptr.is_null()); }
ptr
}

/// Forces the length of the vector to `new_len`.
///
/// This is a low-level operation that maintains none of the normal
@@ -1706,9 +1775,7 @@ impl<T> ops::Deref for Vec<T> {

fn deref(&self) -> &[T] {
unsafe {
let p = self.buf.ptr();
assume(!p.is_null());
slice::from_raw_parts(p, self.len)
slice::from_raw_parts(self.as_ptr(), self.len)
}
}
}
@@ -1717,9 +1784,7 @@ impl<T> ops::Deref for Vec<T> {
impl<T> ops::DerefMut for Vec<T> {
fn deref_mut(&mut self) -> &mut [T] {
unsafe {
let ptr = self.buf.ptr();
assume(!ptr.is_null());
slice::from_raw_parts_mut(ptr, self.len)
slice::from_raw_parts_mut(self.as_mut_ptr(), self.len)
}
}
}
@@ -1754,7 +1819,6 @@ impl<T> IntoIterator for Vec<T> {
fn into_iter(mut self) -> IntoIter<T> {
unsafe {
let begin = self.as_mut_ptr();
assume(!begin.is_null());
let end = if mem::size_of::<T>() == 0 {
arith_offset(begin as *const i8, self.len() as isize) as *const T
} else {
4 changes: 2 additions & 2 deletions src/libcore/mem.rs
Original file line number Diff line number Diff line change
@@ -982,7 +982,7 @@ impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
/// out.write(vec![1, 2, 3]);
/// }
///
/// let mut v: MaybeUninit<Vec<i32>> = MaybeUninit::uninit();
/// let mut v = MaybeUninit::uninit();
/// unsafe { make_vec(v.as_mut_ptr()); }
/// // Now we know `v` is initialized! This also makes sure the vector gets
/// // properly dropped.
@@ -1071,7 +1071,7 @@ impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
/// optimizations, potentially resulting in a larger size:
///
/// ```rust
/// # use std::mem::{MaybeUninit, size_of, align_of};
/// # use std::mem::{MaybeUninit, size_of};
/// assert_eq!(size_of::<Option<bool>>(), 1);
/// assert_eq!(size_of::<Option<MaybeUninit<bool>>>(), 2);
/// ```
26 changes: 1 addition & 25 deletions src/librustc/hir/map/definitions.rs
Original file line number Diff line number Diff line change
@@ -10,7 +10,6 @@ use crate::ich::Fingerprint;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::indexed_vec::{IndexVec};
use rustc_data_structures::stable_hasher::StableHasher;
use serialize::{Encodable, Decodable, Encoder, Decoder};
use crate::session::CrateDisambiguator;
use std::borrow::Borrow;
use std::fmt::Write;
@@ -25,14 +24,13 @@ use crate::util::nodemap::NodeMap;
/// Internally the DefPathTable holds a tree of DefKeys, where each DefKey
/// stores the DefIndex of its parent.
/// There is one DefPathTable for each crate.
#[derive(Clone, Default)]
#[derive(Clone, Default, RustcDecodable, RustcEncodable)]
pub struct DefPathTable {
index_to_key: Vec<DefKey>,
def_path_hashes: Vec<DefPathHash>,
}

impl DefPathTable {

fn allocate(&mut self,
key: DefKey,
def_path_hash: DefPathHash)
@@ -86,28 +84,6 @@ impl DefPathTable {
}
}


impl Encodable for DefPathTable {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
// Index to key
self.index_to_key.encode(s)?;

// DefPath hashes
self.def_path_hashes.encode(s)?;

Ok(())
}
}

impl Decodable for DefPathTable {
fn decode<D: Decoder>(d: &mut D) -> Result<DefPathTable, D::Error> {
Ok(DefPathTable {
index_to_key: Decodable::decode(d)?,
def_path_hashes : Decodable::decode(d)?,
})
}
}

/// The definition table containing node definitions.
/// It holds the `DefPathTable` for local `DefId`s/`DefPath`s and it also stores a
/// mapping from `NodeId`s to local `DefId`s.
24 changes: 11 additions & 13 deletions src/librustc_mir/borrow_check/conflict_errors.rs
Original file line number Diff line number Diff line change
@@ -158,18 +158,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
span,
format!("value moved{} here, in previous iteration of loop", move_msg),
);
if Some(CompilerDesugaringKind::ForLoop) == span.compiler_desugaring_kind() {
if let Ok(snippet) = self.infcx.tcx.sess.source_map()
.span_to_snippet(span)
{
err.span_suggestion(
move_span,
"consider borrowing this to avoid moving it into the for loop",
format!("&{}", snippet),
Applicability::MaybeIncorrect,
);
}
}
is_loop_move = true;
} else if move_site.traversed_back_edge {
err.span_label(
@@ -185,7 +173,17 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
&mut err,
format!("variable moved due to use{}", move_spans.describe()),
);
};
}
if Some(CompilerDesugaringKind::ForLoop) == move_span.compiler_desugaring_kind() {
if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) {
err.span_suggestion(
move_span,
"consider borrowing to avoid moving into the for loop",
format!("&{}", snippet),
Applicability::MaybeIncorrect,
);
}
}
}

use_spans.var_span_label(
2 changes: 2 additions & 0 deletions src/librustc_mir/interpret/operand.rs
Original file line number Diff line number Diff line change
@@ -475,6 +475,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
PlaceBase::Local(mir::RETURN_PLACE) => return err!(ReadFromReturnPointer),
PlaceBase::Local(local) => {
// FIXME use place_projection.is_empty() when is available
// Do not use the layout passed in as argument if the base we are looking at
// here is not the entire place.
let layout = if let Place::Base(_) = mir_place {
layout
} else {
12 changes: 11 additions & 1 deletion src/librustc_mir/transform/const_prop.rs
Original file line number Diff line number Diff line change
@@ -295,6 +295,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
}

fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
trace!("eval_place(place={:?})", place);
match *place {
Place::Base(PlaceBase::Local(loc)) => self.places[loc].clone(),
Place::Projection(ref proj) => match proj.elem {
@@ -516,6 +517,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
}

fn replace_with_const(&self, rval: &mut Rvalue<'tcx>, value: Const<'tcx>, span: Span) {
trace!("attepting to replace {:?} with {:?}", rval, value);
self.ecx.validate_operand(
value,
vec![],
@@ -579,6 +581,10 @@ impl CanConstProp {
// FIXME(oli-obk): lint variables until they are used in a condition
// FIXME(oli-obk): lint if return value is constant
*val = mir.local_kind(local) == LocalKind::Temp;

if !*val {
trace!("local {:?} can't be propagated because it's not a temporary", local);
}
}
cpv.visit_mir(mir);
cpv.can_const_prop
@@ -598,6 +604,7 @@ impl<'tcx> Visitor<'tcx> for CanConstProp {
// FIXME(oli-obk): we could be more powerful here, if the multiple writes
// only occur in independent execution paths
MutatingUse(MutatingUseContext::Store) => if self.found_assignment[local] {
trace!("local {:?} can't be propagated because of multiple assignments", local);
self.can_const_prop[local] = false;
} else {
self.found_assignment[local] = true
@@ -609,7 +616,10 @@ impl<'tcx> Visitor<'tcx> for CanConstProp {
NonMutatingUse(NonMutatingUseContext::Projection) |
MutatingUse(MutatingUseContext::Projection) |
NonUse(_) => {},
_ => self.can_const_prop[local] = false,
_ => {
trace!("local {:?} can't be propagaged because it's used: {:?}", local, context);
self.can_const_prop[local] = false;
},
}
}
}
67 changes: 33 additions & 34 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
@@ -5194,7 +5194,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
&self,
res: Res,
span: Span,
) -> Result<(DefKind, DefId, Ty<'tcx>), ErrorReported> {
) -> Result<Res, ErrorReported> {
let tcx = self.tcx;
if let Res::SelfCtor(impl_def_id) = res {
let ty = self.impl_self_ty(span, impl_def_id).ty;
@@ -5204,11 +5204,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
Some(adt_def) if adt_def.has_ctor() => {
let variant = adt_def.non_enum_variant();
let ctor_def_id = variant.ctor_def_id.unwrap();
Ok((
DefKind::Ctor(CtorOf::Struct, variant.ctor_kind),
ctor_def_id,
tcx.type_of(ctor_def_id),
))
Ok(Res::Def(DefKind::Ctor(CtorOf::Struct, variant.ctor_kind), ctor_def_id))
}
_ => {
let mut err = tcx.sess.struct_span_err(span,
@@ -5235,15 +5231,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
}
}
} else {
match res {
Res::Def(kind, def_id) => {
// The things we are substituting into the type should not contain
// escaping late-bound regions, and nor should the base type scheme.
let ty = tcx.type_of(def_id);
Ok((kind, def_id, ty))
}
_ => span_bug!(span, "unexpected res in rewrite_self_ctor: {:?}", res),
}
Ok(res)
}
}

@@ -5266,27 +5254,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {

let tcx = self.tcx;

match res {
Res::Local(hid) | Res::Upvar(hid, ..) => {
let ty = self.local_ty(span, hid).decl_ty;
let ty = self.normalize_associated_types_in(span, &ty);
self.write_ty(hir_id, ty);
return (ty, res);
}
_ => {}
}

let (kind, def_id, ty) = match self.rewrite_self_ctor(res, span) {
Ok(result) => result,
let res = match self.rewrite_self_ctor(res, span) {
Ok(res) => res,
Err(ErrorReported) => return (tcx.types.err, res),
};
let path_segs =
AstConv::def_ids_for_value_path_segments(self, segments, self_ty, kind, def_id);
let path_segs = match res {
Res::Local(_) | Res::Upvar(..) => Vec::new(),
Res::Def(kind, def_id) =>
AstConv::def_ids_for_value_path_segments(self, segments, self_ty, kind, def_id),
_ => bug!("instantiate_value_path on {:?}", res),
};

let mut user_self_ty = None;
let mut is_alias_variant_ctor = false;
match kind {
DefKind::Ctor(CtorOf::Variant, _) => {
match res {
Res::Def(DefKind::Ctor(CtorOf::Variant, _), _) => {
if let Some(self_ty) = self_ty {
let adt_def = self_ty.ty_adt_def().unwrap();
user_self_ty = Some(UserSelfTy {
@@ -5296,8 +5278,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
is_alias_variant_ctor = true;
}
}
DefKind::Method
| DefKind::AssociatedConst => {
Res::Def(DefKind::Method, def_id)
| Res::Def(DefKind::AssociatedConst, def_id) => {
let container = tcx.associated_item(def_id).container;
debug!("instantiate_value_path: def_id={:?} container={:?}", def_id, container);
match container {
@@ -5337,6 +5319,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
None
}
}));

match res {
Res::Local(hid) | Res::Upvar(hid, ..) => {
let ty = self.local_ty(span, hid).decl_ty;
let ty = self.normalize_associated_types_in(span, &ty);
self.write_ty(hir_id, ty);
return (ty, res);
}
_ => {}
}

if generics_has_err {
// Don't try to infer type parameters when prohibited generic arguments were given.
user_self_ty = None;
@@ -5374,6 +5367,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
tcx.generics_of(*def_id).has_self
}).unwrap_or(false);

let def_id = res.def_id();

// The things we are substituting into the type should not contain
// escaping late-bound regions, and nor should the base type scheme.
let ty = tcx.type_of(def_id);

let substs = AstConv::create_substs_for_generic_args(
tcx,
def_id,
@@ -5490,7 +5489,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
ty_substituted);
self.write_substs(hir_id, substs);

(ty_substituted, Res::Def(kind, def_id))
(ty_substituted, res)
}

fn check_rustc_args_require_const(&self,
588 changes: 580 additions & 8 deletions src/libsyntax/parse/diagnostics.rs

Large diffs are not rendered by default.

587 changes: 43 additions & 544 deletions src/libsyntax/parse/parser.rs

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions src/test/ui/invalid-self-argument/bare-fn-start.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
fn a(&self) { }
//~^ ERROR unexpected `self` argument in function
//~| NOTE `self` is only valid as the first argument of an associated function
//~^ ERROR unexpected `self` parameter in function
//~| NOTE not valid as function parameter
//~| NOTE `self` is only valid as the first parameter of an associated function

fn main() { }
8 changes: 5 additions & 3 deletions src/test/ui/invalid-self-argument/bare-fn-start.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
error: unexpected `self` argument in function
--> $DIR/bare-fn-start.rs:1:7
error: unexpected `self` parameter in function
--> $DIR/bare-fn-start.rs:1:6
|
LL | fn a(&self) { }
| ^^^^ `self` is only valid as the first argument of an associated function
| ^^^^^ not valid as function parameter
|
= note: `self` is only valid as the first parameter of an associated function

error: aborting due to previous error

5 changes: 3 additions & 2 deletions src/test/ui/invalid-self-argument/bare-fn.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
fn b(foo: u32, &mut self) { }
//~^ ERROR unexpected `self` argument in function
//~| NOTE `self` is only valid as the first argument of an associated function
//~^ ERROR unexpected `self` parameter in function
//~| NOTE not valid as function parameter
//~| NOTE `self` is only valid as the first parameter of an associated function

fn main() { }
8 changes: 5 additions & 3 deletions src/test/ui/invalid-self-argument/bare-fn.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
error: unexpected `self` argument in function
--> $DIR/bare-fn.rs:1:21
error: unexpected `self` parameter in function
--> $DIR/bare-fn.rs:1:16
|
LL | fn b(foo: u32, &mut self) { }
| ^^^^ `self` is only valid as the first argument of an associated function
| ^^^^^^^^^ not valid as function parameter
|
= note: `self` is only valid as the first parameter of an associated function

error: aborting due to previous error

4 changes: 2 additions & 2 deletions src/test/ui/invalid-self-argument/trait-fn.rs
Original file line number Diff line number Diff line change
@@ -2,8 +2,8 @@ struct Foo {}

impl Foo {
fn c(foo: u32, self) {}
//~^ ERROR unexpected `self` argument in function
//~| NOTE `self` is only valid as the first argument of an associated function
//~^ ERROR unexpected `self` parameter in function
//~| NOTE must be the first associated function parameter

fn good(&mut self, foo: u32) {}
}
4 changes: 2 additions & 2 deletions src/test/ui/invalid-self-argument/trait-fn.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error: unexpected `self` argument in function
error: unexpected `self` parameter in function
--> $DIR/trait-fn.rs:4:20
|
LL | fn c(foo: u32, self) {}
| ^^^^ `self` is only valid as the first argument of an associated function
| ^^^^ must be the first associated function parameter

error: aborting due to previous error

18 changes: 18 additions & 0 deletions src/test/ui/issues/issue-60989.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
struct A {}
struct B {}

impl From<A> for B {
fn from(a: A) -> B {
B{}
}
}

fn main() {
let c1 = ();
c1::<()>;
//~^ ERROR type arguments are not allowed for this type

let c1 = A {};
c1::<Into<B>>;
//~^ ERROR type arguments are not allowed for this type
}
15 changes: 15 additions & 0 deletions src/test/ui/issues/issue-60989.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error[E0109]: type arguments are not allowed for this type
--> $DIR/issue-60989.rs:12:10
|
LL | c1::<()>;
| ^^ type argument not allowed

error[E0109]: type arguments are not allowed for this type
--> $DIR/issue-60989.rs:16:10
|
LL | c1::<Into<B>>;
| ^^^^^^^ type argument not allowed

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0109`.
7 changes: 7 additions & 0 deletions src/test/ui/issues/issue-61108.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
fn main() {
let mut bad_letters = vec!['e', 't', 'o', 'i'];
for l in bad_letters {
// something here
}
bad_letters.push('s'); //~ ERROR borrow of moved value: `bad_letters`
}
17 changes: 17 additions & 0 deletions src/test/ui/issues/issue-61108.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
error[E0382]: borrow of moved value: `bad_letters`
--> $DIR/issue-61108.rs:6:5
|
LL | let mut bad_letters = vec!['e', 't', 'o', 'i'];
| --------------- move occurs because `bad_letters` has type `std::vec::Vec<char>`, which does not implement the `Copy` trait
LL | for l in bad_letters {
| -----------
| |
| value moved here
| help: consider borrowing to avoid moving into the for loop: `&bad_letters`
...
LL | bad_letters.push('s');
| ^^^^^^^^^^^ value borrowed here after move

error: aborting due to previous error

For more information about this error, try `rustc --explain E0382`.
3 changes: 3 additions & 0 deletions src/test/ui/parser/self-in-function-arg.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn foo(x:i32, self: i32) -> i32 { self } //~ ERROR unexpected `self` parameter in function

fn main() {}
10 changes: 10 additions & 0 deletions src/test/ui/parser/self-in-function-arg.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
error: unexpected `self` parameter in function
--> $DIR/self-in-function-arg.rs:1:15
|
LL | fn foo(x:i32, self: i32) -> i32 { self }
| ^^^^ not valid as function parameter
|
= note: `self` is only valid as the first parameter of an associated function

error: aborting due to previous error

9 changes: 4 additions & 5 deletions src/test/ui/suggestions/borrow-for-loop-head.stderr
Original file line number Diff line number Diff line change
@@ -13,11 +13,10 @@ LL | let a = vec![1, 2, 3];
| - move occurs because `a` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
LL | for i in &a {
LL | for j in a {
| ^ value moved here, in previous iteration of loop
help: consider borrowing this to avoid moving it into the for loop
|
LL | for j in &a {
| ^^
| ^
| |
| value moved here, in previous iteration of loop
| help: consider borrowing to avoid moving into the for loop: `&a`

error: aborting due to 2 previous errors