From ad1cdecaeb64fa020c46ce43d87a8e33fc3fdafc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tuomas=20Lappetel=C3=A4inen?= Date: Thu, 23 Jan 2020 15:16:16 +0200 Subject: [PATCH 01/17] add a test for #60976 The test fails on 1.36.0 but passes on master. --- src/test/ui/use/auxiliary/extern-use-primitive-type-lib.rs | 3 +++ src/test/ui/use/issue-60976-extern-use-primitive-type.rs | 7 +++++++ 2 files changed, 10 insertions(+) create mode 100644 src/test/ui/use/auxiliary/extern-use-primitive-type-lib.rs create mode 100644 src/test/ui/use/issue-60976-extern-use-primitive-type.rs diff --git a/src/test/ui/use/auxiliary/extern-use-primitive-type-lib.rs b/src/test/ui/use/auxiliary/extern-use-primitive-type-lib.rs new file mode 100644 index 0000000000000..3c7756ef7e679 --- /dev/null +++ b/src/test/ui/use/auxiliary/extern-use-primitive-type-lib.rs @@ -0,0 +1,3 @@ +// compile-flags: --edition=2018 + +pub use u32; diff --git a/src/test/ui/use/issue-60976-extern-use-primitive-type.rs b/src/test/ui/use/issue-60976-extern-use-primitive-type.rs new file mode 100644 index 0000000000000..4cd458302a498 --- /dev/null +++ b/src/test/ui/use/issue-60976-extern-use-primitive-type.rs @@ -0,0 +1,7 @@ +// Regression test for #60976: ICE (with <=1.36.0) when another file had `use ;`. +// check-pass +// aux-build:extern-use-primitive-type-lib.rs + +extern crate extern_use_primitive_type_lib; + +fn main() {} From b680f408d06a519132b6fb5ef78a0938f8a71b7e Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 14 Jan 2020 01:21:10 -0300 Subject: [PATCH 02/17] Place conflict functions take Local by value --- src/librustc_mir/borrow_check/places_conflict.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs index b95d1af11ad1d..6b1cdaf9b383c 100644 --- a/src/librustc_mir/borrow_check/places_conflict.rs +++ b/src/librustc_mir/borrow_check/places_conflict.rs @@ -119,10 +119,10 @@ fn place_components_conflict<'tcx>( // and either equal or disjoint. // - If we did run out of access, the borrow can access a part of it. - let borrow_local = &borrow_place.local; + let borrow_local = borrow_place.local; let access_local = access_place.local; - match place_base_conflict(borrow_local, access_local) { + match place_base_conflict(borrow_local, *access_local) { Overlap::Arbitrary => { bug!("Two base can't return Arbitrary"); } @@ -208,7 +208,7 @@ fn place_components_conflict<'tcx>( // access cares about. let proj_base = &borrow_place.projection[..access_place.projection.len() + i]; - let base_ty = Place::ty_from(borrow_local, proj_base, body, tcx).ty; + let base_ty = Place::ty_from(&borrow_local, proj_base, body, tcx).ty; match (elem, &base_ty.kind, access) { (_, _, Shallow(Some(ArtificialField::ArrayLength))) @@ -293,7 +293,7 @@ fn place_components_conflict<'tcx>( // Given that the bases of `elem1` and `elem2` are always either equal // or disjoint (and have the same type!), return the overlap situation // between `elem1` and `elem2`. -fn place_base_conflict(l1: &Local, l2: &Local) -> Overlap { +fn place_base_conflict(l1: Local, l2: Local) -> Overlap { if l1 == l2 { // the same local - base case, equal debug!("place_element_conflict: DISJOINT-OR-EQ-LOCAL"); @@ -311,7 +311,7 @@ fn place_base_conflict(l1: &Local, l2: &Local) -> Overlap { fn place_projection_conflict<'tcx>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, - pi1_local: &Local, + pi1_local: Local, pi1_proj_base: &[PlaceElem<'tcx>], pi1_elem: &PlaceElem<'tcx>, pi2_elem: &PlaceElem<'tcx>, @@ -329,7 +329,7 @@ fn place_projection_conflict<'tcx>( debug!("place_element_conflict: DISJOINT-OR-EQ-FIELD"); Overlap::EqualOrDisjoint } else { - let ty = Place::ty_from(pi1_local, pi1_proj_base, body, tcx).ty; + let ty = Place::ty_from(&pi1_local, pi1_proj_base, body, tcx).ty; match ty.kind { ty::Adt(def, _) if def.is_union() => { // Different fields of a union, we are basically stuck. From 88643428560ecc874da3194fbd606a4d3795027d Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 14 Jan 2020 01:23:51 -0300 Subject: [PATCH 03/17] record_killed_borrows_for_local takes Local by value --- src/librustc_mir/borrow_check/constraint_generation.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_mir/borrow_check/constraint_generation.rs b/src/librustc_mir/borrow_check/constraint_generation.rs index 0f6a360c7933b..d85b55656ca20 100644 --- a/src/librustc_mir/borrow_check/constraint_generation.rs +++ b/src/librustc_mir/borrow_check/constraint_generation.rs @@ -97,7 +97,7 @@ impl<'cg, 'cx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'tcx> { )); // If there are borrows on this now dead local, we need to record them as `killed`. - if let StatementKind::StorageDead(ref local) = statement.kind { + if let StatementKind::StorageDead(local) = statement.kind { record_killed_borrows_for_local( all_facts, self.borrow_set, @@ -199,7 +199,7 @@ impl<'cx, 'cg, 'tcx> ConstraintGeneration<'cx, 'cg, 'tcx> { all_facts, self.borrow_set, self.location_table, - local, + *local, location, ); } @@ -239,10 +239,10 @@ fn record_killed_borrows_for_local( all_facts: &mut AllFacts, borrow_set: &BorrowSet<'_>, location_table: &LocationTable, - local: &Local, + local: Local, location: Location, ) { - if let Some(borrow_indices) = borrow_set.local_map.get(local) { + if let Some(borrow_indices) = borrow_set.local_map.get(&local) { all_facts.killed.reserve(borrow_indices.len()); for &borrow_index in borrow_indices { let location_index = location_table.mid_index(location); From a943a2dbcabfb57d7171719638faecac88c2abd1 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 14 Jan 2020 01:26:11 -0300 Subject: [PATCH 04/17] make_integrate_local takes Local by value --- src/librustc_mir/transform/inline.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 2dd00fe2fee19..6ce73a2502b80 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -640,8 +640,8 @@ impl<'a, 'tcx> Integrator<'a, 'tcx> { new } - fn make_integrate_local(&self, local: &Local) -> Local { - if *local == RETURN_PLACE { + fn make_integrate_local(&self, local: Local) -> Local { + if local == RETURN_PLACE { return self.destination.local; } @@ -660,7 +660,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> { } fn visit_local(&mut self, local: &mut Local, _ctxt: PlaceContext, _location: Location) { - *local = self.make_integrate_local(local); + *local = self.make_integrate_local(*local); } fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) { @@ -680,7 +680,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> { fn process_projection_elem(&mut self, elem: &PlaceElem<'tcx>) -> Option> { if let PlaceElem::Index(local) = elem { - let new_local = self.make_integrate_local(local); + let new_local = self.make_integrate_local(*local); if new_local != *local { return Some(PlaceElem::Index(new_local)); From 074113d2e6458239063da9fc515b43ff1e5b75c4 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 14 Jan 2020 01:51:59 -0300 Subject: [PATCH 05/17] codegen_place and related functions can take PlaceRef by value --- src/librustc_codegen_ssa/mir/block.rs | 10 +++++----- src/librustc_codegen_ssa/mir/operand.rs | 6 +++--- src/librustc_codegen_ssa/mir/place.rs | 10 +++++----- src/librustc_codegen_ssa/mir/rvalue.rs | 6 +++--- src/librustc_codegen_ssa/mir/statement.rs | 6 +++--- 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 9169010da8801..339a6efb8351a 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -264,7 +264,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } PassMode::Direct(_) | PassMode::Pair(..) => { - let op = self.codegen_consume(&mut bx, &mir::Place::return_place().as_ref()); + let op = self.codegen_consume(&mut bx, mir::Place::return_place().as_ref()); if let Ref(llval, _, align) = op.val { bx.load(llval, align) } else { @@ -319,7 +319,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { return; } - let place = self.codegen_place(&mut bx, &location.as_ref()); + let place = self.codegen_place(&mut bx, location.as_ref()); let (args1, args2); let mut args = if let Some(llextra) = place.llextra { args2 = [place.llval, llextra]; @@ -1111,7 +1111,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } else { self.codegen_place( bx, - &mir::PlaceRef { local: &dest.local, projection: &dest.projection }, + mir::PlaceRef { local: &dest.local, projection: &dest.projection }, ) }; if fn_ret.is_indirect() { @@ -1137,7 +1137,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { LocalRef::Place(place) => self.codegen_transmute_into(bx, src, place), LocalRef::UnsizedPlace(_) => bug!("transmute must not involve unsized locals"), LocalRef::Operand(None) => { - let dst_layout = bx.layout_of(self.monomorphized_place_ty(&dst.as_ref())); + let dst_layout = bx.layout_of(self.monomorphized_place_ty(dst.as_ref())); assert!(!dst_layout.ty.has_erasable_regions()); let place = PlaceRef::alloca(bx, dst_layout); place.storage_live(bx); @@ -1151,7 +1151,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } } else { - let dst = self.codegen_place(bx, &dst.as_ref()); + let dst = self.codegen_place(bx, dst.as_ref()); self.codegen_transmute_into(bx, src, dst); } } diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index a155a6e78f7c3..363967510dc08 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -369,7 +369,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { fn maybe_codegen_consume_direct( &mut self, bx: &mut Bx, - place_ref: &mir::PlaceRef<'_, 'tcx>, + place_ref: mir::PlaceRef<'_, 'tcx>, ) -> Option> { debug!("maybe_codegen_consume_direct(place_ref={:?})", place_ref); @@ -413,7 +413,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn codegen_consume( &mut self, bx: &mut Bx, - place_ref: &mir::PlaceRef<'_, 'tcx>, + place_ref: mir::PlaceRef<'_, 'tcx>, ) -> OperandRef<'tcx, Bx::Value> { debug!("codegen_consume(place_ref={:?})", place_ref); @@ -444,7 +444,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { match *operand { mir::Operand::Copy(ref place) | mir::Operand::Move(ref place) => { - self.codegen_consume(bx, &place.as_ref()) + self.codegen_consume(bx, place.as_ref()) } mir::Operand::Constant(ref constant) => { diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index 5e03a35b8a6fd..1fe9b6ed4b6bb 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -408,14 +408,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn codegen_place( &mut self, bx: &mut Bx, - place_ref: &mir::PlaceRef<'_, 'tcx>, + place_ref: mir::PlaceRef<'_, 'tcx>, ) -> PlaceRef<'tcx, Bx::Value> { debug!("codegen_place(place_ref={:?})", place_ref); let cx = self.cx; let tcx = self.cx.tcx(); let result = match place_ref { - mir::PlaceRef { local, projection: [] } => match self.locals[**local] { + mir::PlaceRef { local, projection: [] } => match self.locals[*local] { LocalRef::Place(place) => { return place; } @@ -428,13 +428,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }, mir::PlaceRef { local, projection: [proj_base @ .., mir::ProjectionElem::Deref] } => { // Load the pointer from its location. - self.codegen_consume(bx, &mir::PlaceRef { local, projection: proj_base }) + self.codegen_consume(bx, mir::PlaceRef { local, projection: proj_base }) .deref(bx.cx()) } mir::PlaceRef { local, projection: [proj_base @ .., elem] } => { // FIXME turn this recursion into iteration let cg_base = - self.codegen_place(bx, &mir::PlaceRef { local, projection: proj_base }); + self.codegen_place(bx, mir::PlaceRef { local, projection: proj_base }); match elem { mir::ProjectionElem::Deref => bug!(), @@ -497,7 +497,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { result } - pub fn monomorphized_place_ty(&self, place_ref: &mir::PlaceRef<'_, 'tcx>) -> Ty<'tcx> { + pub fn monomorphized_place_ty(&self, place_ref: mir::PlaceRef<'_, 'tcx>) -> Ty<'tcx> { let tcx = self.cx.tcx(); let place_ty = mir::Place::ty_from(place_ref.local, place_ref.projection, *self.mir, tcx); self.monomorphize(&place_ty.ty) diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index 39cb501b7aa98..2f83298741aa6 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -467,7 +467,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::Rvalue::Discriminant(ref place) => { let discr_ty = rvalue.ty(*self.mir, bx.tcx()); let discr = self - .codegen_place(&mut bx, &place.as_ref()) + .codegen_place(&mut bx, place.as_ref()) .codegen_get_discr(&mut bx, discr_ty); ( bx, @@ -541,7 +541,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } // use common size calculation for non zero-sized types - let cg_value = self.codegen_place(bx, &place.as_ref()); + let cg_value = self.codegen_place(bx, place.as_ref()); cg_value.len(bx.cx()) } @@ -552,7 +552,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { place: &mir::Place<'tcx>, mk_ptr_ty: impl FnOnce(TyCtxt<'tcx>, Ty<'tcx>) -> Ty<'tcx>, ) -> (Bx, OperandRef<'tcx, Bx::Value>) { - let cg_place = self.codegen_place(&mut bx, &place.as_ref()); + let cg_place = self.codegen_place(&mut bx, place.as_ref()); let ty = cg_place.layout.ty; diff --git a/src/librustc_codegen_ssa/mir/statement.rs b/src/librustc_codegen_ssa/mir/statement.rs index 8422c625d634e..e68b41ad18879 100644 --- a/src/librustc_codegen_ssa/mir/statement.rs +++ b/src/librustc_codegen_ssa/mir/statement.rs @@ -41,12 +41,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } } else { - let cg_dest = self.codegen_place(&mut bx, &place.as_ref()); + let cg_dest = self.codegen_place(&mut bx, place.as_ref()); self.codegen_rvalue(bx, cg_dest, rvalue) } } mir::StatementKind::SetDiscriminant { box ref place, variant_index } => { - self.codegen_place(&mut bx, &place.as_ref()) + self.codegen_place(&mut bx, place.as_ref()) .codegen_set_discr(&mut bx, variant_index); bx } @@ -70,7 +70,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let outputs = asm .outputs .iter() - .map(|output| self.codegen_place(&mut bx, &output.as_ref())) + .map(|output| self.codegen_place(&mut bx, output.as_ref())) .collect(); let input_vals = asm.inputs.iter().fold( From e5b18374cbc0626b65e24af4147b664c8355c6ae Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 14 Jan 2020 02:10:05 -0300 Subject: [PATCH 06/17] Local field on PlaceRef and RootPlace is not a reference anymore --- src/librustc/mir/mod.rs | 14 +++---- src/librustc_codegen_ssa/mir/analyze.rs | 10 ++--- src/librustc_codegen_ssa/mir/block.rs | 2 +- src/librustc_codegen_ssa/mir/operand.rs | 2 +- src/librustc_codegen_ssa/mir/place.rs | 4 +- .../borrow_check/constraint_generation.rs | 4 +- .../diagnostics/conflict_errors.rs | 12 +++--- .../borrow_check/diagnostics/mod.rs | 14 +++---- .../borrow_check/diagnostics/move_errors.rs | 8 ++-- .../diagnostics/mutability_errors.rs | 40 +++++++++---------- src/librustc_mir/borrow_check/mod.rs | 26 ++++++------ .../borrow_check/places_conflict.rs | 2 +- src/librustc_mir/borrow_check/prefixes.rs | 2 +- .../dataflow/move_paths/builder.rs | 2 +- src/librustc_mir/dataflow/move_paths/mod.rs | 2 +- .../transform/check_consts/qualifs.rs | 6 +-- .../transform/check_consts/resolver.rs | 2 +- src/librustc_mir/transform/instcombine.rs | 2 +- src/librustc_mir/transform/promote_consts.rs | 12 +++--- src/librustc_mir/transform/simplify_try.rs | 2 +- .../build/expr/as_rvalue.rs | 10 ++--- src/librustc_mir_build/build/matches/mod.rs | 2 +- 22 files changed, 90 insertions(+), 90 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 3a7c650c4618c..34e5ddbb513af 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1773,7 +1773,7 @@ rustc_index::newtype_index! { #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct PlaceRef<'a, 'tcx> { - pub local: &'a Local, + pub local: Local, pub projection: &'a [PlaceElem<'tcx>], } @@ -1798,7 +1798,7 @@ impl<'tcx> Place<'tcx> { pub fn local_or_deref_local(&self) -> Option { match self.as_ref() { PlaceRef { local, projection: &[] } - | PlaceRef { local, projection: &[ProjectionElem::Deref] } => Some(*local), + | PlaceRef { local, projection: &[ProjectionElem::Deref] } => Some(local), _ => None, } } @@ -1810,7 +1810,7 @@ impl<'tcx> Place<'tcx> { } pub fn as_ref(&self) -> PlaceRef<'_, 'tcx> { - PlaceRef { local: &self.local, projection: &self.projection } + PlaceRef { local: self.local, projection: &self.projection } } } @@ -1826,9 +1826,9 @@ impl<'a, 'tcx> PlaceRef<'a, 'tcx> { // // FIXME: can we safely swap the semantics of `fn base_local` below in here instead? pub fn local_or_deref_local(&self) -> Option { - match self { + match *self { PlaceRef { local, projection: [] } - | PlaceRef { local, projection: [ProjectionElem::Deref] } => Some(**local), + | PlaceRef { local, projection: [ProjectionElem::Deref] } => Some(local), _ => None, } } @@ -1836,8 +1836,8 @@ impl<'a, 'tcx> PlaceRef<'a, 'tcx> { /// If this place represents a local variable like `_X` with no /// projections, return `Some(_X)`. pub fn as_local(&self) -> Option { - match self { - PlaceRef { local, projection: [] } => Some(**local), + match *self { + PlaceRef { local, projection: [] } => Some(local), _ => None, } } diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs index c3affd233f8e3..2b5e00e321392 100644 --- a/src/librustc_codegen_ssa/mir/analyze.rs +++ b/src/librustc_codegen_ssa/mir/analyze.rs @@ -128,13 +128,13 @@ impl> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { }; if is_consume { let base_ty = - mir::Place::ty_from(place_ref.local, proj_base, *self.fx.mir, cx.tcx()); + mir::Place::ty_from(&place_ref.local, proj_base, *self.fx.mir, cx.tcx()); let base_ty = self.fx.monomorphize(&base_ty); // ZSTs don't require any actual memory access. let elem_ty = base_ty.projection_ty(cx.tcx(), elem).ty; let elem_ty = self.fx.monomorphize(&elem_ty); - let span = self.fx.mir.local_decls[*place_ref.local].source_info.span; + let span = self.fx.mir.local_decls[place_ref.local].source_info.span; if cx.spanned_layout_of(elem_ty, span).is_zst() { return; } @@ -174,7 +174,7 @@ impl> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { // We use `NonUseContext::VarDebugInfo` for the base, // which might not force the base local to memory, // so we have to do it manually. - self.visit_local(place_ref.local, context, location); + self.visit_local(&place_ref.local, context, location); } } @@ -212,8 +212,8 @@ impl> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { }; } - self.visit_place_base(place_ref.local, context, location); - self.visit_projection(place_ref.local, place_ref.projection, context, location); + self.visit_place_base(&place_ref.local, context, location); + self.visit_projection(&place_ref.local, place_ref.projection, context, location); } } } diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 339a6efb8351a..7f43e66549896 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -1111,7 +1111,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } else { self.codegen_place( bx, - mir::PlaceRef { local: &dest.local, projection: &dest.projection }, + mir::PlaceRef { local: dest.local, projection: &dest.projection }, ) }; if fn_ret.is_indirect() { diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index 363967510dc08..a33cd2ddad97b 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -373,7 +373,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ) -> Option> { debug!("maybe_codegen_consume_direct(place_ref={:?})", place_ref); - match self.locals[*place_ref.local] { + match self.locals[place_ref.local] { LocalRef::Operand(Some(mut o)) => { // Moves out of scalar and scalar pair fields are trivial. for elem in place_ref.projection.iter() { diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index 1fe9b6ed4b6bb..ff8871d21adc8 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -415,7 +415,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let tcx = self.cx.tcx(); let result = match place_ref { - mir::PlaceRef { local, projection: [] } => match self.locals[*local] { + mir::PlaceRef { local, projection: [] } => match self.locals[local] { LocalRef::Place(place) => { return place; } @@ -499,7 +499,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn monomorphized_place_ty(&self, place_ref: mir::PlaceRef<'_, 'tcx>) -> Ty<'tcx> { let tcx = self.cx.tcx(); - let place_ty = mir::Place::ty_from(place_ref.local, place_ref.projection, *self.mir, tcx); + let place_ty = mir::Place::ty_from(&place_ref.local, place_ref.projection, *self.mir, tcx); self.monomorphize(&place_ty.ty) } } diff --git a/src/librustc_mir/borrow_check/constraint_generation.rs b/src/librustc_mir/borrow_check/constraint_generation.rs index d85b55656ca20..19b7e0cf59bb4 100644 --- a/src/librustc_mir/borrow_check/constraint_generation.rs +++ b/src/librustc_mir/borrow_check/constraint_generation.rs @@ -199,7 +199,7 @@ impl<'cx, 'cg, 'tcx> ConstraintGeneration<'cx, 'cg, 'tcx> { all_facts, self.borrow_set, self.location_table, - *local, + local, location, ); } @@ -212,7 +212,7 @@ impl<'cx, 'cg, 'tcx> ConstraintGeneration<'cx, 'cg, 'tcx> { local, location ); - if let Some(borrow_indices) = self.borrow_set.local_map.get(local) { + if let Some(borrow_indices) = self.borrow_set.local_map.get(&local) { for &borrow_index in borrow_indices { let places_conflict = places_conflict::places_conflict( self.infcx.tcx, diff --git a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs index 08333ae423da7..5f27486298f82 100644 --- a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs @@ -186,7 +186,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } let ty = - Place::ty_from(used_place.local, used_place.projection, *self.body, self.infcx.tcx) + Place::ty_from(&used_place.local, used_place.projection, *self.body, self.infcx.tcx) .ty; let needs_note = match ty.kind { ty::Closure(id, _) => { @@ -605,7 +605,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { match elem { ProjectionElem::Field(field, _) if union_ty(local, proj_base).is_some() => { - return Some((PlaceRef { local, projection: proj_base }, field)); + return Some((PlaceRef { local: *local, projection: proj_base }, field)); } _ => {} } @@ -624,12 +624,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if let ProjectionElem::Field(field, _) = elem { if let Some(union_ty) = union_ty(local, proj_base) { if field != target_field - && local == target_base.local + && *local == target_base.local && proj_base == target_base.projection { // FIXME when we avoid clone reuse describe_place closure let describe_base_place = self - .describe_place(PlaceRef { local, projection: proj_base }) + .describe_place(PlaceRef { local: *local, projection: proj_base }) .unwrap_or_else(|| "_".to_owned()); return Some(( @@ -686,7 +686,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let borrow_span = borrow_spans.var_or_use(); assert!(root_place.projection.is_empty()); - let proper_span = self.body.local_decls[*root_place.local].source_info.span; + let proper_span = self.body.local_decls[root_place.local].source_info.span; let root_place_projection = self.infcx.tcx.intern_place_elems(root_place.projection); @@ -1139,7 +1139,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let root_place = self.prefixes(borrow.borrowed_place.as_ref(), PrefixSet::All).last().unwrap(); let local = root_place.local; - match self.body.local_kind(*local) { + match self.body.local_kind(local) { LocalKind::ReturnPointer | LocalKind::Temp => { ("temporary value".to_string(), "temporary value created here".to_string()) } diff --git a/src/librustc_mir/borrow_check/diagnostics/mod.rs b/src/librustc_mir/borrow_check/diagnostics/mod.rs index 0fc73d33f9001..1540e5bf420e2 100644 --- a/src/librustc_mir/borrow_check/diagnostics/mod.rs +++ b/src/librustc_mir/borrow_check/diagnostics/mod.rs @@ -169,10 +169,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ) -> Result<(), ()> { match place { PlaceRef { local, projection: [] } => { - self.append_local_to_string(*local, buf)?; + self.append_local_to_string(local, buf)?; } PlaceRef { local, projection: [ProjectionElem::Deref] } - if self.body.local_decls[*local].is_ref_for_guard() => + if self.body.local_decls[local].is_ref_for_guard() => { self.append_place_to_string( PlaceRef { local: local, projection: &[] }, @@ -182,9 +182,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { )?; } PlaceRef { local, projection: [ProjectionElem::Deref] } - if self.body.local_decls[*local].is_ref_to_static() => + if self.body.local_decls[local].is_ref_to_static() => { - let local_info = &self.body.local_decls[*local].local_info; + let local_info = &self.body.local_decls[local].local_info; if let LocalInfo::StaticRef { def_id, .. } = *local_info { buf.push_str(&self.infcx.tcx.item_name(def_id).as_str()); } else { @@ -307,7 +307,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // FIXME Place2 Make this work iteratively match place { PlaceRef { local, projection: [] } => { - let local = &self.body.local_decls[*local]; + let local = &self.body.local_decls[local]; self.describe_field_from_ty(&local.ty, field, None) } PlaceRef { local, projection: [proj_base @ .., elem] } => match elem { @@ -316,7 +316,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } ProjectionElem::Downcast(_, variant_index) => { let base_ty = - Place::ty_from(place.local, place.projection, *self.body, self.infcx.tcx) + Place::ty_from(&place.local, place.projection, *self.body, self.infcx.tcx) .ty; self.describe_field_from_ty(&base_ty, field, Some(*variant_index)) } @@ -447,7 +447,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // If we didn't find an overloaded deref or index, then assume it's a // built in deref and check the type of the base. - let base_ty = Place::ty_from(deref_base.local, deref_base.projection, *self.body, tcx).ty; + let base_ty = Place::ty_from(&deref_base.local, deref_base.projection, *self.body, tcx).ty; if base_ty.is_unsafe_ptr() { BorrowedContentSource::DerefRawPointer } else if base_ty.is_mutable_ptr() { diff --git a/src/librustc_mir/borrow_check/diagnostics/move_errors.rs b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs index eb6db7c145c3c..f438485d575eb 100644 --- a/src/librustc_mir/borrow_check/diagnostics/move_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs @@ -274,7 +274,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { format!("static item `{}`", self.describe_place(place.as_ref()).unwrap()) } else { let base_static = - PlaceRef { local: &place.local, projection: &[ProjectionElem::Deref] }; + PlaceRef { local: place.local, projection: &[ProjectionElem::Deref] }; format!( "`{:?}` as `{:?}` is a static item", @@ -303,17 +303,17 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let deref_base = match deref_target_place.projection.as_ref() { &[ref proj_base @ .., ProjectionElem::Deref] => { - PlaceRef { local: &deref_target_place.local, projection: &proj_base } + PlaceRef { local: deref_target_place.local, projection: &proj_base } } _ => bug!("deref_target_place is not a deref projection"), }; if let PlaceRef { local, projection: [] } = deref_base { - let decl = &self.body.local_decls[*local]; + let decl = &self.body.local_decls[local]; if decl.is_ref_for_guard() { let mut err = self.cannot_move_out_of( span, - &format!("`{}` in pattern guard", self.local_names[*local].unwrap()), + &format!("`{}` in pattern guard", self.local_names[local].unwrap()), ); err.note( "variables bound in patterns cannot be moved from \ diff --git a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs index ae468e83ae253..4e2517211c86c 100644 --- a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs @@ -47,7 +47,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if access_place.as_local().is_some() { reason = ", as it is not declared as mutable".to_string(); } else { - let name = self.local_names[*local].expect("immutable unnamed local"); + let name = self.local_names[local].expect("immutable unnamed local"); reason = format!(", as `{}` is not declared as mutable", name); } } @@ -57,7 +57,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { projection: [proj_base @ .., ProjectionElem::Field(upvar_index, _)], } => { debug_assert!(is_closure_or_generator( - Place::ty_from(local, proj_base, *self.body, self.infcx.tcx).ty + Place::ty_from(&local, proj_base, *self.body, self.infcx.tcx).ty )); item_msg = format!("`{}`", access_place_desc.unwrap()); @@ -70,20 +70,20 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } PlaceRef { local, projection: [ProjectionElem::Deref] } - if self.body.local_decls[*local].is_ref_for_guard() => + if self.body.local_decls[local].is_ref_for_guard() => { item_msg = format!("`{}`", access_place_desc.unwrap()); reason = ", as it is immutable for the pattern guard".to_string(); } PlaceRef { local, projection: [ProjectionElem::Deref] } - if self.body.local_decls[*local].is_ref_to_static() => + if self.body.local_decls[local].is_ref_to_static() => { if access_place.projection.len() == 1 { item_msg = format!("immutable static item `{}`", access_place_desc.unwrap()); reason = String::new(); } else { item_msg = format!("`{}`", access_place_desc.unwrap()); - let local_info = &self.body.local_decls[*local].local_info; + let local_info = &self.body.local_decls[local].local_info; if let LocalInfo::StaticRef { def_id, .. } = *local_info { let static_name = &self.infcx.tcx.item_name(def_id); reason = format!(", as `{}` is an immutable static item", static_name); @@ -93,7 +93,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } } PlaceRef { local: _, projection: [proj_base @ .., ProjectionElem::Deref] } => { - if *the_place_err.local == Local::new(1) + if the_place_err.local == Local::new(1) && proj_base.is_empty() && !self.upvars.is_empty() { @@ -101,7 +101,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { debug_assert!(self.body.local_decls[Local::new(1)].ty.is_region_ptr()); debug_assert!(is_closure_or_generator( Place::ty_from( - the_place_err.local, + &the_place_err.local, the_place_err.projection, *self.body, self.infcx.tcx @@ -195,7 +195,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if let Some((span, message)) = annotate_struct_field( self.infcx.tcx, - Place::ty_from(local, proj_base, *self.body, self.infcx.tcx).ty, + Place::ty_from(&local, proj_base, *self.body, self.infcx.tcx).ty, field, ) { err.span_suggestion( @@ -212,7 +212,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if { self.body .local_decls - .get(*local) + .get(local) .map(|local_decl| { if let LocalInfo::User(ClearCrossCrate::Set( mir::BindingForm::ImplicitSelf(kind), @@ -224,7 +224,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // Deliberately fall into this case for all implicit self types, // so that we don't fall in to the next case with them. kind == mir::ImplicitSelfKind::MutRef - } else if Some(kw::SelfLower) == self.local_names[*local] { + } else if Some(kw::SelfLower) == self.local_names[local] { // Otherwise, check if the name is the self kewyord - in which case // we have an explicit self. Do the same thing in this case and check // for a `self: &mut Self` to suggest removing the `&mut`. @@ -247,20 +247,20 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // We want to suggest users use `let mut` for local (user // variable) mutations... PlaceRef { local, projection: [] } - if self.body.local_decls[*local].can_be_made_mutable() => + if self.body.local_decls[local].can_be_made_mutable() => { // ... but it doesn't make sense to suggest it on // variables that are `ref x`, `ref mut x`, `&self`, // or `&mut self` (such variables are simply not // mutable). - let local_decl = &self.body.local_decls[*local]; + let local_decl = &self.body.local_decls[local]; assert_eq!(local_decl.mutability, Mutability::Not); err.span_label(span, format!("cannot {ACT}", ACT = act)); err.span_suggestion( local_decl.source_info.span, "consider changing this to be mutable", - format!("mut {}", self.local_names[*local].unwrap()), + format!("mut {}", self.local_names[local].unwrap()), Applicability::MachineApplicable, ); } @@ -271,7 +271,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { projection: [proj_base @ .., ProjectionElem::Field(upvar_index, _)], } => { debug_assert!(is_closure_or_generator( - Place::ty_from(local, proj_base, *self.body, self.infcx.tcx).ty + Place::ty_from(&local, proj_base, *self.body, self.infcx.tcx).ty )); err.span_label(span, format!("cannot {ACT}", ACT = act)); @@ -312,7 +312,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } PlaceRef { local, projection: [ProjectionElem::Deref] } - if self.body.local_decls[*local].is_ref_for_guard() => + if self.body.local_decls[local].is_ref_for_guard() => { err.span_label(span, format!("cannot {ACT}", ACT = act)); err.note( @@ -326,9 +326,9 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // FIXME: can this case be generalized to work for an // arbitrary base for the projection? PlaceRef { local, projection: [ProjectionElem::Deref] } - if self.body.local_decls[*local].is_user_variable() => + if self.body.local_decls[local].is_user_variable() => { - let local_decl = &self.body.local_decls[*local]; + let local_decl = &self.body.local_decls[local]; let suggestion = match local_decl.local_info { LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::ImplicitSelf(_))) => { Some(suggest_ampmut_self(self.infcx.tcx, local_decl)) @@ -343,7 +343,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { ))) => Some(suggest_ampmut( self.infcx.tcx, self.body, - *local, + local, local_decl, opt_ty_info, )), @@ -379,7 +379,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { ); } - match self.local_names[*local] { + match self.local_names[local] { Some(name) if !local_decl.from_compiler_desugaring() => { err.span_label( span, @@ -411,7 +411,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { local, projection: [ProjectionElem::Deref], // FIXME document what is this 1 magic number about - } if *local == Local::new(1) && !self.upvars.is_empty() => { + } if local == Local::new(1) && !self.upvars.is_empty() => { err.span_label(span, format!("cannot {ACT}", ACT = act)); err.span_help( self.body.span, diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 90927069242b1..003e61f0ef434 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -823,7 +823,7 @@ enum InitializationRequiringAction { } struct RootPlace<'d, 'tcx> { - place_local: &'d Local, + place_local: Local, place_projection: &'d [PlaceElem<'tcx>], is_local_mutation_allowed: LocalMutationIsAllowed, } @@ -1384,7 +1384,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { debug!("check_for_invalidation_at_exit({:?})", borrow); let place = &borrow.borrowed_place; let deref = [ProjectionElem::Deref]; - let mut root_place = PlaceRef { local: &place.local, projection: &[] }; + let mut root_place = PlaceRef { local: place.local, projection: &[] }; // FIXME(nll-rfc#40): do more precise destructor tracking here. For now // we just know that all locals are dropped at function exit (otherwise @@ -1393,7 +1393,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // FIXME: allow thread-locals to borrow other thread locals? let (might_be_alive, will_be_dropped) = - if self.body.local_decls[*root_place.local].is_ref_to_thread_local() { + if self.body.local_decls[root_place.local].is_ref_to_thread_local() { // Thread-locals might be dropped after the function exits // We have to dereference the outer reference because // borrows don't conflict behind shared references. @@ -1625,7 +1625,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { place_span.0.projection { let place_ty = - Place::ty_from(place_span.0.local, base_proj, self.body(), self.infcx.tcx); + Place::ty_from(&place_span.0.local, base_proj, self.body(), self.infcx.tcx); if let ty::Array(..) = place_ty.ty.kind { let array_place = PlaceRef { local: place_span.0.local, projection: base_proj }; self.check_if_subslice_element_is_moved( @@ -1724,7 +1724,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.check_if_full_path_is_moved( location, InitializationRequiringAction::Use, (PlaceRef { - local: &place.local, + local: place.local, projection: proj_base, }, span), flow_state); // (base initialized; no need to @@ -1748,7 +1748,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.check_if_path_or_subpath_is_moved( location, InitializationRequiringAction::Assignment, (PlaceRef { - local: &place.local, + local: place.local, projection: proj_base, }, span), flow_state); @@ -1761,7 +1761,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // is allowed, remove this match arm. ty::Adt(..) | ty::Tuple(..) => { check_parent_of_field(self, location, PlaceRef { - local: &place.local, + local: place.local, projection: proj_base, }, span, flow_state); @@ -1846,7 +1846,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // of the union - we should error in that case. let tcx = this.infcx.tcx; if let ty::Adt(def, _) = - Place::ty_from(base.local, base.projection, this.body(), tcx).ty.kind + Place::ty_from(&base.local, base.projection, this.body(), tcx).ty.kind { if def.is_union() { if this.move_data.path_map[mpi].iter().any(|moi| { @@ -2000,9 +2000,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // mutated, then it is justified to be annotated with the `mut` // keyword, since the mutation may be a possible reassignment. if is_local_mutation_allowed != LocalMutationIsAllowed::Yes - && self.is_local_ever_initialized(*local, flow_state).is_some() + && self.is_local_ever_initialized(local, flow_state).is_some() { - self.used_mut.insert(*local); + self.used_mut.insert(local); } } RootPlace { @@ -2034,7 +2034,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ) -> Result, PlaceRef<'d, 'tcx>> { match place { PlaceRef { local, projection: [] } => { - let local = &self.body.local_decls[*local]; + let local = &self.body.local_decls[local]; match local.mutability { Mutability::Not => match is_local_mutation_allowed { LocalMutationIsAllowed::Yes => Ok(RootPlace { @@ -2060,7 +2060,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { match elem { ProjectionElem::Deref => { let base_ty = - Place::ty_from(place.local, proj_base, self.body(), self.infcx.tcx).ty; + Place::ty_from(&place.local, proj_base, self.body(), self.infcx.tcx).ty; // Check the kind of deref to decide match base_ty.kind { @@ -2194,7 +2194,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { match place_projection { [base @ .., ProjectionElem::Field(field, _ty)] => { let tcx = self.infcx.tcx; - let base_ty = Place::ty_from(place_ref.local, base, self.body(), tcx).ty; + let base_ty = Place::ty_from(&place_ref.local, base, self.body(), tcx).ty; if (base_ty.is_closure() || base_ty.is_generator()) && (!by_ref || self.upvars[field.index()].by_ref) diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs index 6b1cdaf9b383c..196768905676f 100644 --- a/src/librustc_mir/borrow_check/places_conflict.rs +++ b/src/librustc_mir/borrow_check/places_conflict.rs @@ -122,7 +122,7 @@ fn place_components_conflict<'tcx>( let borrow_local = borrow_place.local; let access_local = access_place.local; - match place_base_conflict(borrow_local, *access_local) { + match place_base_conflict(borrow_local, access_local) { Overlap::Arbitrary => { bug!("Two base can't return Arbitrary"); } diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs index 31bee460fa011..9aa2b98cbb156 100644 --- a/src/librustc_mir/borrow_check/prefixes.rs +++ b/src/librustc_mir/borrow_check/prefixes.rs @@ -120,7 +120,7 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> { // derefs, except we stop at the deref of a shared // reference. - let ty = Place::ty_from(cursor.local, proj_base, *self.body, self.tcx).ty; + let ty = Place::ty_from(&cursor.local, proj_base, *self.body, self.tcx).ty; match ty.kind { ty::RawPtr(_) | ty::Ref(_ /*rgn*/, _ /*ty*/, hir::Mutability::Not) => { // don't continue traversing over derefs of raw pointers or shared diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs index 271bcce6ca53c..eecb9f633bf60 100644 --- a/src/librustc_mir/dataflow/move_paths/builder.rs +++ b/src/librustc_mir/dataflow/move_paths/builder.rs @@ -492,7 +492,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { // of the union so it is marked as initialized again. if let [proj_base @ .., ProjectionElem::Field(_, _)] = place.projection { if let ty::Adt(def, _) = - Place::ty_from(place.local, proj_base, self.builder.body, self.builder.tcx).ty.kind + Place::ty_from(&place.local, proj_base, self.builder.body, self.builder.tcx).ty.kind { if def.is_union() { place = PlaceRef { local: place.local, projection: proj_base } diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs index a46465ab49376..8d62b84bda8f0 100644 --- a/src/librustc_mir/dataflow/move_paths/mod.rs +++ b/src/librustc_mir/dataflow/move_paths/mod.rs @@ -246,7 +246,7 @@ impl MovePathLookup { // unknown place, but will rather return the nearest available // parent. pub fn find(&self, place: PlaceRef<'_, '_>) -> LookupResult { - let mut result = self.locals[*place.local]; + let mut result = self.locals[place.local]; for elem in place.projection.iter() { if let Some(&subpath) = self.projections.get(&(result, elem.lift())) { diff --git a/src/librustc_mir/transform/check_consts/qualifs.rs b/src/librustc_mir/transform/check_consts/qualifs.rs index 577736f9bd11d..96bc9c3b22587 100644 --- a/src/librustc_mir/transform/check_consts/qualifs.rs +++ b/src/librustc_mir/transform/check_consts/qualifs.rs @@ -46,7 +46,7 @@ pub trait Qualif { let qualif = base_qualif && Self::in_any_value_of_ty( cx, - Place::ty_from(place.local, proj_base, *cx.body, cx.tcx) + Place::ty_from(&place.local, proj_base, *cx.body, cx.tcx) .projection_ty(cx.tcx, elem) .ty, ); @@ -78,7 +78,7 @@ pub trait Qualif { place: PlaceRef<'_, 'tcx>, ) -> bool { match place { - PlaceRef { local, projection: [] } => per_local(*local), + PlaceRef { local, projection: [] } => per_local(local), PlaceRef { local: _, projection: [.., _] } => Self::in_projection(cx, per_local, place), } } @@ -154,7 +154,7 @@ pub trait Qualif { return Self::in_place( cx, per_local, - PlaceRef { local: &place.local, projection: proj_base }, + PlaceRef { local: place.local, projection: proj_base }, ); } } diff --git a/src/librustc_mir/transform/check_consts/resolver.rs b/src/librustc_mir/transform/check_consts/resolver.rs index 2cd2495eef8a2..eac60029784d2 100644 --- a/src/librustc_mir/transform/check_consts/resolver.rs +++ b/src/librustc_mir/transform/check_consts/resolver.rs @@ -48,7 +48,7 @@ where match (value, place.as_ref()) { (true, mir::PlaceRef { local, .. }) => { - self.qualifs_per_local.insert(*local); + self.qualifs_per_local.insert(local); } // For now, we do not clear the qualif if a local is overwritten in full by diff --git a/src/librustc_mir/transform/instcombine.rs b/src/librustc_mir/transform/instcombine.rs index afe42e6357128..1d2917a808ea2 100644 --- a/src/librustc_mir/transform/instcombine.rs +++ b/src/librustc_mir/transform/instcombine.rs @@ -95,7 +95,7 @@ impl Visitor<'tcx> for OptimizationFinder<'b, 'tcx> { if let PlaceRef { local, projection: &[ref proj_base @ .., ProjectionElem::Deref] } = place.as_ref() { - if Place::ty_from(local, proj_base, self.body, self.tcx).ty.is_region_ptr() { + if Place::ty_from(&local, proj_base, self.body, self.tcx).ty.is_region_ptr() { self.optimizations.and_stars.insert(location); } } diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index f058ac834ef34..c1aa4aa786719 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -475,7 +475,7 @@ impl<'tcx> Validator<'_, 'tcx> { fn validate_place(&self, place: PlaceRef<'_, 'tcx>) -> Result<(), Unpromotable> { match place { - PlaceRef { local, projection: [] } => self.validate_local(*local), + PlaceRef { local, projection: [] } => self.validate_local(local), PlaceRef { local: _, projection: [proj_base @ .., elem] } => { match *elem { ProjectionElem::Deref | ProjectionElem::Downcast(..) => { @@ -491,7 +491,7 @@ impl<'tcx> Validator<'_, 'tcx> { ProjectionElem::Field(..) => { if self.const_kind.is_none() { let base_ty = - Place::ty_from(place.local, proj_base, *self.body, self.tcx).ty; + Place::ty_from(&place.local, proj_base, *self.body, self.tcx).ty; if let Some(def) = base_ty.ty_adt_def() { // No promotion of union field accesses. if def.is_union() { @@ -592,7 +592,7 @@ impl<'tcx> Validator<'_, 'tcx> { let base_ty = Place::ty_from(&place.local, proj_base, *self.body, self.tcx).ty; if let ty::Ref(..) = base_ty.kind { return self.validate_place(PlaceRef { - local: &place.local, + local: place.local, projection: proj_base, }); } @@ -630,7 +630,7 @@ impl<'tcx> Validator<'_, 'tcx> { if let [proj_base @ .., ProjectionElem::Deref] = &place.projection { let base_ty = Place::ty_from(&place.local, proj_base, *self.body, self.tcx).ty; if let ty::Ref(..) = base_ty.kind { - place = PlaceRef { local: &place.local, projection: proj_base }; + place = PlaceRef { local: place.local, projection: proj_base }; } } @@ -640,14 +640,14 @@ impl<'tcx> Validator<'_, 'tcx> { // `::in_projection` from // `check_consts::qualifs` but without recursion. let mut has_mut_interior = - self.qualif_local::(*place.local); + self.qualif_local::(place.local); if has_mut_interior { let mut place_projection = place.projection; // FIXME(eddyb) use a forward loop instead of a reverse one. while let [proj_base @ .., elem] = place_projection { // FIXME(eddyb) this is probably excessive, with // the exception of `union` member accesses. - let ty = Place::ty_from(place.local, proj_base, *self.body, self.tcx) + let ty = Place::ty_from(&place.local, proj_base, *self.body, self.tcx) .projection_ty(self.tcx, elem) .ty; if ty.is_freeze(self.tcx, self.param_env, DUMMY_SP) { diff --git a/src/librustc_mir/transform/simplify_try.rs b/src/librustc_mir/transform/simplify_try.rs index e733b0a5b5928..bd661195a4852 100644 --- a/src/librustc_mir/transform/simplify_try.rs +++ b/src/librustc_mir/transform/simplify_try.rs @@ -139,7 +139,7 @@ fn match_variant_field_place<'tcx>(place: &Place<'tcx>) -> Option<(Local, VarFie PlaceRef { local, projection: &[ProjectionElem::Downcast(_, var_idx), ProjectionElem::Field(field, ty)], - } => Some((*local, VarField { field, field_ty: ty, var_idx })), + } => Some((local, VarField { field, field_ty: ty, var_idx })), _ => None, } } diff --git a/src/librustc_mir_build/build/expr/as_rvalue.rs b/src/librustc_mir_build/build/expr/as_rvalue.rs index 5959b85225674..16795b459b6bd 100644 --- a/src/librustc_mir_build/build/expr/as_rvalue.rs +++ b/src/librustc_mir_build/build/expr/as_rvalue.rs @@ -393,20 +393,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let arg_place = unpack!(block = this.as_place(block, arg)); let mutability = match arg_place.as_ref() { - PlaceRef { local, projection: &[] } => this.local_decls[*local].mutability, + PlaceRef { local, projection: &[] } => this.local_decls[local].mutability, PlaceRef { local, projection: &[ProjectionElem::Deref] } => { debug_assert!( - this.local_decls[*local].is_ref_for_guard(), + this.local_decls[local].is_ref_for_guard(), "Unexpected capture place", ); - this.local_decls[*local].mutability + this.local_decls[local].mutability } PlaceRef { - ref local, + local, projection: &[ref proj_base @ .., ProjectionElem::Field(upvar_index, _)], } | PlaceRef { - ref local, + local, projection: &[ref proj_base @ .., ProjectionElem::Field(upvar_index, _), ProjectionElem::Deref], } => { diff --git a/src/librustc_mir_build/build/matches/mod.rs b/src/librustc_mir_build/build/matches/mod.rs index f9f10b55495fa..1dd334e278133 100644 --- a/src/librustc_mir_build/build/matches/mod.rs +++ b/src/librustc_mir_build/build/matches/mod.rs @@ -1241,7 +1241,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Insert a shallow borrow after a deref. For other // projections the borrow of prefix_cursor will // conflict with any mutation of base. - all_fake_borrows.push(PlaceRef { local: &place.local, projection: proj_base }); + all_fake_borrows.push(PlaceRef { local: place.local, projection: proj_base }); } } From e51b5a45cc542aef3e3def8786c6e7375a32cec1 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 14 Jan 2020 02:21:42 -0300 Subject: [PATCH 07/17] Place::ty_from takes local by value --- src/librustc/mir/tcx.rs | 6 +++--- src/librustc_codegen_ssa/mir/analyze.rs | 2 +- src/librustc_codegen_ssa/mir/place.rs | 2 +- .../borrow_check/diagnostics/conflict_errors.rs | 10 +++++----- src/librustc_mir/borrow_check/diagnostics/mod.rs | 4 ++-- .../borrow_check/diagnostics/mutability_errors.rs | 8 ++++---- src/librustc_mir/borrow_check/mod.rs | 10 +++++----- src/librustc_mir/borrow_check/place_ext.rs | 2 +- src/librustc_mir/borrow_check/places_conflict.rs | 4 ++-- src/librustc_mir/borrow_check/prefixes.rs | 2 +- src/librustc_mir/borrow_check/type_check/mod.rs | 2 +- src/librustc_mir/dataflow/move_paths/builder.rs | 4 ++-- src/librustc_mir/transform/check_consts/qualifs.rs | 4 ++-- src/librustc_mir/transform/check_consts/validation.rs | 6 +++--- src/librustc_mir/transform/check_unsafety.rs | 6 +++--- src/librustc_mir/transform/instcombine.rs | 2 +- src/librustc_mir/transform/promote_consts.rs | 10 +++++----- src/librustc_mir/transform/qualify_min_const_fn.rs | 2 +- src/librustc_mir/util/alignment.rs | 2 +- src/librustc_mir_build/build/expr/as_place.rs | 6 +++--- 20 files changed, 47 insertions(+), 47 deletions(-) diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index e2aac562cc4cc..e6c7c84494cd8 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -114,7 +114,7 @@ impl<'tcx> PlaceTy<'tcx> { impl<'tcx> Place<'tcx> { pub fn ty_from( - local: &Local, + local: Local, projection: &[PlaceElem<'tcx>], local_decls: &D, tcx: TyCtxt<'tcx>, @@ -124,7 +124,7 @@ impl<'tcx> Place<'tcx> { { projection .iter() - .fold(PlaceTy::from_ty(local_decls.local_decls()[*local].ty), |place_ty, elem| { + .fold(PlaceTy::from_ty(local_decls.local_decls()[local].ty), |place_ty, elem| { place_ty.projection_ty(tcx, elem) }) } @@ -133,7 +133,7 @@ impl<'tcx> Place<'tcx> { where D: HasLocalDecls<'tcx>, { - Place::ty_from(&self.local, &self.projection, local_decls, tcx) + Place::ty_from(self.local, &self.projection, local_decls, tcx) } } diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs index 2b5e00e321392..d4b0ab0448a8b 100644 --- a/src/librustc_codegen_ssa/mir/analyze.rs +++ b/src/librustc_codegen_ssa/mir/analyze.rs @@ -128,7 +128,7 @@ impl> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { }; if is_consume { let base_ty = - mir::Place::ty_from(&place_ref.local, proj_base, *self.fx.mir, cx.tcx()); + mir::Place::ty_from(place_ref.local, proj_base, *self.fx.mir, cx.tcx()); let base_ty = self.fx.monomorphize(&base_ty); // ZSTs don't require any actual memory access. diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index ff8871d21adc8..fa82daa0f7d52 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -499,7 +499,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn monomorphized_place_ty(&self, place_ref: mir::PlaceRef<'_, 'tcx>) -> Ty<'tcx> { let tcx = self.cx.tcx(); - let place_ty = mir::Place::ty_from(&place_ref.local, place_ref.projection, *self.mir, tcx); + let place_ty = mir::Place::ty_from(place_ref.local, place_ref.projection, *self.mir, tcx); self.monomorphize(&place_ty.ty) } } diff --git a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs index 5f27486298f82..a14e034cfc197 100644 --- a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs @@ -186,7 +186,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } let ty = - Place::ty_from(&used_place.local, used_place.projection, *self.body, self.infcx.tcx) + Place::ty_from(used_place.local, used_place.projection, *self.body, self.infcx.tcx) .ty; let needs_note = match ty.kind { ty::Closure(id, _) => { @@ -604,7 +604,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { cursor = proj_base; match elem { - ProjectionElem::Field(field, _) if union_ty(local, proj_base).is_some() => { + ProjectionElem::Field(field, _) if union_ty(*local, proj_base).is_some() => { return Some((PlaceRef { local: *local, projection: proj_base }, field)); } _ => {} @@ -622,7 +622,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { cursor = proj_base; if let ProjectionElem::Field(field, _) = elem { - if let Some(union_ty) = union_ty(local, proj_base) { + if let Some(union_ty) = union_ty(*local, proj_base) { if field != target_field && *local == target_base.local && proj_base == target_base.projection @@ -1513,7 +1513,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { StorageDeadOrDrop::LocalStorageDead | StorageDeadOrDrop::BoxedStorageDead => { assert!( - Place::ty_from(&place.local, proj_base, *self.body, tcx) + Place::ty_from(place.local, proj_base, *self.body, tcx) .ty .is_box(), "Drop of value behind a reference or raw pointer" @@ -1523,7 +1523,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { StorageDeadOrDrop::Destructor(_) => base_access, }, ProjectionElem::Field(..) | ProjectionElem::Downcast(..) => { - let base_ty = Place::ty_from(&place.local, proj_base, *self.body, tcx).ty; + let base_ty = Place::ty_from(place.local, proj_base, *self.body, tcx).ty; match base_ty.kind { ty::Adt(def, _) if def.has_dtor(tcx) => { // Report the outermost adt with a destructor diff --git a/src/librustc_mir/borrow_check/diagnostics/mod.rs b/src/librustc_mir/borrow_check/diagnostics/mod.rs index 1540e5bf420e2..ba4af59eede06 100644 --- a/src/librustc_mir/borrow_check/diagnostics/mod.rs +++ b/src/librustc_mir/borrow_check/diagnostics/mod.rs @@ -316,7 +316,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } ProjectionElem::Downcast(_, variant_index) => { let base_ty = - Place::ty_from(&place.local, place.projection, *self.body, self.infcx.tcx) + Place::ty_from(place.local, place.projection, *self.body, self.infcx.tcx) .ty; self.describe_field_from_ty(&base_ty, field, Some(*variant_index)) } @@ -447,7 +447,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // If we didn't find an overloaded deref or index, then assume it's a // built in deref and check the type of the base. - let base_ty = Place::ty_from(&deref_base.local, deref_base.projection, *self.body, tcx).ty; + let base_ty = Place::ty_from(deref_base.local, deref_base.projection, *self.body, tcx).ty; if base_ty.is_unsafe_ptr() { BorrowedContentSource::DerefRawPointer } else if base_ty.is_mutable_ptr() { diff --git a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs index 4e2517211c86c..563ff1112c3a6 100644 --- a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs @@ -57,7 +57,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { projection: [proj_base @ .., ProjectionElem::Field(upvar_index, _)], } => { debug_assert!(is_closure_or_generator( - Place::ty_from(&local, proj_base, *self.body, self.infcx.tcx).ty + Place::ty_from(local, proj_base, *self.body, self.infcx.tcx).ty )); item_msg = format!("`{}`", access_place_desc.unwrap()); @@ -101,7 +101,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { debug_assert!(self.body.local_decls[Local::new(1)].ty.is_region_ptr()); debug_assert!(is_closure_or_generator( Place::ty_from( - &the_place_err.local, + the_place_err.local, the_place_err.projection, *self.body, self.infcx.tcx @@ -195,7 +195,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if let Some((span, message)) = annotate_struct_field( self.infcx.tcx, - Place::ty_from(&local, proj_base, *self.body, self.infcx.tcx).ty, + Place::ty_from(local, proj_base, *self.body, self.infcx.tcx).ty, field, ) { err.span_suggestion( @@ -271,7 +271,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { projection: [proj_base @ .., ProjectionElem::Field(upvar_index, _)], } => { debug_assert!(is_closure_or_generator( - Place::ty_from(&local, proj_base, *self.body, self.infcx.tcx).ty + Place::ty_from(local, proj_base, *self.body, self.infcx.tcx).ty )); err.span_label(span, format!("cannot {ACT}", ACT = act)); diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 003e61f0ef434..b89b6a43fa5a2 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -1625,7 +1625,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { place_span.0.projection { let place_ty = - Place::ty_from(&place_span.0.local, base_proj, self.body(), self.infcx.tcx); + Place::ty_from(place_span.0.local, base_proj, self.body(), self.infcx.tcx); if let ty::Array(..) = place_ty.ty.kind { let array_place = PlaceRef { local: place_span.0.local, projection: base_proj }; self.check_if_subslice_element_is_moved( @@ -1742,7 +1742,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // assigning to `P.f` requires `P` itself // be already initialized let tcx = self.infcx.tcx; - let base_ty = Place::ty_from(&place.local, proj_base, self.body(), tcx).ty; + let base_ty = Place::ty_from(place.local, proj_base, self.body(), tcx).ty; match base_ty.kind { ty::Adt(def, _) if def.has_dtor(tcx) => { self.check_if_path_or_subpath_is_moved( @@ -1846,7 +1846,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // of the union - we should error in that case. let tcx = this.infcx.tcx; if let ty::Adt(def, _) = - Place::ty_from(&base.local, base.projection, this.body(), tcx).ty.kind + Place::ty_from(base.local, base.projection, this.body(), tcx).ty.kind { if def.is_union() { if this.move_data.path_map[mpi].iter().any(|moi| { @@ -2060,7 +2060,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { match elem { ProjectionElem::Deref => { let base_ty = - Place::ty_from(&place.local, proj_base, self.body(), self.infcx.tcx).ty; + Place::ty_from(place.local, proj_base, self.body(), self.infcx.tcx).ty; // Check the kind of deref to decide match base_ty.kind { @@ -2194,7 +2194,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { match place_projection { [base @ .., ProjectionElem::Field(field, _ty)] => { let tcx = self.infcx.tcx; - let base_ty = Place::ty_from(&place_ref.local, base, self.body(), tcx).ty; + let base_ty = Place::ty_from(place_ref.local, base, self.body(), tcx).ty; if (base_ty.is_closure() || base_ty.is_generator()) && (!by_ref || self.upvars[field.index()].by_ref) diff --git a/src/librustc_mir/borrow_check/place_ext.rs b/src/librustc_mir/borrow_check/place_ext.rs index ac02da2661586..01c44d0d905b6 100644 --- a/src/librustc_mir/borrow_check/place_ext.rs +++ b/src/librustc_mir/borrow_check/place_ext.rs @@ -48,7 +48,7 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> { let proj_base = &self.projection[..i]; if *elem == ProjectionElem::Deref { - let ty = Place::ty_from(&self.local, proj_base, body, tcx).ty; + let ty = Place::ty_from(self.local, proj_base, body, tcx).ty; match ty.kind { ty::Ref(_, _, hir::Mutability::Not) if i == 0 => { // For references to thread-local statics, we do need diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs index 196768905676f..984de021ca112 100644 --- a/src/librustc_mir/borrow_check/places_conflict.rs +++ b/src/librustc_mir/borrow_check/places_conflict.rs @@ -208,7 +208,7 @@ fn place_components_conflict<'tcx>( // access cares about. let proj_base = &borrow_place.projection[..access_place.projection.len() + i]; - let base_ty = Place::ty_from(&borrow_local, proj_base, body, tcx).ty; + let base_ty = Place::ty_from(borrow_local, proj_base, body, tcx).ty; match (elem, &base_ty.kind, access) { (_, _, Shallow(Some(ArtificialField::ArrayLength))) @@ -329,7 +329,7 @@ fn place_projection_conflict<'tcx>( debug!("place_element_conflict: DISJOINT-OR-EQ-FIELD"); Overlap::EqualOrDisjoint } else { - let ty = Place::ty_from(&pi1_local, pi1_proj_base, body, tcx).ty; + let ty = Place::ty_from(pi1_local, pi1_proj_base, body, tcx).ty; match ty.kind { ty::Adt(def, _) if def.is_union() => { // Different fields of a union, we are basically stuck. diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs index 9aa2b98cbb156..31bee460fa011 100644 --- a/src/librustc_mir/borrow_check/prefixes.rs +++ b/src/librustc_mir/borrow_check/prefixes.rs @@ -120,7 +120,7 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> { // derefs, except we stop at the deref of a shared // reference. - let ty = Place::ty_from(&cursor.local, proj_base, *self.body, self.tcx).ty; + let ty = Place::ty_from(cursor.local, proj_base, *self.body, self.tcx).ty; match ty.kind { ty::RawPtr(_) | ty::Ref(_ /*rgn*/, _ /*ty*/, hir::Mutability::Not) => { // don't continue traversing over derefs of raw pointers or shared diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index c9a1c465165d7..f645435cdf60f 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -2390,7 +2390,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { match elem { ProjectionElem::Deref => { let tcx = self.infcx.tcx; - let base_ty = Place::ty_from(&borrowed_place.local, proj_base, body, tcx).ty; + let base_ty = Place::ty_from(borrowed_place.local, proj_base, body, tcx).ty; debug!("add_reborrow_constraint - base_ty = {:?}", base_ty); match base_ty.kind { diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs index eecb9f633bf60..0f6640363fed6 100644 --- a/src/librustc_mir/dataflow/move_paths/builder.rs +++ b/src/librustc_mir/dataflow/move_paths/builder.rs @@ -109,7 +109,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { let proj_base = &place.projection[..i]; let body = self.builder.body; let tcx = self.builder.tcx; - let place_ty = Place::ty_from(&place.local, proj_base, body, tcx).ty; + let place_ty = Place::ty_from(place.local, proj_base, body, tcx).ty; match place_ty.kind { ty::Ref(..) | ty::RawPtr(..) => { let proj = &place.projection[..i + 1]; @@ -492,7 +492,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { // of the union so it is marked as initialized again. if let [proj_base @ .., ProjectionElem::Field(_, _)] = place.projection { if let ty::Adt(def, _) = - Place::ty_from(&place.local, proj_base, self.builder.body, self.builder.tcx).ty.kind + Place::ty_from(place.local, proj_base, self.builder.body, self.builder.tcx).ty.kind { if def.is_union() { place = PlaceRef { local: place.local, projection: proj_base } diff --git a/src/librustc_mir/transform/check_consts/qualifs.rs b/src/librustc_mir/transform/check_consts/qualifs.rs index 96bc9c3b22587..2c0c0cbbaddb9 100644 --- a/src/librustc_mir/transform/check_consts/qualifs.rs +++ b/src/librustc_mir/transform/check_consts/qualifs.rs @@ -46,7 +46,7 @@ pub trait Qualif { let qualif = base_qualif && Self::in_any_value_of_ty( cx, - Place::ty_from(&place.local, proj_base, *cx.body, cx.tcx) + Place::ty_from(place.local, proj_base, *cx.body, cx.tcx) .projection_ty(cx.tcx, elem) .ty, ); @@ -149,7 +149,7 @@ pub trait Qualif { Rvalue::Ref(_, _, ref place) | Rvalue::AddressOf(_, ref place) => { // Special-case reborrows to be more like a copy of the reference. if let [proj_base @ .., ProjectionElem::Deref] = place.projection.as_ref() { - let base_ty = Place::ty_from(&place.local, proj_base, *cx.body, cx.tcx).ty; + let base_ty = Place::ty_from(place.local, proj_base, *cx.body, cx.tcx).ty; if let ty::Ref(..) = base_ty.kind { return Self::in_place( cx, diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs index 44b2a90053a38..6f109a060dfc1 100644 --- a/src/librustc_mir/transform/check_consts/validation.rs +++ b/src/librustc_mir/transform/check_consts/validation.rs @@ -448,7 +448,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { match elem { ProjectionElem::Deref => { - let base_ty = Place::ty_from(place_local, proj_base, *self.body, self.tcx).ty; + let base_ty = Place::ty_from(*place_local, proj_base, *self.body, self.tcx).ty; if let ty::RawPtr(_) = base_ty.kind { if proj_base.is_empty() { if let (local, []) = (place_local, proj_base) { @@ -472,7 +472,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { | ProjectionElem::Subslice { .. } | ProjectionElem::Field(..) | ProjectionElem::Index(_) => { - let base_ty = Place::ty_from(place_local, proj_base, *self.body, self.tcx).ty; + let base_ty = Place::ty_from(*place_local, proj_base, *self.body, self.tcx).ty; match base_ty.ty_adt_def() { Some(def) if def.is_union() => { self.check_op(ops::UnionAccess); @@ -664,7 +664,7 @@ fn place_as_reborrow( // // This is sufficient to prevent an access to a `static mut` from being marked as a // reborrow, even if the check above were to disappear. - let inner_ty = Place::ty_from(&place.local, inner, body, tcx).ty; + let inner_ty = Place::ty_from(place.local, inner, body, tcx).ty; match inner_ty.kind { ty::Ref(..) => Some(inner), _ => None, diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index 4e943547f07f5..d455f7f40b7e0 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -215,7 +215,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { } } let is_borrow_of_interior_mut = context.is_borrow() - && !Place::ty_from(&place.local, proj_base, self.body, self.tcx).ty.is_freeze( + && !Place::ty_from(place.local, proj_base, self.body, self.tcx).ty.is_freeze( self.tcx, self.param_env, self.source_info.span, @@ -258,7 +258,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { } } } - let base_ty = Place::ty_from(&place.local, proj_base, self.body, self.tcx).ty; + let base_ty = Place::ty_from(place.local, proj_base, self.body, self.tcx).ty; match base_ty.kind { ty::RawPtr(..) => self.require_unsafe( "dereference of raw pointer", @@ -412,7 +412,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { match elem { ProjectionElem::Field(..) => { let ty = - Place::ty_from(&place.local, proj_base, &self.body.local_decls, self.tcx) + Place::ty_from(place.local, proj_base, &self.body.local_decls, self.tcx) .ty; match ty.kind { ty::Adt(def, _) => match self.tcx.layout_scalar_valid_range(def.did) { diff --git a/src/librustc_mir/transform/instcombine.rs b/src/librustc_mir/transform/instcombine.rs index 1d2917a808ea2..afe42e6357128 100644 --- a/src/librustc_mir/transform/instcombine.rs +++ b/src/librustc_mir/transform/instcombine.rs @@ -95,7 +95,7 @@ impl Visitor<'tcx> for OptimizationFinder<'b, 'tcx> { if let PlaceRef { local, projection: &[ref proj_base @ .., ProjectionElem::Deref] } = place.as_ref() { - if Place::ty_from(&local, proj_base, self.body, self.tcx).ty.is_region_ptr() { + if Place::ty_from(local, proj_base, self.body, self.tcx).ty.is_region_ptr() { self.optimizations.and_stars.insert(location); } } diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index c1aa4aa786719..f82225c6ae147 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -329,7 +329,7 @@ impl<'tcx> Validator<'_, 'tcx> { // FIXME(eddyb) this is probably excessive, with // the exception of `union` member accesses. let ty = - Place::ty_from(&place.local, proj_base, *self.body, self.tcx) + Place::ty_from(place.local, proj_base, *self.body, self.tcx) .projection_ty(self.tcx, elem) .ty; if ty.is_freeze(self.tcx, self.param_env, DUMMY_SP) { @@ -491,7 +491,7 @@ impl<'tcx> Validator<'_, 'tcx> { ProjectionElem::Field(..) => { if self.const_kind.is_none() { let base_ty = - Place::ty_from(&place.local, proj_base, *self.body, self.tcx).ty; + Place::ty_from(place.local, proj_base, *self.body, self.tcx).ty; if let Some(def) = base_ty.ty_adt_def() { // No promotion of union field accesses. if def.is_union() { @@ -589,7 +589,7 @@ impl<'tcx> Validator<'_, 'tcx> { // Raw reborrows can come from reference to pointer coercions, // so are allowed. if let [proj_base @ .., ProjectionElem::Deref] = place.projection.as_ref() { - let base_ty = Place::ty_from(&place.local, proj_base, *self.body, self.tcx).ty; + let base_ty = Place::ty_from(place.local, proj_base, *self.body, self.tcx).ty; if let ty::Ref(..) = base_ty.kind { return self.validate_place(PlaceRef { local: place.local, @@ -628,7 +628,7 @@ impl<'tcx> Validator<'_, 'tcx> { // Special-case reborrows to be more like a copy of the reference. let mut place = place.as_ref(); if let [proj_base @ .., ProjectionElem::Deref] = &place.projection { - let base_ty = Place::ty_from(&place.local, proj_base, *self.body, self.tcx).ty; + let base_ty = Place::ty_from(place.local, proj_base, *self.body, self.tcx).ty; if let ty::Ref(..) = base_ty.kind { place = PlaceRef { local: place.local, projection: proj_base }; } @@ -647,7 +647,7 @@ impl<'tcx> Validator<'_, 'tcx> { while let [proj_base @ .., elem] = place_projection { // FIXME(eddyb) this is probably excessive, with // the exception of `union` member accesses. - let ty = Place::ty_from(&place.local, proj_base, *self.body, self.tcx) + let ty = Place::ty_from(place.local, proj_base, *self.body, self.tcx) .projection_ty(self.tcx, elem) .ty; if ty.is_freeze(self.tcx, self.param_env, DUMMY_SP) { diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index b047e534e4f1c..49921badf33d9 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -268,7 +268,7 @@ fn check_place( ProjectionElem::Downcast(_symbol, _variant_index) => {} ProjectionElem::Field(..) => { - let base_ty = Place::ty_from(&place.local, &proj_base, body, tcx).ty; + let base_ty = Place::ty_from(place.local, &proj_base, body, tcx).ty; if let Some(def) = base_ty.ty_adt_def() { // No union field accesses in `const fn` if def.is_union() { diff --git a/src/librustc_mir/util/alignment.rs b/src/librustc_mir/util/alignment.rs index e17c7a80f1a76..d7f2abfbe9943 100644 --- a/src/librustc_mir/util/alignment.rs +++ b/src/librustc_mir/util/alignment.rs @@ -46,7 +46,7 @@ where // encountered a Deref, which is ABI-aligned ProjectionElem::Deref => break, ProjectionElem::Field(..) => { - let ty = Place::ty_from(&place.local, proj_base, local_decls, tcx).ty; + let ty = Place::ty_from(place.local, proj_base, local_decls, tcx).ty; match ty.kind { ty::Adt(def, _) if def.repr.packed() => return true, _ => {} diff --git a/src/librustc_mir_build/build/expr/as_place.rs b/src/librustc_mir_build/build/expr/as_place.rs index fd6882fa19fdf..ac12fbecb22e7 100644 --- a/src/librustc_mir_build/build/expr/as_place.rs +++ b/src/librustc_mir_build/build/expr/as_place.rs @@ -368,7 +368,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ) { let tcx = self.hir.tcx(); let place_ty = - Place::ty_from(&base_place.local, &base_place.projection, &self.local_decls, tcx); + Place::ty_from(base_place.local, &base_place.projection, &self.local_decls, tcx); if let ty::Slice(_) = place_ty.ty.kind { // We need to create fake borrows to ensure that the bounds // check that we just did stays valid. Since we can't assign to @@ -378,7 +378,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { match elem { ProjectionElem::Deref => { let fake_borrow_deref_ty = Place::ty_from( - &base_place.local, + base_place.local, &base_place.projection[..idx], &self.local_decls, tcx, @@ -403,7 +403,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } ProjectionElem::Index(_) => { let index_ty = Place::ty_from( - &base_place.local, + base_place.local, &base_place.projection[..idx], &self.local_decls, tcx, From 55dce720b24fde5d8489498fb5f7abd8c52c28f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 23 Jan 2020 15:21:15 -0800 Subject: [PATCH 08/17] Account for `ty::Error` when suggesting `impl Trait` or `Box` --- .../traits/error_reporting/suggestions.rs | 14 +- .../dyn-trait-return-should-be-impl-trait.rs | 33 ++++ ...n-trait-return-should-be-impl-trait.stderr | 152 +++++++++++++++++- 3 files changed, 191 insertions(+), 8 deletions(-) diff --git a/src/librustc/traits/error_reporting/suggestions.rs b/src/librustc/traits/error_reporting/suggestions.rs index 4559007ea426a..12c8de17d10f9 100644 --- a/src/librustc/traits/error_reporting/suggestions.rs +++ b/src/librustc/traits/error_reporting/suggestions.rs @@ -606,11 +606,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let tables = self.in_progress_tables.map(|t| t.borrow()).unwrap(); let mut ret_types = visitor.0.iter().filter_map(|expr| tables.node_type_opt(expr.hir_id)); - let (last_ty, all_returns_have_same_type) = - ret_types.clone().fold((None, true), |(last_ty, mut same), returned_ty| { - same &= last_ty.map_or(true, |ty| ty == returned_ty); - (Some(returned_ty), same) - }); + let (last_ty, all_returns_have_same_type) = ret_types.clone().fold( + (None, true), + |(last_ty, mut same): (std::option::Option>, bool), ty| { + same &= last_ty.map_or(true, |last_ty| last_ty == ty) && ty.kind != ty::Error; + (Some(ty), same) + }, + ); let all_returns_conform_to_trait = if let Some(ty_ret_ty) = tables.node_type_opt(ret_ty.hir_id) { match ty_ret_ty.kind { @@ -625,7 +627,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { }) }) } - _ => true, + _ => false, } } else { true diff --git a/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs b/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs index b70a51dc82511..93414379fd41a 100644 --- a/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs +++ b/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs @@ -22,6 +22,32 @@ fn bal() -> dyn Trait { //~ ERROR E0746 } 42 } +fn bam() -> Box { + if true { + return Struct; //~ ERROR mismatched types + } + 42 //~ ERROR mismatched types +} +fn baq() -> Box { + if true { + return 0; //~ ERROR mismatched types + } + 42 //~ ERROR mismatched types +} +fn baz() -> Box { + if true { + Struct //~ ERROR mismatched types + } else { + 42 //~ ERROR mismatched types + } +} +fn baw() -> Box { + if true { + 0 //~ ERROR mismatched types + } else { + 42 //~ ERROR mismatched types + } +} // Suggest using `impl Trait` fn bat() -> dyn Trait { //~ ERROR E0746 @@ -30,5 +56,12 @@ fn bat() -> dyn Trait { //~ ERROR E0746 } 42 } +fn bay() -> dyn Trait { //~ ERROR E0746 + if true { + 0u32 + } else { + 42u32 + } +} fn main() {} diff --git a/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr b/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr index 977a7ef0e0244..0df6e8f8dc77c 100644 --- a/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr +++ b/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr @@ -95,8 +95,136 @@ LL | } LL | Box::new(42) | +error[E0308]: mismatched types + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:27:16 + | +LL | fn bam() -> Box { + | -------------- expected `std::boxed::Box<(dyn Trait + 'static)>` because of return type +LL | if true { +LL | return Struct; + | ^^^^^^ + | | + | expected struct `std::boxed::Box`, found struct `Struct` + | help: store this in the heap by calling `Box::new`: `Box::new(Struct)` + | + = note: expected struct `std::boxed::Box<(dyn Trait + 'static)>` + found struct `Struct` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html + +error[E0308]: mismatched types + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:29:5 + | +LL | fn bam() -> Box { + | -------------- expected `std::boxed::Box<(dyn Trait + 'static)>` because of return type +... +LL | 42 + | ^^ + | | + | expected struct `std::boxed::Box`, found integer + | help: store this in the heap by calling `Box::new`: `Box::new(42)` + | + = note: expected struct `std::boxed::Box<(dyn Trait + 'static)>` + found type `{integer}` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html + +error[E0308]: mismatched types + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:33:16 + | +LL | fn baq() -> Box { + | -------------- expected `std::boxed::Box<(dyn Trait + 'static)>` because of return type +LL | if true { +LL | return 0; + | ^ + | | + | expected struct `std::boxed::Box`, found integer + | help: store this in the heap by calling `Box::new`: `Box::new(0)` + | + = note: expected struct `std::boxed::Box<(dyn Trait + 'static)>` + found type `{integer}` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html + +error[E0308]: mismatched types + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:35:5 + | +LL | fn baq() -> Box { + | -------------- expected `std::boxed::Box<(dyn Trait + 'static)>` because of return type +... +LL | 42 + | ^^ + | | + | expected struct `std::boxed::Box`, found integer + | help: store this in the heap by calling `Box::new`: `Box::new(42)` + | + = note: expected struct `std::boxed::Box<(dyn Trait + 'static)>` + found type `{integer}` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html + +error[E0308]: mismatched types + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:39:9 + | +LL | fn baz() -> Box { + | -------------- expected `std::boxed::Box<(dyn Trait + 'static)>` because of return type +LL | if true { +LL | Struct + | ^^^^^^ + | | + | expected struct `std::boxed::Box`, found struct `Struct` + | help: store this in the heap by calling `Box::new`: `Box::new(Struct)` + | + = note: expected struct `std::boxed::Box<(dyn Trait + 'static)>` + found struct `Struct` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html + +error[E0308]: mismatched types + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:41:9 + | +LL | fn baz() -> Box { + | -------------- expected `std::boxed::Box<(dyn Trait + 'static)>` because of return type +... +LL | 42 + | ^^ + | | + | expected struct `std::boxed::Box`, found integer + | help: store this in the heap by calling `Box::new`: `Box::new(42)` + | + = note: expected struct `std::boxed::Box<(dyn Trait + 'static)>` + found type `{integer}` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html + +error[E0308]: mismatched types + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:46:9 + | +LL | fn baw() -> Box { + | -------------- expected `std::boxed::Box<(dyn Trait + 'static)>` because of return type +LL | if true { +LL | 0 + | ^ + | | + | expected struct `std::boxed::Box`, found integer + | help: store this in the heap by calling `Box::new`: `Box::new(0)` + | + = note: expected struct `std::boxed::Box<(dyn Trait + 'static)>` + found type `{integer}` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html + +error[E0308]: mismatched types + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:48:9 + | +LL | fn baw() -> Box { + | -------------- expected `std::boxed::Box<(dyn Trait + 'static)>` because of return type +... +LL | 42 + | ^^ + | | + | expected struct `std::boxed::Box`, found integer + | help: store this in the heap by calling `Box::new`: `Box::new(42)` + | + = note: expected struct `std::boxed::Box<(dyn Trait + 'static)>` + found type `{integer}` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html + error[E0746]: return type cannot have an unboxed trait object - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:27:13 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:53:13 | LL | fn bat() -> dyn Trait { | ^^^^^^^^^ doesn't have a size known at compile-time @@ -107,7 +235,27 @@ help: return `impl Trait` instead, as all return paths are of type `{integer}`, LL | fn bat() -> impl Trait { | ^^^^^^^^^^ -error: aborting due to 9 previous errors +error[E0746]: return type cannot have an unboxed trait object + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:59:13 + | +LL | fn bay() -> dyn Trait { + | ^^^^^^^^^ doesn't have a size known at compile-time + | + = note: for information on trait objects, see + = note: if all the returned values were of the same type you could use `impl Trait` as the return type + = note: for information on `impl Trait`, see + = note: you can create a new `enum` with a variant for each returned type +help: return a boxed trait object instead + | +LL | fn bay() -> Box { +LL | Box::new(if true { +LL | 0u32 +LL | } else { +LL | 42u32 +LL | }) + | + +error: aborting due to 18 previous errors Some errors have detailed explanations: E0277, E0308, E0746. For more information about an error, try `rustc --explain E0277`. From afe992832693f5712b14cba406eced8b4d1f04b1 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 24 Jan 2020 12:50:13 -0300 Subject: [PATCH 09/17] ./x.py fmt --- .../diagnostics/conflict_errors.rs | 18 ++++++++++++------ .../borrow_check/diagnostics/move_errors.rs | 3 +-- src/librustc_mir/transform/check_unsafety.rs | 3 +-- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs index a14e034cfc197..24c6ed8bc21a1 100644 --- a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs @@ -604,8 +604,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { cursor = proj_base; match elem { - ProjectionElem::Field(field, _) if union_ty(*local, proj_base).is_some() => { - return Some((PlaceRef { local: *local, projection: proj_base }, field)); + ProjectionElem::Field(field, _) + if union_ty(*local, proj_base).is_some() => + { + return Some(( + PlaceRef { local: *local, projection: proj_base }, + field, + )); } _ => {} } @@ -629,7 +634,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { { // FIXME when we avoid clone reuse describe_place closure let describe_base_place = self - .describe_place(PlaceRef { local: *local, projection: proj_base }) + .describe_place(PlaceRef { + local: *local, + projection: proj_base, + }) .unwrap_or_else(|| "_".to_owned()); return Some(( @@ -1513,9 +1521,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { StorageDeadOrDrop::LocalStorageDead | StorageDeadOrDrop::BoxedStorageDead => { assert!( - Place::ty_from(place.local, proj_base, *self.body, tcx) - .ty - .is_box(), + Place::ty_from(place.local, proj_base, *self.body, tcx).ty.is_box(), "Drop of value behind a reference or raw pointer" ); StorageDeadOrDrop::BoxedStorageDead diff --git a/src/librustc_mir/borrow_check/diagnostics/move_errors.rs b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs index f438485d575eb..7e1ad9051b629 100644 --- a/src/librustc_mir/borrow_check/diagnostics/move_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs @@ -273,8 +273,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let description = if place.projection.len() == 1 { format!("static item `{}`", self.describe_place(place.as_ref()).unwrap()) } else { - let base_static = - PlaceRef { local: place.local, projection: &[ProjectionElem::Deref] }; + let base_static = PlaceRef { local: place.local, projection: &[ProjectionElem::Deref] }; format!( "`{:?}` as `{:?}` is a static item", diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index d455f7f40b7e0..dc669a3e97796 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -412,8 +412,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { match elem { ProjectionElem::Field(..) => { let ty = - Place::ty_from(place.local, proj_base, &self.body.local_decls, self.tcx) - .ty; + Place::ty_from(place.local, proj_base, &self.body.local_decls, self.tcx).ty; match ty.kind { ty::Adt(def, _) => match self.tcx.layout_scalar_valid_range(def.did) { (Bound::Unbounded, Bound::Unbounded) => {} From 3859a474a1cdec18c6b971c947a77a3af26b43df Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 24 Jan 2020 13:27:01 -0300 Subject: [PATCH 10/17] Remove unneeded & on match pattern --- src/librustc/mir/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 34e5ddbb513af..bacbb325e5895 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1797,8 +1797,8 @@ impl<'tcx> Place<'tcx> { // FIXME: can we safely swap the semantics of `fn base_local` below in here instead? pub fn local_or_deref_local(&self) -> Option { match self.as_ref() { - PlaceRef { local, projection: &[] } - | PlaceRef { local, projection: &[ProjectionElem::Deref] } => Some(local), + PlaceRef { local, projection: [] } + | PlaceRef { local, projection: [ProjectionElem::Deref] } => Some(local), _ => None, } } From 2d7f8b31db062b695175c940d7f0c13281e45bb2 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Fri, 24 Jan 2020 17:43:57 +0100 Subject: [PATCH 11/17] Use Self instead of self return type --- src/libcore/fmt/builders.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/libcore/fmt/builders.rs b/src/libcore/fmt/builders.rs index dd0f3ccb15841..8ba0e422e8f13 100644 --- a/src/libcore/fmt/builders.rs +++ b/src/libcore/fmt/builders.rs @@ -133,7 +133,7 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { /// ); /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] - pub fn field(&mut self, name: &str, value: &dyn fmt::Debug) -> &mut DebugStruct<'a, 'b> { + pub fn field(&mut self, name: &str, value: &dyn fmt::Debug) -> &mut Self { self.result = self.result.and_then(|_| { if self.is_pretty() { if !self.has_fields { @@ -330,7 +330,7 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> { /// ); /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] - pub fn field(&mut self, value: &dyn fmt::Debug) -> &mut DebugTuple<'a, 'b> { + pub fn field(&mut self, value: &dyn fmt::Debug) -> &mut Self { self.result = self.result.and_then(|_| { if self.is_pretty() { if self.fields == 0 { @@ -492,7 +492,7 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> { /// ); /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] - pub fn entry(&mut self, entry: &dyn fmt::Debug) -> &mut DebugSet<'a, 'b> { + pub fn entry(&mut self, entry: &dyn fmt::Debug) -> &mut Self { self.inner.entry(entry); self } @@ -521,7 +521,7 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> { /// ); /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] - pub fn entries(&mut self, entries: I) -> &mut DebugSet<'a, 'b> + pub fn entries(&mut self, entries: I) -> &mut Self where D: fmt::Debug, I: IntoIterator, @@ -624,7 +624,7 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> { /// ); /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] - pub fn entry(&mut self, entry: &dyn fmt::Debug) -> &mut DebugList<'a, 'b> { + pub fn entry(&mut self, entry: &dyn fmt::Debug) -> &mut Self { self.inner.entry(entry); self } @@ -653,7 +653,7 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> { /// ); /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] - pub fn entries(&mut self, entries: I) -> &mut DebugList<'a, 'b> + pub fn entries(&mut self, entries: I) -> &mut Self where D: fmt::Debug, I: IntoIterator, @@ -760,7 +760,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// ); /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] - pub fn entry(&mut self, key: &dyn fmt::Debug, value: &dyn fmt::Debug) -> &mut DebugMap<'a, 'b> { + pub fn entry(&mut self, key: &dyn fmt::Debug, value: &dyn fmt::Debug) -> &mut Self { self.key(key).value(value) } @@ -797,7 +797,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// ); /// ``` #[unstable(feature = "debug_map_key_value", reason = "recently added", issue = "62482")] - pub fn key(&mut self, key: &dyn fmt::Debug) -> &mut DebugMap<'a, 'b> { + pub fn key(&mut self, key: &dyn fmt::Debug) -> &mut Self { self.result = self.result.and_then(|_| { assert!( !self.has_key, @@ -862,7 +862,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// ); /// ``` #[unstable(feature = "debug_map_key_value", reason = "recently added", issue = "62482")] - pub fn value(&mut self, value: &dyn fmt::Debug) -> &mut DebugMap<'a, 'b> { + pub fn value(&mut self, value: &dyn fmt::Debug) -> &mut Self { self.result = self.result.and_then(|_| { assert!(self.has_key, "attempted to format a map value before its key"); @@ -908,7 +908,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// ); /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] - pub fn entries(&mut self, entries: I) -> &mut DebugMap<'a, 'b> + pub fn entries(&mut self, entries: I) -> &mut Self where K: fmt::Debug, V: fmt::Debug, From d14a323e74d0770960553fe79d0bcd578c393cf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 24 Jan 2020 10:35:13 -0800 Subject: [PATCH 12/17] Use more accurate return path spans No longer suggest `Box::new(if foo { Type1 } else { Type2 })`, instead suggesting `if foo { Box::new(Type1) } else { Box::new(Type2) }`. --- .../traits/error_reporting/suggestions.rs | 53 +++++++++++++---- src/test/ui/error-codes/E0746.fixed | 4 +- src/test/ui/error-codes/E0746.rs | 4 +- src/test/ui/error-codes/E0746.stderr | 2 +- .../dyn-trait-return-should-be-impl-trait.rs | 11 +++- ...n-trait-return-should-be-impl-trait.stderr | 57 +++++++++++-------- .../feature-gate-never_type_fallback.stderr | 2 +- 7 files changed, 91 insertions(+), 42 deletions(-) diff --git a/src/librustc/traits/error_reporting/suggestions.rs b/src/librustc/traits/error_reporting/suggestions.rs index 12c8de17d10f9..84f1260385553 100644 --- a/src/librustc/traits/error_reporting/suggestions.rs +++ b/src/librustc/traits/error_reporting/suggestions.rs @@ -600,12 +600,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // Visit to make sure there's a single `return` type to suggest `impl Trait`, // otherwise suggest using `Box` or an enum. - let mut visitor = ReturnsVisitor(vec![]); + let mut visitor = ReturnsVisitor::new(); visitor.visit_body(&body); let tables = self.in_progress_tables.map(|t| t.borrow()).unwrap(); - let mut ret_types = visitor.0.iter().filter_map(|expr| tables.node_type_opt(expr.hir_id)); + let mut ret_types = + visitor.returns.iter().filter_map(|expr| tables.node_type_opt(expr.hir_id)); let (last_ty, all_returns_have_same_type) = ret_types.clone().fold( (None, true), |(last_ty, mut same): (std::option::Option>, bool), ty| { @@ -677,7 +678,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // Suggest `-> Box` and `Box::new(returned_value)`. // Get all the return values and collect their span and suggestion. let mut suggestions = visitor - .0 + .returns .iter() .map(|expr| { ( @@ -737,10 +738,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { { let body = hir.body(*body_id); // Point at all the `return`s in the function as they have failed trait bounds. - let mut visitor = ReturnsVisitor(vec![]); + let mut visitor = ReturnsVisitor::new(); visitor.visit_body(&body); let tables = self.in_progress_tables.map(|t| t.borrow()).unwrap(); - for expr in &visitor.0 { + for expr in &visitor.returns { if let Some(returned_ty) = tables.node_type_opt(expr.hir_id) { let ty = self.resolve_vars_if_possible(&returned_ty); err.span_label(expr.span, &format!("this returned value is of type `{}`", ty)); @@ -1691,7 +1692,16 @@ pub fn suggest_constraining_type_param( /// Collect all the returned expressions within the input expression. /// Used to point at the return spans when we want to suggest some change to them. -struct ReturnsVisitor<'v>(Vec<&'v hir::Expr<'v>>); +struct ReturnsVisitor<'v> { + returns: Vec<&'v hir::Expr<'v>>, + in_block_tail: bool, +} + +impl ReturnsVisitor<'_> { + fn new() -> Self { + ReturnsVisitor { returns: vec![], in_block_tail: false } + } +} impl<'v> Visitor<'v> for ReturnsVisitor<'v> { type Map = rustc::hir::map::Map<'v>; @@ -1701,20 +1711,41 @@ impl<'v> Visitor<'v> for ReturnsVisitor<'v> { } fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) { - if let hir::ExprKind::Ret(Some(ex)) = ex.kind { - self.0.push(ex); + match ex.kind { + hir::ExprKind::Ret(Some(ex)) => { + self.returns.push(ex); + } + hir::ExprKind::Block(block, _) if self.in_block_tail => { + self.in_block_tail = false; + for stmt in block.stmts { + hir::intravisit::walk_stmt(self, stmt); + } + self.in_block_tail = true; + if let Some(expr) = block.expr { + self.visit_expr(expr); + } + } + hir::ExprKind::Match(_, arms, _) if self.in_block_tail => { + for arm in arms { + self.visit_expr(arm.body); + } + } + // We need to walk to find `return`s in the entire body. + _ if !self.in_block_tail => hir::intravisit::walk_expr(self, ex), + _ => self.returns.push(ex), } - hir::intravisit::walk_expr(self, ex); } fn visit_body(&mut self, body: &'v hir::Body<'v>) { + let prev = self.in_block_tail; if body.generator_kind().is_none() { if let hir::ExprKind::Block(block, None) = body.value.kind { - if let Some(expr) = block.expr { - self.0.push(expr); + if block.expr.is_some() { + self.in_block_tail = true; } } } hir::intravisit::walk_body(self, body); + self.in_block_tail = prev; } } diff --git a/src/test/ui/error-codes/E0746.fixed b/src/test/ui/error-codes/E0746.fixed index ca8319aa020dc..70c7f791a2b88 100644 --- a/src/test/ui/error-codes/E0746.fixed +++ b/src/test/ui/error-codes/E0746.fixed @@ -10,9 +10,9 @@ fn foo() -> impl Trait { Struct } fn bar() -> impl Trait { //~ ERROR E0746 if true { - return 0; + return 0u32; } - 42 + 42u32 } fn main() {} diff --git a/src/test/ui/error-codes/E0746.rs b/src/test/ui/error-codes/E0746.rs index bf5ba8fff562a..fbf18246e1648 100644 --- a/src/test/ui/error-codes/E0746.rs +++ b/src/test/ui/error-codes/E0746.rs @@ -10,9 +10,9 @@ fn foo() -> dyn Trait { Struct } fn bar() -> dyn Trait { //~ ERROR E0746 if true { - return 0; + return 0u32; } - 42 + 42u32 } fn main() {} diff --git a/src/test/ui/error-codes/E0746.stderr b/src/test/ui/error-codes/E0746.stderr index e7a8fd304cabe..05c61f1149fb5 100644 --- a/src/test/ui/error-codes/E0746.stderr +++ b/src/test/ui/error-codes/E0746.stderr @@ -17,7 +17,7 @@ LL | fn bar() -> dyn Trait { | ^^^^^^^^^ doesn't have a size known at compile-time | = note: for information on `impl Trait`, see -help: return `impl Trait` instead, as all return paths are of type `{integer}`, which implements `Trait` +help: return `impl Trait` instead, as all return paths are of type `u32`, which implements `Trait` | LL | fn bar() -> impl Trait { | ^^^^^^^^^^ diff --git a/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs b/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs index 93414379fd41a..dfcc22aee3485 100644 --- a/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs +++ b/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs @@ -22,6 +22,13 @@ fn bal() -> dyn Trait { //~ ERROR E0746 } 42 } +fn bax() -> dyn Trait { //~ ERROR E0746 + if true { + Struct + } else { + 42 + } +} fn bam() -> Box { if true { return Struct; //~ ERROR mismatched types @@ -52,9 +59,9 @@ fn baw() -> Box { // Suggest using `impl Trait` fn bat() -> dyn Trait { //~ ERROR E0746 if true { - return 0; + return 0u32; } - 42 + 42u32 } fn bay() -> dyn Trait { //~ ERROR E0746 if true { diff --git a/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr b/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr index 0df6e8f8dc77c..fbad7ec124cb9 100644 --- a/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr +++ b/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr @@ -95,8 +95,27 @@ LL | } LL | Box::new(42) | +error[E0746]: return type cannot have an unboxed trait object + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:25:13 + | +LL | fn bax() -> dyn Trait { + | ^^^^^^^^^ doesn't have a size known at compile-time + | + = note: for information on trait objects, see + = note: if all the returned values were of the same type you could use `impl Trait` as the return type + = note: for information on `impl Trait`, see + = note: you can create a new `enum` with a variant for each returned type +help: return a boxed trait object instead + | +LL | fn bax() -> Box { +LL | if true { +LL | Box::new(Struct) +LL | } else { +LL | Box::new(42) + | + error[E0308]: mismatched types - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:27:16 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:34:16 | LL | fn bam() -> Box { | -------------- expected `std::boxed::Box<(dyn Trait + 'static)>` because of return type @@ -112,7 +131,7 @@ LL | return Struct; = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html error[E0308]: mismatched types - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:29:5 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:36:5 | LL | fn bam() -> Box { | -------------- expected `std::boxed::Box<(dyn Trait + 'static)>` because of return type @@ -128,7 +147,7 @@ LL | 42 = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html error[E0308]: mismatched types - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:33:16 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:40:16 | LL | fn baq() -> Box { | -------------- expected `std::boxed::Box<(dyn Trait + 'static)>` because of return type @@ -144,7 +163,7 @@ LL | return 0; = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html error[E0308]: mismatched types - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:35:5 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:42:5 | LL | fn baq() -> Box { | -------------- expected `std::boxed::Box<(dyn Trait + 'static)>` because of return type @@ -160,7 +179,7 @@ LL | 42 = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html error[E0308]: mismatched types - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:39:9 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:46:9 | LL | fn baz() -> Box { | -------------- expected `std::boxed::Box<(dyn Trait + 'static)>` because of return type @@ -176,7 +195,7 @@ LL | Struct = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html error[E0308]: mismatched types - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:41:9 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:48:9 | LL | fn baz() -> Box { | -------------- expected `std::boxed::Box<(dyn Trait + 'static)>` because of return type @@ -192,7 +211,7 @@ LL | 42 = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html error[E0308]: mismatched types - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:46:9 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:53:9 | LL | fn baw() -> Box { | -------------- expected `std::boxed::Box<(dyn Trait + 'static)>` because of return type @@ -208,7 +227,7 @@ LL | 0 = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html error[E0308]: mismatched types - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:48:9 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:55:9 | LL | fn baw() -> Box { | -------------- expected `std::boxed::Box<(dyn Trait + 'static)>` because of return type @@ -224,38 +243,30 @@ LL | 42 = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html error[E0746]: return type cannot have an unboxed trait object - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:53:13 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:60:13 | LL | fn bat() -> dyn Trait { | ^^^^^^^^^ doesn't have a size known at compile-time | = note: for information on `impl Trait`, see -help: return `impl Trait` instead, as all return paths are of type `{integer}`, which implements `Trait` +help: return `impl Trait` instead, as all return paths are of type `u32`, which implements `Trait` | LL | fn bat() -> impl Trait { | ^^^^^^^^^^ error[E0746]: return type cannot have an unboxed trait object - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:59:13 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:66:13 | LL | fn bay() -> dyn Trait { | ^^^^^^^^^ doesn't have a size known at compile-time | - = note: for information on trait objects, see - = note: if all the returned values were of the same type you could use `impl Trait` as the return type = note: for information on `impl Trait`, see - = note: you can create a new `enum` with a variant for each returned type -help: return a boxed trait object instead - | -LL | fn bay() -> Box { -LL | Box::new(if true { -LL | 0u32 -LL | } else { -LL | 42u32 -LL | }) +help: return `impl Trait` instead, as all return paths are of type `u32`, which implements `Trait` | +LL | fn bay() -> impl Trait { + | ^^^^^^^^^^ -error: aborting due to 18 previous errors +error: aborting due to 19 previous errors Some errors have detailed explanations: E0277, E0308, E0746. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/never_type/feature-gate-never_type_fallback.stderr b/src/test/ui/never_type/feature-gate-never_type_fallback.stderr index 77288f1badac5..08e16f4693645 100644 --- a/src/test/ui/never_type/feature-gate-never_type_fallback.stderr +++ b/src/test/ui/never_type/feature-gate-never_type_fallback.stderr @@ -5,7 +5,7 @@ LL | fn should_ret_unit() -> impl T { | ^^^^^^ the trait `T` is not implemented for `()` LL | LL | panic!() - | -------- this returned value is of type `()` + | -------- this returned value is of type `!` | = note: the return type of a function must have a statically known size = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) From 34d51b33787c9b2f59cb3283c8b57a290ab86437 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 24 Jan 2020 11:18:45 -0800 Subject: [PATCH 13/17] Increase suggestion code window from 6 lines to 20 --- src/librustc_errors/emitter.rs | 11 ++++++++--- src/test/ui/issues/issue-22644.stderr | 3 ++- .../unboxed-closure-sugar-lifetime-elision.stderr | 3 ++- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index b0e0cb611afaf..2149e46a1cfbc 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -456,9 +456,14 @@ impl Emitter for SilentEmitter { fn emit_diagnostic(&mut self, _: &Diagnostic) {} } -/// maximum number of lines we will print for each error; arbitrary. +/// Maximum number of lines we will print for each error; arbitrary. pub const MAX_HIGHLIGHT_LINES: usize = 6; -/// maximum number of suggestions to be shown +/// Maximum number of lines we will print for a multiline suggestion; arbitrary. +/// +/// This should be replaced with a more involved mechanism to output multiline suggestions that +/// more closely mimmics the regular diagnostic output, where irrelevant code lines are ellided. +pub const MAX_SUGGESTION_HIGHLIGHT_LINES: usize = 20; +/// Maximum number of suggestions to be shown /// /// Arbitrary, but taken from trait import suggestion limit pub const MAX_SUGGESTIONS: usize = 4; @@ -1521,7 +1526,7 @@ impl EmitterWriter { draw_col_separator_no_space(&mut buffer, 1, max_line_num_len + 1); let mut line_pos = 0; let mut lines = complete.lines(); - for line in lines.by_ref().take(MAX_HIGHLIGHT_LINES) { + for line in lines.by_ref().take(MAX_SUGGESTION_HIGHLIGHT_LINES) { // Print the span column to avoid confusion buffer.puts( row_num, diff --git a/src/test/ui/issues/issue-22644.stderr b/src/test/ui/issues/issue-22644.stderr index 2bddcc2ba56ce..105cf73652586 100644 --- a/src/test/ui/issues/issue-22644.stderr +++ b/src/test/ui/issues/issue-22644.stderr @@ -74,7 +74,8 @@ LL | LL | as LL | LL | - ... +LL | usize) + | error: `<` is interpreted as a start of generic arguments for `usize`, not a shift --> $DIR/issue-22644.rs:32:31 diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr index 0a028e44919a6..469425ea44ded 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr @@ -13,7 +13,8 @@ LL | dyn Foo(&isize) -> &isize >(); LL | eq::< dyn for<'a> Foo<(&'a isize,), Output=(&'a isize, &'a isize)>, LL | dyn Foo(&isize) -> (&isize, &isize) >(); LL | - ... +LL | let _: dyn Foo(&isize, &usize) -> &'lifetime usize; + | error: aborting due to previous error From d493dccef7ae1d2ca739fe828bf9556b44dc460a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 24 Jan 2020 11:47:54 -0800 Subject: [PATCH 14/17] Apply `resolve_vars_if_possible` to returned types for more accurate suggestions --- src/librustc/traits/error_reporting/suggestions.rs | 8 ++++++-- .../impl-trait/dyn-trait-return-should-be-impl-trait.rs | 8 ++++---- .../dyn-trait-return-should-be-impl-trait.stderr | 4 ++-- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/librustc/traits/error_reporting/suggestions.rs b/src/librustc/traits/error_reporting/suggestions.rs index 84f1260385553..cc2c97096e966 100644 --- a/src/librustc/traits/error_reporting/suggestions.rs +++ b/src/librustc/traits/error_reporting/suggestions.rs @@ -605,11 +605,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let tables = self.in_progress_tables.map(|t| t.borrow()).unwrap(); - let mut ret_types = - visitor.returns.iter().filter_map(|expr| tables.node_type_opt(expr.hir_id)); + let mut ret_types = visitor + .returns + .iter() + .filter_map(|expr| tables.node_type_opt(expr.hir_id)) + .map(|ty| self.resolve_vars_if_possible(&ty)); let (last_ty, all_returns_have_same_type) = ret_types.clone().fold( (None, true), |(last_ty, mut same): (std::option::Option>, bool), ty| { + let ty = self.resolve_vars_if_possible(&ty); same &= last_ty.map_or(true, |last_ty| last_ty == ty) && ty.kind != ty::Error; (Some(ty), same) }, diff --git a/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs b/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs index dfcc22aee3485..08bab5734fd7a 100644 --- a/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs +++ b/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs @@ -59,15 +59,15 @@ fn baw() -> Box { // Suggest using `impl Trait` fn bat() -> dyn Trait { //~ ERROR E0746 if true { - return 0u32; + return 0; } - 42u32 + 42 } fn bay() -> dyn Trait { //~ ERROR E0746 if true { - 0u32 + 0 } else { - 42u32 + 42 } } diff --git a/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr b/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr index fbad7ec124cb9..664a897c593fc 100644 --- a/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr +++ b/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr @@ -249,7 +249,7 @@ LL | fn bat() -> dyn Trait { | ^^^^^^^^^ doesn't have a size known at compile-time | = note: for information on `impl Trait`, see -help: return `impl Trait` instead, as all return paths are of type `u32`, which implements `Trait` +help: return `impl Trait` instead, as all return paths are of type `{integer}`, which implements `Trait` | LL | fn bat() -> impl Trait { | ^^^^^^^^^^ @@ -261,7 +261,7 @@ LL | fn bay() -> dyn Trait { | ^^^^^^^^^ doesn't have a size known at compile-time | = note: for information on `impl Trait`, see -help: return `impl Trait` instead, as all return paths are of type `u32`, which implements `Trait` +help: return `impl Trait` instead, as all return paths are of type `{integer}`, which implements `Trait` | LL | fn bay() -> impl Trait { | ^^^^^^^^^^ From 600e385c43904eb4a5337427f3f6fb169fe32234 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 24 Jan 2020 14:03:35 -0800 Subject: [PATCH 15/17] review comments --- .../traits/error_reporting/suggestions.rs | 18 ++++++++---------- src/librustc_errors/emitter.rs | 2 +- src/test/ui/error-codes/E0746.fixed | 4 ++-- src/test/ui/error-codes/E0746.rs | 4 ++-- src/test/ui/error-codes/E0746.stderr | 2 +- 5 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/librustc/traits/error_reporting/suggestions.rs b/src/librustc/traits/error_reporting/suggestions.rs index cc2c97096e966..b2aec78c175ad 100644 --- a/src/librustc/traits/error_reporting/suggestions.rs +++ b/src/librustc/traits/error_reporting/suggestions.rs @@ -600,7 +600,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // Visit to make sure there's a single `return` type to suggest `impl Trait`, // otherwise suggest using `Box` or an enum. - let mut visitor = ReturnsVisitor::new(); + let mut visitor = ReturnsVisitor::default(); visitor.visit_body(&body); let tables = self.in_progress_tables.map(|t| t.borrow()).unwrap(); @@ -742,7 +742,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { { let body = hir.body(*body_id); // Point at all the `return`s in the function as they have failed trait bounds. - let mut visitor = ReturnsVisitor::new(); + let mut visitor = ReturnsVisitor::default(); visitor.visit_body(&body); let tables = self.in_progress_tables.map(|t| t.borrow()).unwrap(); for expr in &visitor.returns { @@ -1696,17 +1696,12 @@ pub fn suggest_constraining_type_param( /// Collect all the returned expressions within the input expression. /// Used to point at the return spans when we want to suggest some change to them. +#[derive(Default)] struct ReturnsVisitor<'v> { returns: Vec<&'v hir::Expr<'v>>, in_block_tail: bool, } -impl ReturnsVisitor<'_> { - fn new() -> Self { - ReturnsVisitor { returns: vec![], in_block_tail: false } - } -} - impl<'v> Visitor<'v> for ReturnsVisitor<'v> { type Map = rustc::hir::map::Map<'v>; @@ -1715,6 +1710,10 @@ impl<'v> Visitor<'v> for ReturnsVisitor<'v> { } fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) { + // Visit every expression to detect `return` paths, either through the function's tail + // expression or `return` statements. We walk all nodes to find `return` statements, but + // we only care about tail expressions when `in_block_tail` is `true`, which means that + // they're in the return path of the function body. match ex.kind { hir::ExprKind::Ret(Some(ex)) => { self.returns.push(ex); @@ -1741,7 +1740,7 @@ impl<'v> Visitor<'v> for ReturnsVisitor<'v> { } fn visit_body(&mut self, body: &'v hir::Body<'v>) { - let prev = self.in_block_tail; + assert!(!self.in_block_tail); if body.generator_kind().is_none() { if let hir::ExprKind::Block(block, None) = body.value.kind { if block.expr.is_some() { @@ -1750,6 +1749,5 @@ impl<'v> Visitor<'v> for ReturnsVisitor<'v> { } } hir::intravisit::walk_body(self, body); - self.in_block_tail = prev; } } diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 2149e46a1cfbc..b62e4223fea10 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -461,7 +461,7 @@ pub const MAX_HIGHLIGHT_LINES: usize = 6; /// Maximum number of lines we will print for a multiline suggestion; arbitrary. /// /// This should be replaced with a more involved mechanism to output multiline suggestions that -/// more closely mimmics the regular diagnostic output, where irrelevant code lines are ellided. +/// more closely mimmics the regular diagnostic output, where irrelevant code lines are elided. pub const MAX_SUGGESTION_HIGHLIGHT_LINES: usize = 20; /// Maximum number of suggestions to be shown /// diff --git a/src/test/ui/error-codes/E0746.fixed b/src/test/ui/error-codes/E0746.fixed index 70c7f791a2b88..ca8319aa020dc 100644 --- a/src/test/ui/error-codes/E0746.fixed +++ b/src/test/ui/error-codes/E0746.fixed @@ -10,9 +10,9 @@ fn foo() -> impl Trait { Struct } fn bar() -> impl Trait { //~ ERROR E0746 if true { - return 0u32; + return 0; } - 42u32 + 42 } fn main() {} diff --git a/src/test/ui/error-codes/E0746.rs b/src/test/ui/error-codes/E0746.rs index fbf18246e1648..bf5ba8fff562a 100644 --- a/src/test/ui/error-codes/E0746.rs +++ b/src/test/ui/error-codes/E0746.rs @@ -10,9 +10,9 @@ fn foo() -> dyn Trait { Struct } fn bar() -> dyn Trait { //~ ERROR E0746 if true { - return 0u32; + return 0; } - 42u32 + 42 } fn main() {} diff --git a/src/test/ui/error-codes/E0746.stderr b/src/test/ui/error-codes/E0746.stderr index 05c61f1149fb5..e7a8fd304cabe 100644 --- a/src/test/ui/error-codes/E0746.stderr +++ b/src/test/ui/error-codes/E0746.stderr @@ -17,7 +17,7 @@ LL | fn bar() -> dyn Trait { | ^^^^^^^^^ doesn't have a size known at compile-time | = note: for information on `impl Trait`, see -help: return `impl Trait` instead, as all return paths are of type `u32`, which implements `Trait` +help: return `impl Trait` instead, as all return paths are of type `{integer}`, which implements `Trait` | LL | fn bar() -> impl Trait { | ^^^^^^^^^^ From b626202087dff72216c14e08e11d936136dc2126 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 24 Jan 2020 18:03:09 -0800 Subject: [PATCH 16/17] Do not ICE on multipart suggestions touching multiple files When encountering a multipart suggestion with spans belonging to different contexts, skip that suggestion. --- src/librustc_errors/lib.rs | 11 ++++++----- .../ui/consts/miri_unleashed/mutable_const2.stderr | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 827e9b831f32d..17b293401f89e 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -185,16 +185,17 @@ impl CodeSuggestion { !invalid }) .cloned() - .map(|mut substitution| { + .filter_map(|mut substitution| { // Assumption: all spans are in the same file, and all spans // are disjoint. Sort in ascending order. substitution.parts.sort_by_key(|part| part.span.lo()); // Find the bounding span. - let lo = substitution.parts.iter().map(|part| part.span.lo()).min().unwrap(); - let hi = substitution.parts.iter().map(|part| part.span.hi()).max().unwrap(); + let lo = substitution.parts.iter().map(|part| part.span.lo()).min()?; + let hi = substitution.parts.iter().map(|part| part.span.hi()).max()?; let bounding_span = Span::with_root_ctxt(lo, hi); - let lines = cm.span_to_lines(bounding_span).unwrap(); + // The different spans might belong to different contexts, if so ignore suggestion. + let lines = cm.span_to_lines(bounding_span).ok()?; assert!(!lines.lines.is_empty()); // To build up the result, we do this for each span: @@ -244,7 +245,7 @@ impl CodeSuggestion { while buf.ends_with('\n') { buf.pop(); } - (buf, substitution.parts, only_capitalization) + Some((buf, substitution.parts, only_capitalization)) }) .collect() } diff --git a/src/test/ui/consts/miri_unleashed/mutable_const2.stderr b/src/test/ui/consts/miri_unleashed/mutable_const2.stderr index 0d7fb845a40ee..a316d8f1698ac 100644 --- a/src/test/ui/consts/miri_unleashed/mutable_const2.stderr +++ b/src/test/ui/consts/miri_unleashed/mutable_const2.stderr @@ -10,7 +10,7 @@ error: internal compiler error: mutable allocation in constant LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -thread 'rustc' panicked at 'no errors encountered even though `delay_span_bug` issued', src/librustc_errors/lib.rs:356:17 +thread 'rustc' panicked at 'no errors encountered even though `delay_span_bug` issued', src/librustc_errors/lib.rs:357:17 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace error: internal compiler error: unexpected panic From 1605276cc2ff3319a7f360b389be1a53d0d5751c Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Thu, 23 Jan 2020 18:19:59 -0500 Subject: [PATCH 17/17] Add some type-alias-impl-trait regression tests Fixes #57611 Fixes #57807 --- .../issue-57611-trait-alias.rs | 27 ++++++++++++++++ .../issue-57611-trait-alias.stderr | 23 ++++++++++++++ .../issue-57807-associated-type.rs | 31 +++++++++++++++++++ 3 files changed, 81 insertions(+) create mode 100644 src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs create mode 100644 src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr create mode 100644 src/test/ui/type-alias-impl-trait/issue-57807-associated-type.rs diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs new file mode 100644 index 0000000000000..1c2051e7eaeeb --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs @@ -0,0 +1,27 @@ +// Regression test for issue #57611 +// Ensures that we don't ICE +// FIXME: This should compile, but it currently doesn't + +#![feature(trait_alias)] +#![feature(type_alias_impl_trait)] + +trait Foo { + type Bar: Baz; + + fn bar(&self) -> Self::Bar; +} + +struct X; + +impl Foo for X { + type Bar = impl Baz; //~ ERROR type mismatch in closure arguments + //~^ ERROR type mismatch resolving + + fn bar(&self) -> Self::Bar { + |x| x + } +} + +trait Baz = Fn(&A) -> &B; + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr new file mode 100644 index 0000000000000..f648b7bfc991d --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr @@ -0,0 +1,23 @@ +error[E0631]: type mismatch in closure arguments + --> $DIR/issue-57611-trait-alias.rs:17:5 + | +LL | type Bar = impl Baz; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected signature of `for<'r> fn(&'r X) -> _` +... +LL | |x| x + | ----- found signature of `fn(_) -> _` + | + = note: the return type of a function must have a statically known size + +error[E0271]: type mismatch resolving `for<'r> <[closure@$DIR/issue-57611-trait-alias.rs:21:9: 21:14] as std::ops::FnOnce<(&'r X,)>>::Output == &'r X` + --> $DIR/issue-57611-trait-alias.rs:17:5 + | +LL | type Bar = impl Baz; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter, found concrete lifetime + | + = note: the return type of a function must have a statically known size + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0271, E0631. +For more information about an error, try `rustc --explain E0271`. diff --git a/src/test/ui/type-alias-impl-trait/issue-57807-associated-type.rs b/src/test/ui/type-alias-impl-trait/issue-57807-associated-type.rs new file mode 100644 index 0000000000000..fcab2c7db2605 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-57807-associated-type.rs @@ -0,0 +1,31 @@ +// Regression test for issue #57807 - ensure +// that we properly unify associated types within +// a type alias impl trait +// check-pass +#![feature(type_alias_impl_trait)] + +trait Bar { + type A; +} + +impl Bar for () { + type A = (); +} + +trait Foo { + type A; + type B: Bar; + + fn foo() -> Self::B; +} + +impl Foo for () { + type A = (); + type B = impl Bar; + + fn foo() -> Self::B { + () + } +} + +fn main() {}