From 941ca6f3e29655be69aa0f263077cf9f185b2ea8 Mon Sep 17 00:00:00 2001 From: Brent Kerby Date: Thu, 23 May 2019 09:04:01 -0600 Subject: [PATCH 01/14] Clarify docs for unreachable! macro --- src/libcore/macros.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index d2ee9b11b3640..168fc0424764e 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -445,9 +445,10 @@ macro_rules! writeln { /// * Iterators that dynamically terminate. /// /// If the determination that the code is unreachable proves incorrect, the -/// program immediately terminates with a [`panic!`]. The function [`unreachable_unchecked`], -/// which belongs to the [`std::hint`] module, informs the compiler to -/// optimize the code out of the release version entirely. +/// program immediately terminates with a [`panic!`]. +/// +/// The unsafe counterpart of this macro is the [`unreachable_unchecked`] function, which +/// instead of a [`panic!`] will cause undefined behavior if the code is reached. /// /// [`panic!`]: ../std/macro.panic.html /// [`unreachable_unchecked`]: ../std/hint/fn.unreachable_unchecked.html From 27c75372f116093110cf4230cac8672b0762cb92 Mon Sep 17 00:00:00 2001 From: Brent Kerby Date: Thu, 23 May 2019 17:34:10 -0600 Subject: [PATCH 02/14] Remove phrase "instead of a panic!" --- src/libcore/macros.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index 168fc0424764e..9dfa09cf8a512 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -448,7 +448,7 @@ macro_rules! writeln { /// program immediately terminates with a [`panic!`]. /// /// The unsafe counterpart of this macro is the [`unreachable_unchecked`] function, which -/// instead of a [`panic!`] will cause undefined behavior if the code is reached. +/// will cause undefined behavior if the code is reached. /// /// [`panic!`]: ../std/macro.panic.html /// [`unreachable_unchecked`]: ../std/hint/fn.unreachable_unchecked.html From 03cce1d81ea17639167681c42ae1afa4c67a2fd2 Mon Sep 17 00:00:00 2001 From: Jad Ghalayini Date: Sun, 26 May 2019 16:48:02 -0400 Subject: [PATCH 03/14] Added error message for E0284 --- src/librustc/error_codes.rs | 47 ++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index a1bfd417566ad..ef4d13096baae 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -1207,6 +1207,52 @@ fn main() { ``` "##, +E0284: r##" +This error occurs when the compiler is unable to unambiguously infer the +return type of a function or method which is generic on return type, such +as the `collect` method for `Iterator`s. + +For example: + +```compile_fail,E0284 +fn foo() -> Result { + let results = [Ok(true), Ok(false), Err(())].iter().cloned(); + let v : Vec = results.collect()?; + // Do things with v... + Ok(true) +} +``` + +Here we have an iterator `results` over `Result`. +Hence, `results.collect()` can return any type implementing +`FromIterator>`. On the other hand, the +`?` operator can accept any type implementing `Try`. + +The user of this code probably wants `collect()` to return a +`Result, ()>`, but the compiler can't be sure +that there isn't another type `T` implementing both `Try` and +`FromIterator>` in scope such that +`T::Ok == Vec`. Hence, this code is ambiguous and an error +is returned. + +To resolve this error, use a concrete type for the intermediate expression: + +``` +fn foo() -> Result { + let results = [Ok(true), Ok(false), Err(())].iter().cloned(); + let v = { + let temp : Result, ()> = results.collect(); + temp? + }; + // Do things with v... + Ok(true) +} +``` +Note that the type of `v` can now be inferred from the type of `temp` + + +"##, + E0308: r##" This error occurs when the compiler was unable to infer the concrete type of a variable. It can occur for several cases, the most common of which is a @@ -2158,7 +2204,6 @@ register_diagnostics! { E0278, // requirement is not satisfied E0279, // requirement is not satisfied E0280, // requirement is not satisfied - E0284, // cannot resolve type // E0285, // overflow evaluation builtin bounds // E0296, // replaced with a generic attribute input check // E0300, // unexpanded macro From 5c5f08ab9375606a686223bdf3d883cf8dac0e04 Mon Sep 17 00:00:00 2001 From: diwic Date: Mon, 27 May 2019 07:27:13 +0200 Subject: [PATCH 04/14] Use .await syntax instead of await! --- src/libcore/future/future.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/future/future.rs b/src/libcore/future/future.rs index 3f76ac20192ba..0492fd709b8dc 100644 --- a/src/libcore/future/future.rs +++ b/src/libcore/future/future.rs @@ -21,7 +21,7 @@ use crate::task::{Context, Poll}; /// task. /// /// When using a future, you generally won't call `poll` directly, but instead -/// `await!` the value. +/// `.await` the value. #[doc(spotlight)] #[must_use = "futures do nothing unless you `.await` or poll them"] #[stable(feature = "futures_api", since = "1.36.0")] From a23a77fb19b24adb22d0a3d3886acac1a7a31f68 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 27 May 2019 09:43:20 +0300 Subject: [PATCH 05/14] avoid materializing unintialized Boxes in RawVec --- src/liballoc/boxed.rs | 9 ++++++--- src/liballoc/raw_vec.rs | 10 ++++++---- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index bf8f5b8b91a1e..5affdbdb7e9d1 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -546,9 +546,12 @@ impl From<&[T]> for Box<[T]> { /// println!("{:?}", boxed_slice); /// ``` fn from(slice: &[T]) -> Box<[T]> { - let mut boxed = unsafe { RawVec::with_capacity(slice.len()).into_box() }; - boxed.copy_from_slice(slice); - boxed + let len = slice.len(); + let buf = RawVec::with_capacity(len); + unsafe { + ptr::copy_nonoverlapping(slice.as_ptr(), buf.ptr(), len); + buf.into_box() + } } } diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index d1fc5ac3b30d4..0454a56443579 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -685,12 +685,14 @@ impl RawVec { impl RawVec { /// Converts the entire buffer into `Box<[T]>`. /// - /// While it is not *strictly* Undefined Behavior to call - /// this procedure while some of the RawVec is uninitialized, - /// it certainly makes it trivial to trigger it. - /// /// Note that this will correctly reconstitute any `cap` changes /// that may have been performed. (see description of type for details) + /// + /// # Undefined Behavior + /// + /// All elements of `RawVec` must be initialized. Notice that + /// the rules around uninitialized boxed values are not finalized yet, + /// but until they are, it is advisable to avoid them. pub unsafe fn into_box(self) -> Box<[T]> { // NOTE: not calling `cap()` here, actually using the real `cap` field! let slice = slice::from_raw_parts_mut(self.ptr(), self.cap); From b560b9cd363d5b35d7f468d1749cab94380f7c62 Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 27 May 2019 16:17:39 +0200 Subject: [PATCH 06/14] Updated the Iterator docs with information about overriding methods. --- src/libcore/iter/mod.rs | 5 +++++ src/libcore/iter/traits/iterator.rs | 1 + 2 files changed, 6 insertions(+) diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index 1601357d3b054..6eccb9d1ea86d 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -140,6 +140,11 @@ //! call `next()` on your iterator, until it reaches `None`. Let's go over that //! next. //! +//! Also note that `Iterator` provides a default implementation of methods such as `nth` and `fold` +//! which call `next` internally. However, it is also possible to write a custom implementation of +//! methods like `nth` and `fold` if an iterator can compute them more efficiently without calling +//! `next`. +//! //! # for Loops and IntoIterator //! //! Rust's `for` loop syntax is actually sugar for iterators. Here's a basic diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs index 403f335810532..062a7f7043de5 100644 --- a/src/libcore/iter/traits/iterator.rs +++ b/src/libcore/iter/traits/iterator.rs @@ -964,6 +964,7 @@ pub trait Iterator { /// Creates an iterator that skips the first `n` elements. /// /// After they have been consumed, the rest of the elements are yielded. + /// Rather than overriding this method directly, instead override the `nth` method. /// /// # Examples /// From 0653e78ae1b35eb50e06423052a34d807f1ac2af Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 27 May 2019 09:43:20 +0300 Subject: [PATCH 07/14] make Box::clone simpler & safer --- src/liballoc/boxed.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 5affdbdb7e9d1..2f45ec7d643f8 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -395,11 +395,9 @@ impl Clone for Box { #[stable(feature = "box_slice_clone", since = "1.3.0")] impl Clone for Box { fn clone(&self) -> Self { - let len = self.len(); - let buf = RawVec::with_capacity(len); + let buf: Box<[u8]> = self.as_bytes().into(); unsafe { - ptr::copy_nonoverlapping(self.as_ptr(), buf.ptr(), len); - from_boxed_utf8_unchecked(buf.into_box()) + from_boxed_utf8_unchecked(buf) } } } From fe31ad38cb5c6fba5be871ab63082d7cdf430374 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 27 May 2019 22:42:50 +0300 Subject: [PATCH 08/14] Update src/liballoc/boxed.rs Co-Authored-By: Ralf Jung --- src/liballoc/boxed.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 2f45ec7d643f8..76b660fba685c 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -395,6 +395,7 @@ impl Clone for Box { #[stable(feature = "box_slice_clone", since = "1.3.0")] impl Clone for Box { fn clone(&self) -> Self { + // this makes a copy of the data let buf: Box<[u8]> = self.as_bytes().into(); unsafe { from_boxed_utf8_unchecked(buf) From acaf284e5580c5f65489a062635f1829551bec08 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 27 May 2019 21:40:22 +0200 Subject: [PATCH 09/14] Remove unused tcx and mir params --- .../transform/qualify_min_const_fn.rs | 40 +++++++++---------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index e1d41ba4fc509..ce35a06f86a03 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -136,10 +136,10 @@ fn check_rvalue( ) -> McfResult { match rvalue { Rvalue::Repeat(operand, _) | Rvalue::Use(operand) => { - check_operand(tcx, mir, operand, span) + check_operand(operand, span) } Rvalue::Len(place) | Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) => { - check_place(tcx, mir, place, span) + check_place(place, span) } Rvalue::Cast(CastKind::Misc, operand, cast_ty) => { use rustc::ty::cast::CastTy; @@ -153,11 +153,11 @@ fn check_rvalue( (CastTy::RPtr(_), CastTy::Float) => bug!(), (CastTy::RPtr(_), CastTy::Int(_)) => bug!(), (CastTy::Ptr(_), CastTy::RPtr(_)) => bug!(), - _ => check_operand(tcx, mir, operand, span), + _ => check_operand(operand, span), } } Rvalue::Cast(CastKind::Pointer(PointerCast::MutToConstPointer), operand, _) => { - check_operand(tcx, mir, operand, span) + check_operand(operand, span) } Rvalue::Cast(CastKind::Pointer(PointerCast::UnsafeFnPointer), _, _) | Rvalue::Cast(CastKind::Pointer(PointerCast::ClosureFnPointer(_)), _, _) | @@ -171,8 +171,8 @@ fn check_rvalue( )), // binops are fine on integers Rvalue::BinaryOp(_, lhs, rhs) | Rvalue::CheckedBinaryOp(_, lhs, rhs) => { - check_operand(tcx, mir, lhs, span)?; - check_operand(tcx, mir, rhs, span)?; + check_operand(lhs, span)?; + check_operand(rhs, span)?; let ty = lhs.ty(mir, tcx); if ty.is_integral() || ty.is_bool() || ty.is_char() { Ok(()) @@ -191,7 +191,7 @@ fn check_rvalue( Rvalue::UnaryOp(_, operand) => { let ty = operand.ty(mir, tcx); if ty.is_integral() || ty.is_bool() { - check_operand(tcx, mir, operand, span) + check_operand(operand, span) } else { Err(( span, @@ -201,7 +201,7 @@ fn check_rvalue( } Rvalue::Aggregate(_, operands) => { for operand in operands { - check_operand(tcx, mir, operand, span)?; + check_operand(operand, span)?; } Ok(()) } @@ -216,11 +216,11 @@ fn check_statement( let span = statement.source_info.span; match &statement.kind { StatementKind::Assign(place, rval) => { - check_place(tcx, mir, place, span)?; + check_place(place, span)?; check_rvalue(tcx, mir, rval, span) } - StatementKind::FakeRead(_, place) => check_place(tcx, mir, place, span), + StatementKind::FakeRead(_, place) => check_place(place, span), // just an assignment StatementKind::SetDiscriminant { .. } => Ok(()), @@ -239,22 +239,18 @@ fn check_statement( } fn check_operand( - tcx: TyCtxt<'a, 'tcx, 'tcx>, - mir: &'a Mir<'tcx>, operand: &Operand<'tcx>, span: Span, ) -> McfResult { match operand { Operand::Move(place) | Operand::Copy(place) => { - check_place(tcx, mir, place, span) + check_place(place, span) } Operand::Constant(_) => Ok(()), } } fn check_place( - tcx: TyCtxt<'a, 'tcx, 'tcx>, - mir: &'a Mir<'tcx>, place: &Place<'tcx>, span: Span, ) -> McfResult { @@ -268,7 +264,7 @@ fn check_place( match proj.elem { | ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } | ProjectionElem::Deref | ProjectionElem::Field(..) | ProjectionElem::Index(_) => { - check_place(tcx, mir, &proj.base, span) + check_place(&proj.base, span) } | ProjectionElem::Downcast(..) => { Err((span, "`match` or `if let` in `const fn` is unstable".into())) @@ -290,11 +286,11 @@ fn check_terminator( | TerminatorKind::Resume => Ok(()), TerminatorKind::Drop { location, .. } => { - check_place(tcx, mir, location, span) + check_place(location, span) } TerminatorKind::DropAndReplace { location, value, .. } => { - check_place(tcx, mir, location, span)?; - check_operand(tcx, mir, value, span) + check_place(location, span)?; + check_operand(value, span) }, TerminatorKind::FalseEdges { .. } | TerminatorKind::SwitchInt { .. } => Err(( @@ -346,10 +342,10 @@ fn check_terminator( )), } - check_operand(tcx, mir, func, span)?; + check_operand(func, span)?; for arg in args { - check_operand(tcx, mir, arg, span)?; + check_operand(arg, span)?; } Ok(()) } else { @@ -363,7 +359,7 @@ fn check_terminator( msg: _, target: _, cleanup: _, - } => check_operand(tcx, mir, cond, span), + } => check_operand(cond, span), TerminatorKind::FalseUnwind { .. } => { Err((span, "loops are not allowed in const fn".into())) From b922e8a97d12e2b10d918ee54ecd0bc99df050f2 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 27 May 2019 22:00:44 +0200 Subject: [PATCH 10/14] Make dest_needs_borrow iterate instead of recurse --- src/librustc_mir/transform/inline.rs | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 24ec3219a2e7b..782af3024ad2c 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -440,19 +440,22 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { // writes to `i`. To prevent this we need to create a temporary // borrow of the place and pass the destination as `*temp` instead. fn dest_needs_borrow(place: &Place<'_>) -> bool { - match *place { - Place::Projection(ref p) => { - match p.elem { + place.iterate(|place_base, place_projection| { + for proj in place_projection { + match proj.elem { ProjectionElem::Deref | - ProjectionElem::Index(_) => true, - _ => dest_needs_borrow(&p.base) + ProjectionElem::Index(_) => return true, + _ => {} } } - // Static variables need a borrow because the callee - // might modify the same static. - Place::Base(PlaceBase::Static(_)) => true, - _ => false - } + + match place_base { + // Static variables need a borrow because the callee + // might modify the same static. + PlaceBase::Static(_) => true, + _ => false + } + }) } let dest = if dest_needs_borrow(&destination.0) { From fb4b62b87bd35019e2c797d30572ba8188feff9c Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 27 May 2019 21:47:24 +0200 Subject: [PATCH 11/14] Make check_place iterate instead of recurse --- .../transform/qualify_min_const_fn.rs | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index ce35a06f86a03..a1e2d0683d380 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -250,28 +250,29 @@ fn check_operand( } } -fn check_place( - place: &Place<'tcx>, - span: Span, -) -> McfResult { - match place { - Place::Base(PlaceBase::Local(_)) => Ok(()), - // promoteds are always fine, they are essentially constants - Place::Base(PlaceBase::Static(box Static { kind: StaticKind::Promoted(_), .. })) => Ok(()), - Place::Base(PlaceBase::Static(box Static { kind: StaticKind::Static(_), .. })) => - Err((span, "cannot access `static` items in const fn".into())), - Place::Projection(proj) => { +fn check_place(place: &Place<'tcx>, span: Span) -> McfResult { + place.iterate(|place_base, place_projection| { + for proj in place_projection { match proj.elem { - | ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } - | ProjectionElem::Deref | ProjectionElem::Field(..) | ProjectionElem::Index(_) => { - check_place(&proj.base, span) - } - | ProjectionElem::Downcast(..) => { - Err((span, "`match` or `if let` in `const fn` is unstable".into())) + ProjectionElem::Downcast(..) => { + return Err((span, "`match` or `if let` in `const fn` is unstable".into())); } + ProjectionElem::ConstantIndex { .. } + | ProjectionElem::Subslice { .. } + | ProjectionElem::Deref + | ProjectionElem::Field(..) + | ProjectionElem::Index(_) => {} } } - } + + match place_base { + PlaceBase::Static(box Static { kind: StaticKind::Static(_), .. }) => { + Err((span, "cannot access `static` items in const fn".into())) + } + PlaceBase::Local(_) + | PlaceBase::Static(box Static { kind: StaticKind::Promoted(_), .. }) => Ok(()), + } + }) } fn check_terminator( From c3e71f210ed105dc8ef9d104ff6ddec39baa2258 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 27 May 2019 22:47:30 +0200 Subject: [PATCH 12/14] Make eval_place iterate instead of recurse --- src/librustc_mir/transform/const_prop.rs | 79 ++++++++++++------------ 1 file changed, 41 insertions(+), 38 deletions(-) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index b2976cd501e7f..24e7fa009b40c 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -296,47 +296,50 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> { fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option> { trace!("eval_place(place={:?})", place); - match *place { - Place::Base(PlaceBase::Local(loc)) => self.places[loc].clone(), - Place::Projection(ref proj) => match proj.elem { - ProjectionElem::Field(field, _) => { - trace!("field proj on {:?}", proj.base); - let base = self.eval_place(&proj.base, source_info)?; + place.iterate(|place_base, place_projection| { + let mut eval = match place_base { + PlaceBase::Local(loc) => self.places[*loc].clone()?, + PlaceBase::Static(box Static {kind: StaticKind::Promoted(promoted), ..}) => { + let generics = self.tcx.generics_of(self.source.def_id()); + if generics.requires_monomorphization(self.tcx) { + // FIXME: can't handle code with generics + return None; + } + let substs = InternalSubsts::identity_for_item(self.tcx, self.source.def_id()); + let instance = Instance::new(self.source.def_id(), substs); + let cid = GlobalId { + instance, + promoted: Some(*promoted), + }; + // cannot use `const_eval` here, because that would require having the MIR + // for the current function available, but we're producing said MIR right now let res = self.use_ecx(source_info, |this| { - this.ecx.operand_field(base, field.index() as u64) + let mir = &this.promoted[*promoted]; + eval_promoted(this.tcx, cid, mir, this.param_env) })?; - Some(res) - }, - // 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. - _ => None, - }, - Place::Base( - PlaceBase::Static(box Static {kind: StaticKind::Promoted(promoted), ..}) - ) => { - let generics = self.tcx.generics_of(self.source.def_id()); - if generics.requires_monomorphization(self.tcx) { - // FIXME: can't handle code with generics - return None; + trace!("evaluated promoted {:?} to {:?}", promoted, res); + res.into() } - let substs = InternalSubsts::identity_for_item(self.tcx, self.source.def_id()); - let instance = Instance::new(self.source.def_id(), substs); - let cid = GlobalId { - instance, - promoted: Some(promoted), - }; - // cannot use `const_eval` here, because that would require having the MIR - // for the current function available, but we're producing said MIR right now - let res = self.use_ecx(source_info, |this| { - let mir = &this.promoted[promoted]; - eval_promoted(this.tcx, cid, mir, this.param_env) - })?; - trace!("evaluated promoted {:?} to {:?}", promoted, res); - Some(res.into()) - }, - _ => None, - } + _ => return None, + }; + + for proj in place_projection { + match proj.elem { + ProjectionElem::Field(field, _) => { + trace!("field proj on {:?}", proj.base); + eval = self.use_ecx(source_info, |this| { + this.ecx.operand_field(eval, field.index() as u64) + })?; + }, + // 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. + _ => return None, + } + } + + Some(eval) + }) } fn eval_operand(&mut self, op: &Operand<'tcx>, source_info: SourceInfo) -> Option> { From 38ecea4c115114c0e8a19d90d1ca8b5af8f5cf85 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 27 May 2019 23:03:38 +0200 Subject: [PATCH 13/14] Use Place::local --- src/librustc_mir/build/expr/as_rvalue.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index a0b504a99de9a..07a9f294fb68c 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -528,13 +528,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { }) => { // Not projected from the implicit `self` in a closure. debug_assert!( - match *base { - Place::Base(PlaceBase::Local(local)) => local == Local::new(1), - Place::Projection(box Projection { - ref base, - elem: ProjectionElem::Deref, - }) => *base == Place::Base(PlaceBase::Local(Local::new(1))), - _ => false, + match base.local() { + Some(local) => local == Local::new(1), + None => false, }, "Unexpected capture place" ); From b3480126d4acbd197836089257e9a4c751a78f5b Mon Sep 17 00:00:00 2001 From: Jad Ghalayini Date: Mon, 27 May 2019 19:37:20 -0400 Subject: [PATCH 14/14] Incorporated suggested changes --- src/librustc/error_codes.rs | 9 ++++----- .../associated-types-overridden-binding.stderr | 1 + .../associated-types-unconstrained.stderr | 1 + src/test/ui/issues/issue-12028.stderr | 1 + src/test/ui/question-mark-type-infer.stderr | 1 + 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index ef4d13096baae..6243e911bd5fd 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -1217,7 +1217,7 @@ For example: ```compile_fail,E0284 fn foo() -> Result { let results = [Ok(true), Ok(false), Err(())].iter().cloned(); - let v : Vec = results.collect()?; + let v: Vec = results.collect()?; // Do things with v... Ok(true) } @@ -1228,7 +1228,7 @@ Hence, `results.collect()` can return any type implementing `FromIterator>`. On the other hand, the `?` operator can accept any type implementing `Try`. -The user of this code probably wants `collect()` to return a +The author of this code probably wants `collect()` to return a `Result, ()>`, but the compiler can't be sure that there isn't another type `T` implementing both `Try` and `FromIterator>` in scope such that @@ -1241,16 +1241,15 @@ To resolve this error, use a concrete type for the intermediate expression: fn foo() -> Result { let results = [Ok(true), Ok(false), Err(())].iter().cloned(); let v = { - let temp : Result, ()> = results.collect(); + let temp: Result, ()> = results.collect(); temp? }; // Do things with v... Ok(true) } ``` -Note that the type of `v` can now be inferred from the type of `temp` - +Note that the type of `v` can now be inferred from the type of `temp`. "##, E0308: r##" diff --git a/src/test/ui/associated-types/associated-types-overridden-binding.stderr b/src/test/ui/associated-types/associated-types-overridden-binding.stderr index fced38caaba91..a26ee23894f6d 100644 --- a/src/test/ui/associated-types/associated-types-overridden-binding.stderr +++ b/src/test/ui/associated-types/associated-types-overridden-binding.stderr @@ -12,3 +12,4 @@ LL | trait Foo: Iterator {} error: aborting due to previous error +For more information about this error, try `rustc --explain E0284`. diff --git a/src/test/ui/associated-types/associated-types-unconstrained.stderr b/src/test/ui/associated-types/associated-types-unconstrained.stderr index 26e5a6a503c6f..da14a69ae306a 100644 --- a/src/test/ui/associated-types/associated-types-unconstrained.stderr +++ b/src/test/ui/associated-types/associated-types-unconstrained.stderr @@ -6,3 +6,4 @@ LL | let x: isize = Foo::bar(); error: aborting due to previous error +For more information about this error, try `rustc --explain E0284`. diff --git a/src/test/ui/issues/issue-12028.stderr b/src/test/ui/issues/issue-12028.stderr index b9e2e80492b37..64694c7a8d0b6 100644 --- a/src/test/ui/issues/issue-12028.stderr +++ b/src/test/ui/issues/issue-12028.stderr @@ -6,3 +6,4 @@ LL | self.input_stream(&mut stream); error: aborting due to previous error +For more information about this error, try `rustc --explain E0284`. diff --git a/src/test/ui/question-mark-type-infer.stderr b/src/test/ui/question-mark-type-infer.stderr index 2a1bdf57a88cb..f62a540572c93 100644 --- a/src/test/ui/question-mark-type-infer.stderr +++ b/src/test/ui/question-mark-type-infer.stderr @@ -6,3 +6,4 @@ LL | l.iter().map(f).collect()? error: aborting due to previous error +For more information about this error, try `rustc --explain E0284`.