From bd271313321666850ce8d9d8d6093e6f5db530f4 Mon Sep 17 00:00:00 2001 From: David Wood Date: Fri, 26 Oct 2018 12:11:19 +0200 Subject: [PATCH 01/31] Add helpful logging statements. This commit adds logging statements to `promote_consts` and `qualify_consts` to make it easier to understand what it is doing. --- src/librustc_mir/transform/promote_consts.rs | 8 +++++++ src/librustc_mir/transform/qualify_consts.rs | 22 +++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index f4efe33da7080..790e6e82723ef 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -53,6 +53,7 @@ pub enum TempState { impl TempState { pub fn is_promotable(&self) -> bool { + debug!("is_promotable: self={:?}", self); if let TempState::Defined { uses, .. } = *self { uses > 0 } else { @@ -88,6 +89,7 @@ impl<'tcx> Visitor<'tcx> for TempCollector<'tcx> { &index: &Local, context: PlaceContext<'tcx>, location: Location) { + debug!("visit_local: index={:?} context={:?} location={:?}", index, context, location); // We're only interested in temporaries if self.mir.local_kind(index) != LocalKind::Temp { return; @@ -97,10 +99,15 @@ impl<'tcx> Visitor<'tcx> for TempCollector<'tcx> { // then it's constant and thus drop is noop. // Storage live ranges are also irrelevant. if context.is_drop() || context.is_storage_marker() { + debug!( + "visit_local: context.is_drop={:?} context.is_storage_marker={:?}", + context.is_drop(), context.is_storage_marker(), + ); return; } let temp = &mut self.temps[index]; + debug!("visit_local: temp={:?}", temp); if *temp == TempState::Undefined { match context { PlaceContext::Store | @@ -121,6 +128,7 @@ impl<'tcx> Visitor<'tcx> for TempCollector<'tcx> { PlaceContext::Borrow {..} => true, _ => context.is_nonmutating_use() }; + debug!("visit_local: allowed_use={:?}", allowed_use); if allowed_use { *uses += 1; return; diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 78547abf9d9d3..29e6ef18d2d30 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -84,7 +84,7 @@ impl<'a, 'tcx> Qualif { } /// What kind of item we are in. -#[derive(Copy, Clone, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] enum Mode { Const, Static, @@ -383,6 +383,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { // Collect all the temps we need to promote. let mut promoted_temps = BitSet::new_empty(self.temp_promotion_state.len()); + debug!("qualify_const: promotion_candidates={:?}", self.promotion_candidates); for candidate in &self.promotion_candidates { match *candidate { Candidate::Ref(Location { block: bb, statement_index: stmt_idx }) => { @@ -414,6 +415,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { &local: &Local, _: PlaceContext<'tcx>, _: Location) { + debug!("visit_local: local={:?}", local); let kind = self.mir.local_kind(local); match kind { LocalKind::ReturnPointer => { @@ -435,6 +437,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { } if !self.temp_promotion_state[local].is_promotable() { + debug!("visit_local: (not promotable) local={:?}", local); self.add(Qualif::NOT_PROMOTABLE); } @@ -451,6 +454,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { place: &Place<'tcx>, context: PlaceContext<'tcx>, location: Location) { + debug!("visit_place: place={:?} context={:?} location={:?}", place, context, location); match *place { Place::Local(ref local) => self.visit_local(local, context, location), Place::Promoted(_) => bug!("promoting already promoted MIR"), @@ -557,6 +561,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { } fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) { + debug!("visit_operand: operand={:?} location={:?}", operand, location); self.super_operand(operand, location); match *operand { @@ -591,6 +596,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { } fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) { + debug!("visit_rvalue: rvalue={:?} location={:?}", rvalue, location); // Recurse through operands and places. if let Rvalue::Ref(region, kind, ref place) = *rvalue { let mut is_reborrow = false; @@ -696,6 +702,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { } } + debug!("visit_rvalue: forbidden_mut={:?}", forbidden_mut); if forbidden_mut { self.add(Qualif::NOT_CONST); } else { @@ -709,15 +716,19 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { } place = &proj.base; } + debug!("visit_rvalue: place={:?}", place); if let Place::Local(local) = *place { if self.mir.local_kind(local) == LocalKind::Temp { + debug!("visit_rvalue: local={:?}", local); if let Some(qualif) = self.local_qualif[local] { // `forbidden_mut` is false, so we can safely ignore // `MUTABLE_INTERIOR` from the local's qualifications. // This allows borrowing fields which don't have // `MUTABLE_INTERIOR`, from a type that does, e.g.: // `let _: &'static _ = &(Cell::new(1), 2).1;` + debug!("visit_rvalue: qualif={:?}", qualif); if (qualif - Qualif::MUTABLE_INTERIOR).is_empty() { + debug!("visit_rvalue: candidate={:?}", candidate); self.promotion_candidates.push(candidate); } } @@ -815,6 +826,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { bb: BasicBlock, kind: &TerminatorKind<'tcx>, location: Location) { + debug!("visit_terminator_kind: bb={:?} kind={:?} location={:?}", bb, kind, location); if let TerminatorKind::Call { ref func, ref args, ref destination, .. } = *kind { self.visit_operand(func, location); @@ -967,6 +979,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { let candidate = Candidate::Argument { bb, index: i }; if is_shuffle && i == 2 { if this.qualif.is_empty() { + debug!("visit_terminator_kind: candidate={:?}", candidate); this.promotion_candidates.push(candidate); } else { span_err!(this.tcx.sess, this.span, E0526, @@ -983,6 +996,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { return } if this.qualif.is_empty() { + debug!("visit_terminator_kind: candidate={:?}", candidate); this.promotion_candidates.push(candidate); } else { this.tcx.sess.span_err(this.span, @@ -1056,6 +1070,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { dest: &Place<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) { + debug!("visit_assign: dest={:?} rvalue={:?} location={:?}", dest, rvalue, location); self.visit_rvalue(rvalue, location); // Check the allowed const fn argument forms. @@ -1104,10 +1119,12 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { } fn visit_source_info(&mut self, source_info: &SourceInfo) { + debug!("visit_source_info: source_info={:?}", source_info); self.span = source_info.span; } fn visit_statement(&mut self, bb: BasicBlock, statement: &Statement<'tcx>, location: Location) { + debug!("visit_statement: bb={:?} statement={:?} location={:?}", bb, statement, location); self.nest(|this| { this.visit_source_info(&statement.source_info); match statement.kind { @@ -1131,6 +1148,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { bb: BasicBlock, terminator: &Terminator<'tcx>, location: Location) { + debug!("visit_terminator: bb={:?} terminator={:?} location={:?}", bb, terminator, location); self.nest(|this| this.super_terminator(bb, terminator, location)); } } @@ -1197,6 +1215,7 @@ impl MirPass for QualifyAndPromoteConstants { hir::BodyOwnerKind::Static(hir::MutMutable) => Mode::StaticMut, }; + debug!("run_pass: mode={:?}", mode); if mode == Mode::Fn || mode == Mode::ConstFn { // This is ugly because Qualifier holds onto mir, // which can't be mutated until its scope ends. @@ -1239,6 +1258,7 @@ impl MirPass for QualifyAndPromoteConstants { // In `const` and `static` everything without `StorageDead` // is `'static`, we don't have to create promoted MIR fragments, // just remove `Drop` and `StorageDead` on "promoted" locals. + debug!("run_pass: promoted_temps={:?}", promoted_temps); for block in mir.basic_blocks_mut() { block.statements.retain(|statement| { match statement.kind { From 6c1d71859dc643d18c0043efb41769b298be9634 Mon Sep 17 00:00:00 2001 From: David Wood Date: Fri, 26 Oct 2018 13:21:29 +0200 Subject: [PATCH 02/31] Test for cast causing static promotion failure. This commit adds a test that ensures that a cast in a static doesn't stop const promotion within the static. --- src/test/ui/nll/issue-55288.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/test/ui/nll/issue-55288.rs diff --git a/src/test/ui/nll/issue-55288.rs b/src/test/ui/nll/issue-55288.rs new file mode 100644 index 0000000000000..c0f10ee607cf2 --- /dev/null +++ b/src/test/ui/nll/issue-55288.rs @@ -0,0 +1,21 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(nll)] + +// run-pass + +struct Slice(&'static [&'static [u8]]); + +static MAP: Slice = Slice(&[ + b"CloseEvent" as &'static [u8], +]); + +fn main() {} From 0c3dfe117789078543f5bcece2ad5ee12df64e3b Mon Sep 17 00:00:00 2001 From: David Wood Date: Fri, 26 Oct 2018 13:22:45 +0200 Subject: [PATCH 03/31] Refactor and add `PlaceContext::AscribeUserTy`. This commit refactors `PlaceContext` to split it into four different smaller enums based on if the context represents a mutating use, non-mutating use, maybe-mutating use or a non-use (this is based on the recommendation from @oli-obk on Zulip[1]). This commit then introduces a `PlaceContext::AscribeUserTy` variant. `StatementKind::AscribeUserTy` is now correctly mapped to `PlaceContext::AscribeUserTy` instead of `PlaceContext::Validate`. `PlaceContext::AscribeUserTy` can also now be correctly categorized as a non-use which fixes an issue with constant promotion in statics after a cast introduces a `AscribeUserTy` statement. [1]: https://rust-lang.zulipchat.com/#narrow/stream/122657-wg-nll/subject/.2355288.20cast.20fails.20to.20promote.20to.20'static/near/136536949 --- src/librustc/mir/visit.rs | 290 ++++++++++++------ src/librustc_codegen_llvm/mir/analyze.rs | 49 ++- src/librustc_mir/borrow_check/borrow_set.rs | 17 +- .../borrow_check/nll/type_check/mod.rs | 8 +- src/librustc_mir/borrow_check/used_muts.rs | 3 +- src/librustc_mir/transform/check_unsafety.rs | 12 +- src/librustc_mir/transform/const_prop.rs | 15 +- src/librustc_mir/transform/promote_consts.rs | 21 +- src/librustc_mir/transform/qualify_consts.rs | 23 +- src/librustc_mir/transform/simplify.rs | 6 +- .../transform/uniform_array_move_out.rs | 6 +- src/librustc_mir/util/collect_writes.rs | 18 +- src/librustc_mir/util/liveness.rs | 35 ++- 13 files changed, 308 insertions(+), 195 deletions(-) diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index bfc03923f6011..caa627441ceb6 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -364,33 +364,54 @@ macro_rules! make_mir_visitor { self.visit_assign(block, place, rvalue, location); } StatementKind::FakeRead(_, ref $($mutability)* place) => { - self.visit_place(place, - PlaceContext::Inspect, - location); + self.visit_place( + place, + PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect), + location + ); } StatementKind::EndRegion(_) => {} StatementKind::Validate(_, ref $($mutability)* places) => { for operand in places { - self.visit_place(& $($mutability)* operand.place, - PlaceContext::Validate, location); + self.visit_place( + & $($mutability)* operand.place, + PlaceContext::NonUse(NonUseContext::Validate), + location + ); self.visit_ty(& $($mutability)* operand.ty, TyContext::Location(location)); } } StatementKind::SetDiscriminant{ ref $($mutability)* place, .. } => { - self.visit_place(place, PlaceContext::Store, location); + self.visit_place( + place, + PlaceContext::MutatingUse(MutatingUseContext::Store), + location + ); } StatementKind::StorageLive(ref $($mutability)* local) => { - self.visit_local(local, PlaceContext::StorageLive, location); + self.visit_local( + local, + PlaceContext::NonUse(NonUseContext::StorageLive), + location + ); } StatementKind::StorageDead(ref $($mutability)* local) => { - self.visit_local(local, PlaceContext::StorageDead, location); + self.visit_local( + local, + PlaceContext::NonUse(NonUseContext::StorageDead), + location + ); } StatementKind::InlineAsm { ref $($mutability)* outputs, ref $($mutability)* inputs, asm: _ } => { for output in & $($mutability)* outputs[..] { - self.visit_place(output, PlaceContext::AsmOutput, location); + self.visit_place( + output, + PlaceContext::MutatingUse(MutatingUseContext::AsmOutput), + location + ); } for input in & $($mutability)* inputs[..] { self.visit_operand(input, location); @@ -412,7 +433,11 @@ macro_rules! make_mir_visitor { place: &$($mutability)* Place<'tcx>, rvalue: &$($mutability)* Rvalue<'tcx>, location: Location) { - self.visit_place(place, PlaceContext::Store, location); + self.visit_place( + place, + PlaceContext::MutatingUse(MutatingUseContext::Store), + location + ); self.visit_rvalue(rvalue, location); } @@ -459,7 +484,11 @@ macro_rules! make_mir_visitor { TerminatorKind::Drop { ref $($mutability)* location, target, unwind } => { - self.visit_place(location, PlaceContext::Drop, source_location); + self.visit_place( + location, + PlaceContext::MutatingUse(MutatingUseContext::Drop), + source_location + ); self.visit_branch(block, target); unwind.map(|t| self.visit_branch(block, t)); } @@ -468,7 +497,11 @@ macro_rules! make_mir_visitor { ref $($mutability)* value, target, unwind } => { - self.visit_place(location, PlaceContext::Drop, source_location); + self.visit_place( + location, + PlaceContext::MutatingUse(MutatingUseContext::Drop), + source_location + ); self.visit_operand(value, source_location); self.visit_branch(block, target); unwind.map(|t| self.visit_branch(block, t)); @@ -484,7 +517,11 @@ macro_rules! make_mir_visitor { self.visit_operand(arg, source_location); } if let Some((ref $($mutability)* destination, target)) = *destination { - self.visit_place(destination, PlaceContext::Call, source_location); + self.visit_place( + destination, + PlaceContext::MutatingUse(MutatingUseContext::Call), + source_location + ); self.visit_branch(block, target); } cleanup.map(|t| self.visit_branch(block, t)); @@ -552,14 +589,28 @@ macro_rules! make_mir_visitor { Rvalue::Ref(ref $($mutability)* r, bk, ref $($mutability)* path) => { self.visit_region(r, location); - self.visit_place(path, PlaceContext::Borrow { - region: *r, - kind: bk - }, location); + let ctx = match bk { + BorrowKind::Shared => PlaceContext::NonMutatingUse( + NonMutatingUseContext::SharedBorrow(*r) + ), + BorrowKind::Shallow => PlaceContext::NonMutatingUse( + NonMutatingUseContext::ShallowBorrow(*r) + ), + BorrowKind::Unique => PlaceContext::NonMutatingUse( + NonMutatingUseContext::UniqueBorrow(*r) + ), + BorrowKind::Mut { .. } => + PlaceContext::MutatingUse(MutatingUseContext::Borrow(*r)), + }; + self.visit_place(path, ctx, location); } Rvalue::Len(ref $($mutability)* path) => { - self.visit_place(path, PlaceContext::Inspect, location); + self.visit_place( + path, + PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect), + location + ); } Rvalue::Cast(_cast_kind, @@ -584,7 +635,11 @@ macro_rules! make_mir_visitor { } Rvalue::Discriminant(ref $($mutability)* place) => { - self.visit_place(place, PlaceContext::Inspect, location); + self.visit_place( + place, + PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect), + location + ); } Rvalue::NullaryOp(_op, ref $($mutability)* ty) => { @@ -632,10 +687,18 @@ macro_rules! make_mir_visitor { location: Location) { match *operand { Operand::Copy(ref $($mutability)* place) => { - self.visit_place(place, PlaceContext::Copy, location); + self.visit_place( + place, + PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy), + location + ); } Operand::Move(ref $($mutability)* place) => { - self.visit_place(place, PlaceContext::Move, location); + self.visit_place( + place, + PlaceContext::NonMutatingUse(NonMutatingUseContext::Move), + location + ); } Operand::Constant(ref $($mutability)* constant) => { self.visit_constant(constant, location); @@ -648,7 +711,11 @@ macro_rules! make_mir_visitor { _variance: & $($mutability)* ty::Variance, user_ty: & $($mutability)* UserTypeProjection<'tcx>, location: Location) { - self.visit_place(place, PlaceContext::Validate, location); + self.visit_place( + place, + PlaceContext::NonUse(NonUseContext::AscribeUserTy), + location + ); self.visit_user_type_projection(user_ty); } @@ -693,9 +760,9 @@ macro_rules! make_mir_visitor { ref $($mutability)* elem, } = *proj; let context = if context.is_mutating_use() { - PlaceContext::Projection(Mutability::Mut) + PlaceContext::MutatingUse(MutatingUseContext::Projection) } else { - PlaceContext::Projection(Mutability::Not) + PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection) }; self.visit_place(base, context, location); self.visit_projection_elem(elem, location); @@ -713,7 +780,11 @@ macro_rules! make_mir_visitor { self.visit_ty(ty, TyContext::Location(location)); } ProjectionElem::Index(ref $($mutability)* local) => { - self.visit_local(local, PlaceContext::Copy, location); + self.visit_local( + local, + PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy), + location + ); } ProjectionElem::ConstantIndex { offset: _, min_length: _, @@ -896,125 +967,146 @@ pub enum TyContext { } #[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum PlaceContext<'tcx> { - // Appears as LHS of an assignment - Store, +pub enum NonMutatingUseContext<'tcx> { + /// Being inspected in some way, like loading a len. + Inspect, + /// Consumed as part of an operand. + Copy, + /// Consumed as part of an operand. + Move, + /// Shared borrow. + SharedBorrow(Region<'tcx>), + /// Shallow borrow. + ShallowBorrow(Region<'tcx>), + /// Unique borrow. + UniqueBorrow(Region<'tcx>), + /// Used as base for another place, e.g. `x` in `x.y`. Will not mutate the place. + /// For example, the projection `x.y` is not marked as a mutation in these cases: + /// + /// z = x.y; + /// f(&x.y); + /// + Projection, +} - // Can often be treated as a Store, but needs to be separate because - // ASM is allowed to read outputs as well, so a Store-AsmOutput sequence - // cannot be simplified the way a Store-Store can be. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum MutatingUseContext<'tcx> { + /// Appears as LHS of an assignment. + Store, + /// Can often be treated as a `Store`, but needs to be separate because + /// ASM is allowed to read outputs as well, so a `Store`-`AsmOutput` sequence + /// cannot be simplified the way a `Store`-`Store` can be. AsmOutput, - - // Dest of a call + /// Destination of a call. Call, - - // Being dropped + /// Being dropped. Drop, + /// Mutable borrow. + Borrow(Region<'tcx>), + /// Used as base for another place, e.g. `x` in `x.y`. Could potentially mutate the place. + /// For example, the projection `x.y` is marked as a mutation in these cases: + /// + /// x.y = ...; + /// f(&mut x.y); + /// + Projection, +} - // Being inspected in some way, like loading a len - Inspect, - - // Being borrowed - Borrow { region: Region<'tcx>, kind: BorrowKind }, - - // Used as base for another place, e.g. `x` in `x.y`. - // - // The `Mutability` argument specifies whether the projection is being performed in order to - // (potentially) mutate the place. For example, the projection `x.y` is marked as a mutation - // in these cases: - // - // x.y = ...; - // f(&mut x.y); - // - // But not in these cases: - // - // z = x.y; - // f(&x.y); - Projection(Mutability), - - // Consumed as part of an operand - Copy, - Move, - - // Starting and ending a storage live range +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum NonUseContext { + /// Starting a storage live range. StorageLive, + /// Ending a storage live range. StorageDead, - - // Validation command + /// User type annotation assertions for NLL. + AscribeUserTy, + /// Validation command. Validate, } +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum PlaceContext<'tcx> { + NonMutatingUse(NonMutatingUseContext<'tcx>), + MutatingUse(MutatingUseContext<'tcx>), + NonUse(NonUseContext), +} + impl<'tcx> PlaceContext<'tcx> { - /// Returns true if this place context represents a drop. + /// Returns `true` if this place context represents a drop. pub fn is_drop(&self) -> bool { match *self { - PlaceContext::Drop => true, + PlaceContext::MutatingUse(MutatingUseContext::Drop) => true, + _ => false, + } + } + + /// Returns `true` if this place context represents a borrow. + pub fn is_borrow(&self) -> bool { + match *self { + PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow(..)) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow(..)) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow(..)) | + PlaceContext::MutatingUse(MutatingUseContext::Borrow(..)) => true, _ => false, } } - /// Returns true if this place context represents a storage live or storage dead marker. + /// Returns `true` if this place context represents a storage live or storage dead marker. pub fn is_storage_marker(&self) -> bool { match *self { - PlaceContext::StorageLive | PlaceContext::StorageDead => true, + PlaceContext::NonUse(NonUseContext::StorageLive) | + PlaceContext::NonUse(NonUseContext::StorageDead) => true, _ => false, } } - /// Returns true if this place context represents a storage live marker. + /// Returns `true` if this place context represents a storage live marker. pub fn is_storage_live_marker(&self) -> bool { match *self { - PlaceContext::StorageLive => true, + PlaceContext::NonUse(NonUseContext::StorageLive) => true, _ => false, } } - /// Returns true if this place context represents a storage dead marker. + /// Returns `true` if this place context represents a storage dead marker. pub fn is_storage_dead_marker(&self) -> bool { match *self { - PlaceContext::StorageDead => true, + PlaceContext::NonUse(NonUseContext::StorageDead) => true, _ => false, } } - /// Returns true if this place context represents a use that potentially changes the value. + /// Returns `true` if this place context represents a use that potentially changes the value. pub fn is_mutating_use(&self) -> bool { match *self { - PlaceContext::Store | PlaceContext::AsmOutput | PlaceContext::Call | - PlaceContext::Borrow { kind: BorrowKind::Mut { .. }, .. } | - PlaceContext::Projection(Mutability::Mut) | - PlaceContext::Drop => true, - - PlaceContext::Inspect | - PlaceContext::Borrow { kind: BorrowKind::Shared, .. } | - PlaceContext::Borrow { kind: BorrowKind::Shallow, .. } | - PlaceContext::Borrow { kind: BorrowKind::Unique, .. } | - PlaceContext::Projection(Mutability::Not) | - PlaceContext::Copy | PlaceContext::Move | - PlaceContext::StorageLive | PlaceContext::StorageDead | - PlaceContext::Validate => false, + PlaceContext::MutatingUse(..) => true, + _ => false, } } - /// Returns true if this place context represents a use that does not change the value. + /// Returns `true` if this place context represents a use that does not change the value. pub fn is_nonmutating_use(&self) -> bool { match *self { - PlaceContext::Inspect | - PlaceContext::Borrow { kind: BorrowKind::Shared, .. } | - PlaceContext::Borrow { kind: BorrowKind::Shallow, .. } | - PlaceContext::Borrow { kind: BorrowKind::Unique, .. } | - PlaceContext::Projection(Mutability::Not) | - PlaceContext::Copy | PlaceContext::Move => true, - - PlaceContext::Borrow { kind: BorrowKind::Mut { .. }, .. } | PlaceContext::Store | - PlaceContext::AsmOutput | - PlaceContext::Call | PlaceContext::Projection(Mutability::Mut) | - PlaceContext::Drop | PlaceContext::StorageLive | PlaceContext::StorageDead | - PlaceContext::Validate => false, + PlaceContext::NonMutatingUse(..) => true, + _ => false, } } + /// Returns `true` if this place context represents a use. pub fn is_use(&self) -> bool { - self.is_mutating_use() || self.is_nonmutating_use() + match *self { + PlaceContext::NonUse(..) => false, + _ => true, + } + } + + /// Returns `true` if this place context represents an assignment statement. + pub fn is_place_assignment(&self) -> bool { + match *self { + PlaceContext::MutatingUse(MutatingUseContext::Store) | + PlaceContext::MutatingUse(MutatingUseContext::Call) | + PlaceContext::MutatingUse(MutatingUseContext::AsmOutput) => true, + _ => false, + } } } diff --git a/src/librustc_codegen_llvm/mir/analyze.rs b/src/librustc_codegen_llvm/mir/analyze.rs index 1602ef3c5b795..a63cbe70df611 100644 --- a/src/librustc_codegen_llvm/mir/analyze.rs +++ b/src/librustc_codegen_llvm/mir/analyze.rs @@ -15,7 +15,7 @@ use rustc_data_structures::bit_set::BitSet; use rustc_data_structures::graph::dominators::Dominators; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc::mir::{self, Location, TerminatorKind}; -use rustc::mir::visit::{Visitor, PlaceContext}; +use rustc::mir::visit::{Visitor, PlaceContext, MutatingUseContext, NonMutatingUseContext}; use rustc::mir::traversal; use rustc::ty; use rustc::ty::layout::LayoutOf; @@ -116,7 +116,11 @@ impl Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'll, 'tcx> { self.not_ssa(index); } } else { - self.visit_place(place, PlaceContext::Store, location); + self.visit_place( + place, + PlaceContext::MutatingUse(MutatingUseContext::Store), + location + ); } self.visit_rvalue(rvalue, location); @@ -142,7 +146,11 @@ impl Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'll, 'tcx> { // is not guaranteed to be statically dominated by the // definition of x, so x must always be in an alloca. if let mir::Operand::Move(ref place) = args[0] { - self.visit_place(place, PlaceContext::Drop, location); + self.visit_place( + place, + PlaceContext::MutatingUse(MutatingUseContext::Drop), + location + ); } } } @@ -160,7 +168,8 @@ impl Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'll, 'tcx> { if let mir::Place::Projection(ref proj) = *place { // Allow uses of projections that are ZSTs or from scalar fields. let is_consume = match context { - PlaceContext::Copy | PlaceContext::Move => true, + PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) => true, _ => false }; if is_consume { @@ -190,7 +199,11 @@ impl Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'll, 'tcx> { // A deref projection only reads the pointer, never needs the place. if let mir::ProjectionElem::Deref = proj.elem { - return self.visit_place(&proj.base, PlaceContext::Copy, location); + return self.visit_place( + &proj.base, + PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy), + location + ); } } @@ -202,16 +215,14 @@ impl Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'll, 'tcx> { context: PlaceContext<'tcx>, location: Location) { match context { - PlaceContext::Call => { + PlaceContext::MutatingUse(MutatingUseContext::Call) => { self.assign(local, location); } - PlaceContext::StorageLive | - PlaceContext::StorageDead | - PlaceContext::Validate => {} + PlaceContext::NonUse(_) => {} - PlaceContext::Copy | - PlaceContext::Move => { + PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) => { // Reads from uninitialized variables (e.g. in dead code, after // optimizations) require locals to be in (uninitialized) memory. // NB: there can be uninitialized reads of a local visited after @@ -227,15 +238,19 @@ impl Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'll, 'tcx> { } } - PlaceContext::Inspect | - PlaceContext::Store | - PlaceContext::AsmOutput | - PlaceContext::Borrow { .. } | - PlaceContext::Projection(..) => { + PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect) | + PlaceContext::MutatingUse(MutatingUseContext::Store) | + PlaceContext::MutatingUse(MutatingUseContext::AsmOutput) | + PlaceContext::MutatingUse(MutatingUseContext::Borrow(..)) | + PlaceContext::MutatingUse(MutatingUseContext::Projection) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow(..)) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow(..)) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow(..)) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection) => { self.not_ssa(local); } - PlaceContext::Drop => { + PlaceContext::MutatingUse(MutatingUseContext::Drop) => { let ty = mir::Place::Local(local).ty(self.fx.mir, self.fx.cx.tcx); let ty = self.fx.monomorphize(&ty.to_ty(self.fx.cx.tcx)); diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs index ab44ebc052f30..db56ce4627410 100644 --- a/src/librustc_mir/borrow_check/borrow_set.rs +++ b/src/librustc_mir/borrow_check/borrow_set.rs @@ -12,7 +12,9 @@ use borrow_check::place_ext::PlaceExt; use dataflow::indexes::BorrowIndex; use dataflow::move_paths::MoveData; use rustc::mir::traversal; -use rustc::mir::visit::{PlaceContext, Visitor}; +use rustc::mir::visit::{ + PlaceContext, Visitor, NonUseContext, MutatingUseContext, NonMutatingUseContext +}; use rustc::mir::{self, Location, Mir, Place, Local}; use rustc::ty::{Region, TyCtxt}; use rustc::util::nodemap::{FxHashMap, FxHashSet}; @@ -116,7 +118,7 @@ impl LocalsStateAtExit { impl<'tcx> Visitor<'tcx> for HasStorageDead { fn visit_local(&mut self, local: &Local, ctx: PlaceContext<'tcx>, _: Location) { - if ctx == PlaceContext::StorageDead { + if ctx == PlaceContext::NonUse(NonUseContext::StorageDead) { self.0.insert(*local); } } @@ -266,7 +268,9 @@ impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> { // Watch out: the use of TMP in the borrow itself // doesn't count as an activation. =) - if borrow_data.reserve_location == location && context == PlaceContext::Store { + if borrow_data.reserve_location == location && + context == PlaceContext::MutatingUse(MutatingUseContext::Store) + { return; } @@ -287,10 +291,9 @@ impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> { borrow_data.activation_location = match context { // The use of TMP in a shared borrow does not // count as an actual activation. - PlaceContext::Borrow { kind: mir::BorrowKind::Shared, .. } - | PlaceContext::Borrow { kind: mir::BorrowKind::Shallow, .. } => { - TwoPhaseActivation::NotActivated - } + PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow(..)) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow(..)) => + TwoPhaseActivation::NotActivated, _ => { // Double check: This borrow is indeed a two-phase borrow (that is, // we are 'transitioning' from `NotActivated` to `ActivatedAt`) and diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 33bd009c8b565..f1ebddfd6d658 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -35,7 +35,7 @@ use rustc::infer::outlives::env::RegionBoundPairs; use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime}; use rustc::mir::interpret::EvalErrorKind::BoundsCheck; use rustc::mir::tcx::PlaceTy; -use rustc::mir::visit::{PlaceContext, Visitor}; +use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext, NonMutatingUseContext}; use rustc::mir::*; use rustc::traits::query::type_op; use rustc::traits::query::type_op::custom::CustomTypeOp; @@ -472,9 +472,9 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { } Place::Projection(ref proj) => { let base_context = if context.is_mutating_use() { - PlaceContext::Projection(Mutability::Mut) + PlaceContext::MutatingUse(MutatingUseContext::Projection) } else { - PlaceContext::Projection(Mutability::Not) + PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection) }; let base_ty = self.sanitize_place(&proj.base, location, base_context); if let PlaceTy::Ty { ty } = base_ty { @@ -488,7 +488,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { self.sanitize_projection(base_ty, &proj.elem, place, location) } }; - if let PlaceContext::Copy = context { + if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context { let tcx = self.tcx(); let trait_ref = ty::TraitRef { def_id: tcx.lang_items().copy_trait().unwrap(), diff --git a/src/librustc_mir/borrow_check/used_muts.rs b/src/librustc_mir/borrow_check/used_muts.rs index dbe19bc47859f..dad87ed65a7d4 100644 --- a/src/librustc_mir/borrow_check/used_muts.rs +++ b/src/librustc_mir/borrow_check/used_muts.rs @@ -14,7 +14,6 @@ use rustc::mir::{Local, Location, Place}; use rustc_data_structures::fx::FxHashSet; use borrow_check::MirBorrowckCtxt; -use util::collect_writes::is_place_assignment; impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { /// Walks the MIR looking for assignments to a set of locals, as part of the unused mutable @@ -46,7 +45,7 @@ impl<'visit, 'cx, 'gcx, 'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'visit, 'c return; } - if is_place_assignment(&place_context) { + if place_context.is_place_assignment() { // Propagate the Local assigned at this Location as a used mutable local variable for moi in &self.mbcx.move_data.loc_map[location] { let mpi = &self.mbcx.move_data.moves[*moi].path; diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index ae881bad58dcd..edd15c39fed3e 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -19,7 +19,7 @@ use rustc::hir::Node; use rustc::hir::def_id::DefId; use rustc::lint::builtin::{SAFE_EXTERN_STATICS, SAFE_PACKED_BORROWS, UNUSED_UNSAFE}; use rustc::mir::*; -use rustc::mir::visit::{PlaceContext, Visitor}; +use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext}; use syntax::ast; use syntax::symbol::Symbol; @@ -152,7 +152,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { place: &Place<'tcx>, context: PlaceContext<'tcx>, location: Location) { - if let PlaceContext::Borrow { .. } = context { + if context.is_borrow() { if util::is_disaligned(self.tcx, self.mir, self.param_env, place) { let source_info = self.source_info; let lint_root = @@ -193,9 +193,11 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { } ty::Adt(adt, _) => { if adt.is_union() { - if context == PlaceContext::Store || - context == PlaceContext::AsmOutput || - context == PlaceContext::Drop + if context == PlaceContext::MutatingUse(MutatingUseContext::Store) || + context == PlaceContext::MutatingUse(MutatingUseContext::Drop) || + context == PlaceContext::MutatingUse( + MutatingUseContext::AsmOutput + ) { let elem_ty = match elem { &ProjectionElem::Field(_, ty) => ty, diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 626baf207eebc..51644a6bba236 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -16,7 +16,7 @@ use rustc::hir::def::Def; use rustc::mir::{Constant, Location, Place, Mir, Operand, Rvalue, Local}; use rustc::mir::{NullOp, UnOp, StatementKind, Statement, BasicBlock, LocalKind}; use rustc::mir::{TerminatorKind, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem}; -use rustc::mir::visit::{Visitor, PlaceContext}; +use rustc::mir::visit::{Visitor, PlaceContext, MutatingUseContext, NonMutatingUseContext}; use rustc::mir::interpret::{ ConstEvalErr, EvalErrorKind, Scalar, GlobalId, EvalResult }; @@ -529,17 +529,18 @@ impl<'tcx> Visitor<'tcx> for CanConstProp { // Constants must have at most one write // FIXME(oli-obk): we could be more powerful here, if the multiple writes // only occur in independent execution paths - Store => if self.found_assignment[local] { + MutatingUse(MutatingUseContext::Store) => if self.found_assignment[local] { self.can_const_prop[local] = false; } else { self.found_assignment[local] = true }, // Reading constants is allowed an arbitrary number of times - Copy | Move | - StorageDead | StorageLive | - Validate | - Projection(_) | - Inspect => {}, + NonMutatingUse(NonMutatingUseContext::Copy) | + NonMutatingUse(NonMutatingUseContext::Move) | + NonMutatingUse(NonMutatingUseContext::Inspect) | + NonMutatingUse(NonMutatingUseContext::Projection) | + MutatingUse(MutatingUseContext::Projection) | + NonUse(_) => {}, _ => self.can_const_prop[local] = false, } } diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 790e6e82723ef..629211a7b554d 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -23,7 +23,7 @@ //! move analysis runs after promotion on broken MIR. use rustc::mir::*; -use rustc::mir::visit::{PlaceContext, MutVisitor, Visitor}; +use rustc::mir::visit::{PlaceContext, MutatingUseContext, MutVisitor, Visitor}; use rustc::mir::traversal::ReversePostorder; use rustc::ty::TyCtxt; use syntax_pos::Span; @@ -97,11 +97,11 @@ impl<'tcx> Visitor<'tcx> for TempCollector<'tcx> { // Ignore drops, if the temp gets promoted, // then it's constant and thus drop is noop. - // Storage live ranges are also irrelevant. - if context.is_drop() || context.is_storage_marker() { + // Non-uses are also irrelevent. + if context.is_drop() || !context.is_use() { debug!( - "visit_local: context.is_drop={:?} context.is_storage_marker={:?}", - context.is_drop(), context.is_storage_marker(), + "visit_local: context.is_drop={:?} context.is_use={:?}", + context.is_drop(), context.is_use(), ); return; } @@ -110,9 +110,9 @@ impl<'tcx> Visitor<'tcx> for TempCollector<'tcx> { debug!("visit_local: temp={:?}", temp); if *temp == TempState::Undefined { match context { - PlaceContext::Store | - PlaceContext::AsmOutput | - PlaceContext::Call => { + PlaceContext::MutatingUse(MutatingUseContext::Store) | + PlaceContext::MutatingUse(MutatingUseContext::AsmOutput) | + PlaceContext::MutatingUse(MutatingUseContext::Call) => { *temp = TempState::Defined { location, uses: 0 @@ -124,10 +124,7 @@ impl<'tcx> Visitor<'tcx> for TempCollector<'tcx> { } else if let TempState::Defined { ref mut uses, .. } = *temp { // We always allow borrows, even mutable ones, as we need // to promote mutable borrows of some ZSTs e.g. `&mut []`. - let allowed_use = match context { - PlaceContext::Borrow {..} => true, - _ => context.is_nonmutating_use() - }; + let allowed_use = context.is_borrow() || context.is_nonmutating_use(); debug!("visit_local: allowed_use={:?}", allowed_use); if allowed_use { *uses += 1; diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 29e6ef18d2d30..c78fb51961819 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -26,7 +26,7 @@ use rustc::ty::cast::CastTy; use rustc::ty::query::Providers; use rustc::mir::*; use rustc::mir::traversal::ReversePostorder; -use rustc::mir::visit::{PlaceContext, Visitor}; +use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext, NonMutatingUseContext}; use rustc::middle::lang_items; use rustc_target::spec::abi::Abi; use syntax::ast::LitKind; @@ -271,7 +271,11 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { // This must be an explicit assignment. _ => { // Catch more errors in the destination. - self.visit_place(dest, PlaceContext::Store, location); + self.visit_place( + dest, + PlaceContext::MutatingUse(MutatingUseContext::Store), + location + ); self.statement_like(); } } @@ -610,10 +614,17 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { } if is_reborrow { - self.super_place(place, PlaceContext::Borrow { - region, - kind - }, location); + let ctx = match kind { + BorrowKind::Shared => + PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow(region)), + BorrowKind::Shallow => + PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow(region)), + BorrowKind::Unique => + PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow(region)), + BorrowKind::Mut { .. } => + PlaceContext::MutatingUse(MutatingUseContext::Borrow(region)), + }; + self.super_place(place, ctx, location); } else { self.super_rvalue(rvalue, location); } diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index a6e0932bf0ace..c20d40af50151 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -331,8 +331,10 @@ struct DeclMarker { impl<'tcx> Visitor<'tcx> for DeclMarker { fn visit_local(&mut self, local: &Local, ctx: PlaceContext<'tcx>, _: Location) { - // ignore these altogether, they get removed along with their otherwise unused decls. - if ctx != PlaceContext::StorageLive && ctx != PlaceContext::StorageDead { + // Ignore storage markers altogether, they get removed along with their otherwise unused + // decls. + // FIXME: Extend this to all non-uses. + if !ctx.is_storage_marker() { self.locals.insert(*local); } } diff --git a/src/librustc_mir/transform/uniform_array_move_out.rs b/src/librustc_mir/transform/uniform_array_move_out.rs index b123a846596e5..949b8f74f71e9 100644 --- a/src/librustc_mir/transform/uniform_array_move_out.rs +++ b/src/librustc_mir/transform/uniform_array_move_out.rs @@ -39,7 +39,7 @@ use rustc::ty; use rustc::ty::TyCtxt; use rustc::mir::*; -use rustc::mir::visit::{Visitor, PlaceContext}; +use rustc::mir::visit::{Visitor, PlaceContext, NonUseContext}; use transform::{MirPass, MirSource}; use util::patch::MirPatch; use rustc_data_structures::indexed_vec::{IndexVec}; @@ -316,8 +316,8 @@ impl<'tcx> Visitor<'tcx> for RestoreDataCollector { location: Location) { let local_use = &mut self.locals_use[*local]; match context { - PlaceContext::StorageLive => local_use.alive = Some(location), - PlaceContext::StorageDead => local_use.dead = Some(location), + PlaceContext::NonUse(NonUseContext::StorageLive) => local_use.alive = Some(location), + PlaceContext::NonUse(NonUseContext::StorageDead) => local_use.dead = Some(location), _ => { local_use.use_count += 1; if local_use.first_use.is_none() { diff --git a/src/librustc_mir/util/collect_writes.rs b/src/librustc_mir/util/collect_writes.rs index 23f753f8569bb..3e1d0852deedf 100644 --- a/src/librustc_mir/util/collect_writes.rs +++ b/src/librustc_mir/util/collect_writes.rs @@ -43,24 +43,8 @@ impl<'tcx> Visitor<'tcx> for FindLocalAssignmentVisitor { return; } - if is_place_assignment(&place_context) { + if place_context.is_place_assignment() { self.locations.push(location); } } } - -/// Returns true if this place context represents an assignment statement -crate fn is_place_assignment(place_context: &PlaceContext) -> bool { - match *place_context { - PlaceContext::Store | PlaceContext::Call | PlaceContext::AsmOutput => true, - PlaceContext::Drop - | PlaceContext::Inspect - | PlaceContext::Borrow { .. } - | PlaceContext::Projection(..) - | PlaceContext::Copy - | PlaceContext::Move - | PlaceContext::StorageLive - | PlaceContext::StorageDead - | PlaceContext::Validate => false, - } -} diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index 420ca4efde37d..d16094e8238de 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -33,7 +33,9 @@ //! generator yield points, all pre-existing references are invalidated, so this //! doesn't matter). -use rustc::mir::visit::{PlaceContext, Visitor}; +use rustc::mir::visit::{ + PlaceContext, Visitor, MutatingUseContext, NonMutatingUseContext, NonUseContext, +}; use rustc::mir::Local; use rustc::mir::*; use rustc::ty::{item_path, TyCtxt}; @@ -161,10 +163,10 @@ pub fn categorize<'tcx>(context: PlaceContext<'tcx>) -> Option { /////////////////////////////////////////////////////////////////////////// // DEFS - PlaceContext::Store | + PlaceContext::MutatingUse(MutatingUseContext::Store) | // This is potentially both a def and a use... - PlaceContext::AsmOutput | + PlaceContext::MutatingUse(MutatingUseContext::AsmOutput) | // We let Call define the result in both the success and // unwind cases. This is not really correct, however it @@ -172,12 +174,12 @@ pub fn categorize<'tcx>(context: PlaceContext<'tcx>) -> Option { // generate MIR. To do things properly, we would apply // the def in call only to the input from the success // path and not the unwind path. -nmatsakis - PlaceContext::Call | + PlaceContext::MutatingUse(MutatingUseContext::Call) | // Storage live and storage dead aren't proper defines, but we can ignore // values that come before them. - PlaceContext::StorageLive | - PlaceContext::StorageDead => Some(DefUse::Def), + PlaceContext::NonUse(NonUseContext::StorageLive) | + PlaceContext::NonUse(NonUseContext::StorageDead) => Some(DefUse::Def), /////////////////////////////////////////////////////////////////////////// // REGULAR USES @@ -186,18 +188,23 @@ pub fn categorize<'tcx>(context: PlaceContext<'tcx>) -> Option { // purposes of NLL, these are special in that **all** the // lifetimes appearing in the variable must be live for each regular use. - PlaceContext::Projection(..) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection) | + PlaceContext::MutatingUse(MutatingUseContext::Projection) | // Borrows only consider their local used at the point of the borrow. // This won't affect the results since we use this analysis for generators // and we only care about the result at suspension points. Borrows cannot // cross suspension points so this behavior is unproblematic. - PlaceContext::Borrow { .. } | - - PlaceContext::Inspect | - PlaceContext::Copy | - PlaceContext::Move | - PlaceContext::Validate => + PlaceContext::MutatingUse(MutatingUseContext::Borrow(..)) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow(..)) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow(..)) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow(..)) | + + PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) | + PlaceContext::NonUse(NonUseContext::AscribeUserTy) | + PlaceContext::NonUse(NonUseContext::Validate) => Some(DefUse::Use), /////////////////////////////////////////////////////////////////////////// @@ -208,7 +215,7 @@ pub fn categorize<'tcx>(context: PlaceContext<'tcx>) -> Option { // uses in drop are special because `#[may_dangle]` // attributes can affect whether lifetimes must be live. - PlaceContext::Drop => + PlaceContext::MutatingUse(MutatingUseContext::Drop) => Some(DefUse::Drop), } } From 8a6f4c819bef9e7bc473fbfe14dd2a4f59447f93 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sun, 18 Nov 2018 10:07:25 -0500 Subject: [PATCH 04/31] remove "approx env bounds" if we already know from trait --- src/librustc/infer/outlives/obligations.rs | 30 ++++++++++++++---- src/test/ui/nll/ty-outlives/issue-55756.rs | 37 ++++++++++++++++++++++ 2 files changed, 60 insertions(+), 7 deletions(-) create mode 100644 src/test/ui/nll/ty-outlives/issue-55756.rs diff --git a/src/librustc/infer/outlives/obligations.rs b/src/librustc/infer/outlives/obligations.rs index 5db850f1588b6..0215b0380bdf3 100644 --- a/src/librustc/infer/outlives/obligations.rs +++ b/src/librustc/infer/outlives/obligations.rs @@ -388,22 +388,38 @@ where // rule might not apply (but another rule might). For now, we err // on the side of adding too few edges into the graph. + // Compute the bounds we can derive from the trait definition. + // These are guaranteed to apply, no matter the inference + // results. + let trait_bounds: Vec<_> = self.verify_bound + .projection_declared_bounds_from_trait(projection_ty) + .collect(); + // Compute the bounds we can derive from the environment. This // is an "approximate" match -- in some cases, these bounds // may not apply. - let approx_env_bounds = self.verify_bound + let mut approx_env_bounds = self.verify_bound .projection_approx_declared_bounds_from_env(projection_ty); debug!( "projection_must_outlive: approx_env_bounds={:?}", approx_env_bounds ); - // Compute the bounds we can derive from the trait definition. - // These are guaranteed to apply, no matter the inference - // results. - let trait_bounds: Vec<_> = self.verify_bound - .projection_declared_bounds_from_trait(projection_ty) - .collect(); + // Remove outlives bounds that we get from the environment but + // which are also deducable from the trait. This arises (cc + // #55756) in cases where you have e.g. `>::Item: + // 'a` in the environment but `trait Foo<'b> { type Item: 'b + // }` in the trait definition. + approx_env_bounds.retain(|bound| { + match bound.0.sty { + ty::Projection(projection_ty) => { + self.verify_bound.projection_declared_bounds_from_trait(projection_ty) + .all(|r| r != bound.1) + } + + _ => panic!("expected only projection types from env, not {:?}", bound.0), + } + }); // If declared bounds list is empty, the only applicable rule is // OutlivesProjectionComponent. If there are inference variables, diff --git a/src/test/ui/nll/ty-outlives/issue-55756.rs b/src/test/ui/nll/ty-outlives/issue-55756.rs new file mode 100644 index 0000000000000..cda3915849e2d --- /dev/null +++ b/src/test/ui/nll/ty-outlives/issue-55756.rs @@ -0,0 +1,37 @@ +// Regression test for #55756. +// +// In this test, the result of `self.callee` is a projection `>::Guard`. As it may contain a destructor, the dropck +// rules require that this type outlivess the scope of `state`. Unfortunately, +// our region inference is not smart enough to figure out how to +// translate a requirement like +// +// >::guard: 'r +// +// into a requirement that `'0: 'r` -- in particular, it fails to do +// so because it *also* knows that `>::Guard: 'a` +// from the trait definition. Faced with so many choices, the current +// solver opts to do nothing. +// +// Fixed by tweaking the solver to recognize that the constraint from +// the environment duplicates one from the trait. +// +// compile-pass + +#![crate_type="lib"] + +pub trait Database<'a> { + type Guard: 'a; +} + +pub struct Stateful<'a, D: 'a>(&'a D); + +impl<'b, D: for <'a> Database<'a>> Stateful<'b, D> { + pub fn callee<'a>(&'a self) -> >::Guard { + unimplemented!() + } + pub fn caller<'a>(&'a self) -> >::Guard { + let state = self.callee(); + unimplemented!() + } +} From 410f5207874eab36cbfac080782d00c86642f2f1 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 16 Nov 2018 08:25:46 -0500 Subject: [PATCH 05/31] improve debug output related to bound calculation --- src/librustc/traits/mod.rs | 7 ++++++- src/librustc_typeck/collect.rs | 1 + src/librustc_typeck/outlives/implicit_infer.rs | 17 +++++++++++++---- src/librustc_typeck/outlives/mod.rs | 3 +++ 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 8bceebb23950c..c7e5d89007418 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -693,7 +693,12 @@ fn do_normalize_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, predicates: Vec>) -> Result>, ErrorReported> { - debug!("do_normalize_predicates({:?})", predicates); + debug!( + "do_normalize_predicates(predicates={:?}, region_context={:?}, cause={:?})", + predicates, + region_context, + cause, + ); let span = cause.span; tcx.infer_ctxt().enter(|infcx| { // FIXME. We should really... do something with these region diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index eb52a013b0566..b33b21478ca4b 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1591,6 +1591,7 @@ fn predicates_defined_on<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, ) -> ty::GenericPredicates<'tcx> { + debug!("predicates_defined_on({:?})", def_id); let explicit = tcx.explicit_predicates_of(def_id); let span = tcx.def_span(def_id); let predicates = explicit.predicates.into_iter().chain( diff --git a/src/librustc_typeck/outlives/implicit_infer.rs b/src/librustc_typeck/outlives/implicit_infer.rs index 132da8f5cea8d..101edac04c7d4 100644 --- a/src/librustc_typeck/outlives/implicit_infer.rs +++ b/src/librustc_typeck/outlives/implicit_infer.rs @@ -245,6 +245,7 @@ fn insert_required_predicates_to_be_wf<'tcx>( } } +#[derive(Debug)] pub struct IgnoreSelfTy(bool); /// We also have to check the explicit predicates @@ -270,10 +271,18 @@ pub fn check_explicit_predicates<'tcx>( explicit_map: &mut ExplicitPredicatesMap<'tcx>, ignore_self_ty: IgnoreSelfTy, ) { - debug!("def_id = {:?}", &def_id); - debug!("substs = {:?}", &substs); - debug!("explicit_map = {:?}", explicit_map); - debug!("required_predicates = {:?}", required_predicates); + debug!( + "check_explicit_predicates(def_id={:?}, \ + substs={:?}, \ + explicit_map={:?}, \ + required_predicates={:?}, \ + ignore_self_ty={:?})", + def_id, + substs, + explicit_map, + required_predicates, + ignore_self_ty, + ); let explicit_predicates = explicit_map.explicit_predicates_of(tcx, *def_id); for outlives_predicate in explicit_predicates.iter() { diff --git a/src/librustc_typeck/outlives/mod.rs b/src/librustc_typeck/outlives/mod.rs index cca77b20d9b30..1eb53ffc730f6 100644 --- a/src/librustc_typeck/outlives/mod.rs +++ b/src/librustc_typeck/outlives/mod.rs @@ -67,6 +67,9 @@ fn inferred_outlives_of<'a, 'tcx>( } err.emit(); } + + debug!("inferred_outlives_of({:?}) = {:?}", item_def_id, predicates); + predicates } From 84afecccdca8d771e5ae0734bda928304df30dc3 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 16 Nov 2018 08:58:55 -0500 Subject: [PATCH 06/31] handle trait objects formed from traits with `Self::Foo: 'a` clauses --- .../outlives/implicit_infer.rs | 21 ++++++++++++++----- .../ui/rfc-2093-infer-outlives/issue-54467.rs | 17 +++++++++++++++ 2 files changed, 33 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/rfc-2093-infer-outlives/issue-54467.rs diff --git a/src/librustc_typeck/outlives/implicit_infer.rs b/src/librustc_typeck/outlives/implicit_infer.rs index 101edac04c7d4..30e304375fe0e 100644 --- a/src/librustc_typeck/outlives/implicit_infer.rs +++ b/src/librustc_typeck/outlives/implicit_infer.rs @@ -14,6 +14,7 @@ use rustc::hir::def_id::DefId; use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::ty::subst::{Kind, Subst, UnpackedKind}; use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::fold::TypeFoldable; use rustc::util::nodemap::FxHashMap; use super::explicit::ExplicitPredicatesMap; @@ -311,13 +312,23 @@ pub fn check_explicit_predicates<'tcx>( // // Note that we do this check for self **before** applying `substs`. In the // case that `substs` come from a `dyn Trait` type, our caller will have - // included `Self = dyn Trait<'x, X>` as the value for `Self`. If we were + // included `Self = usize` as the value for `Self`. If we were // to apply the substs, and not filter this predicate, we might then falsely // conclude that e.g. `X: 'x` was a reasonable inferred requirement. - if let UnpackedKind::Type(ty) = outlives_predicate.0.unpack() { - if ty.is_self() && ignore_self_ty.0 { - debug!("skipping self ty = {:?}", &ty); - continue; + // + // Another similar case is where we have a inferred + // requirement like `::Foo: 'b`. We presently + // ignore such requirements as well (cc #54467)-- though + // conceivably it might be better if we could extract the `Foo + // = X` binding from the object type (there must be such a + // binding) and thus infer an outlives requirement that `X: + // 'b`. + if ignore_self_ty.0 { + if let UnpackedKind::Type(ty) = outlives_predicate.0.unpack() { + if ty.has_self_ty() { + debug!("skipping self ty = {:?}", &ty); + continue; + } } } diff --git a/src/test/ui/rfc-2093-infer-outlives/issue-54467.rs b/src/test/ui/rfc-2093-infer-outlives/issue-54467.rs new file mode 100644 index 0000000000000..438923e29246c --- /dev/null +++ b/src/test/ui/rfc-2093-infer-outlives/issue-54467.rs @@ -0,0 +1,17 @@ +// Regression test for #54467: +// +// Here, the trait object has an "inferred outlives" requirement that +// `>::Item: 'a`; but since we don't know what +// `Self` is, we were (incorrectly) messing things up, leading to +// strange errors. This test ensures that we do not give compilation +// errors. +// +// compile-pass + +trait MyIterator<'a>: Iterator where Self::Item: 'a { } + +struct MyStruct<'a, A> { + item: Box> +} + +fn main() { } From 0a26e7959aad8b354636862c3847940320307cc9 Mon Sep 17 00:00:00 2001 From: varkor Date: Sat, 10 Nov 2018 18:08:50 +0000 Subject: [PATCH 07/31] Rewrite `...` as `..=` as a MachineApplicable 2018 idiom lint --- src/librustc/lint/context.rs | 7 ++- src/librustc/lint/mod.rs | 2 +- src/librustc_lint/builtin.rs | 44 ++++++++++++++----- src/librustc_lint/unused.rs | 4 +- .../lint/inclusive-range-pattern-syntax.fixed | 6 +++ .../ui/lint/inclusive-range-pattern-syntax.rs | 6 +++ .../inclusive-range-pattern-syntax.stderr | 6 +++ .../range-inclusive-pattern-precedence.stderr | 4 +- 8 files changed, 62 insertions(+), 17 deletions(-) diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 7e2532bb1c4e8..ebb495fdfcee6 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -1020,9 +1020,12 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> { } fn visit_pat(&mut self, p: &'a ast::Pat) { - run_lints!(self, check_pat, p); + let mut visit_subpats = true; + run_lints!(self, check_pat, p, &mut visit_subpats); self.check_id(p.id); - ast_visit::walk_pat(self, p); + if visit_subpats { + ast_visit::walk_pat(self, p); + } } fn visit_expr(&mut self, e: &'a ast::Expr) { diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 5ac0c0d32dcdc..c1e439ce607d4 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -341,7 +341,7 @@ pub trait EarlyLintPass: LintPass { fn check_block_post(&mut self, _: &EarlyContext<'_>, _: &ast::Block) { } fn check_stmt(&mut self, _: &EarlyContext<'_>, _: &ast::Stmt) { } fn check_arm(&mut self, _: &EarlyContext<'_>, _: &ast::Arm) { } - fn check_pat(&mut self, _: &EarlyContext<'_>, _: &ast::Pat) { } + fn check_pat(&mut self, _: &EarlyContext<'_>, _: &ast::Pat, _: &mut bool) { } fn check_expr(&mut self, _: &EarlyContext<'_>, _: &ast::Expr) { } fn check_expr_post(&mut self, _: &EarlyContext<'_>, _: &ast::Expr) { } fn check_ty(&mut self, _: &EarlyContext<'_>, _: &ast::Ty) { } diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 19f9168cf0a0e..fec9542680fb0 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -40,6 +40,8 @@ use rustc::util::nodemap::FxHashSet; use syntax::tokenstream::{TokenTree, TokenStream}; use syntax::ast; +use syntax::ptr::P; +use syntax::ast::Expr; use syntax::attr; use syntax::source_map::Spanned; use syntax::edition::Edition; @@ -47,6 +49,7 @@ use syntax::feature_gate::{AttributeGate, AttributeType, Stability, deprecated_a use syntax_pos::{BytePos, Span, SyntaxContext}; use syntax::symbol::keywords; use syntax::errors::{Applicability, DiagnosticBuilder}; +use syntax::print::pprust::expr_to_string; use rustc::hir::{self, GenericParamKind, PatKind}; use rustc::hir::intravisit::FnKind; @@ -1477,21 +1480,42 @@ impl LintPass for EllipsisInclusiveRangePatterns { } impl EarlyLintPass for EllipsisInclusiveRangePatterns { - fn check_pat(&mut self, cx: &EarlyContext, pat: &ast::Pat) { - use self::ast::{PatKind, RangeEnd, RangeSyntax}; + fn check_pat(&mut self, cx: &EarlyContext, pat: &ast::Pat, visit_subpats: &mut bool) { + use self::ast::{PatKind, RangeEnd, RangeSyntax::DotDotDot}; + + /// If `pat` is a `...` pattern, return the start and end of the range, as well as the span + /// corresponding to the ellipsis. + fn matches_ellipsis_pat(pat: &ast::Pat) -> Option<(&P, &P, Span)> { + match &pat.node { + PatKind::Range(a, b, Spanned { span, node: RangeEnd::Included(DotDotDot), .. }) => { + Some((a, b, *span)) + } + _ => None, + } + } + + let (parenthesise, endpoints) = match &pat.node { + PatKind::Ref(subpat, _) => (true, matches_ellipsis_pat(&subpat)), + _ => (false, matches_ellipsis_pat(pat)), + }; - if let PatKind::Range( - _, _, Spanned { span, node: RangeEnd::Included(RangeSyntax::DotDotDot) } - ) = pat.node { + if let Some((start, end, join)) = endpoints { let msg = "`...` range patterns are deprecated"; + let suggestion = "use `..=` for an inclusive range"; + let (span, replacement) = if parenthesise { + *visit_subpats = false; + (pat.span, format!("&({}..={})", expr_to_string(&start), expr_to_string(&end))) + } else { + (join, "..=".to_owned()) + }; let mut err = cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, span, msg); err.span_suggestion_short_with_applicability( - span, "use `..=` for an inclusive range", "..=".to_owned(), - // FIXME: outstanding problem with precedence in ref patterns: - // https://github.com/rust-lang/rust/issues/51043#issuecomment-392252285 - Applicability::MaybeIncorrect + span, + suggestion, + replacement, + Applicability::MachineApplicable, ); - err.emit() + err.emit(); } } } diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 9ccfecd46fdb2..049bcc3010be1 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -397,12 +397,12 @@ impl EarlyLintPass for UnusedParens { self.check_unused_parens_expr(cx, &value, msg, followed_by_block); } - fn check_pat(&mut self, cx: &EarlyContext, p: &ast::Pat) { + fn check_pat(&mut self, cx: &EarlyContext, p: &ast::Pat, _: &mut bool) { use ast::PatKind::{Paren, Range}; // The lint visitor will visit each subpattern of `p`. We do not want to lint any range // pattern no matter where it occurs in the pattern. For something like `&(a..=b)`, there // is a recursive `check_pat` on `a` and `b`, but we will assume that if there are - // unnecessry parens they serve a purpose of readability. + // unnecessary parens they serve a purpose of readability. if let Paren(ref pat) = p.node { match pat.node { Range(..) => {} diff --git a/src/test/ui/lint/inclusive-range-pattern-syntax.fixed b/src/test/ui/lint/inclusive-range-pattern-syntax.fixed index d16859df79e25..f0aee8a51f18b 100644 --- a/src/test/ui/lint/inclusive-range-pattern-syntax.fixed +++ b/src/test/ui/lint/inclusive-range-pattern-syntax.fixed @@ -20,4 +20,10 @@ fn main() { //~^ WARN `...` range patterns are deprecated _ => {} } + + match &despondency { + &(1..=2) => {} + //~^ WARN `...` range patterns are deprecated + _ => {} + } } diff --git a/src/test/ui/lint/inclusive-range-pattern-syntax.rs b/src/test/ui/lint/inclusive-range-pattern-syntax.rs index 9d418aec0858f..97bc04faa774b 100644 --- a/src/test/ui/lint/inclusive-range-pattern-syntax.rs +++ b/src/test/ui/lint/inclusive-range-pattern-syntax.rs @@ -20,4 +20,10 @@ fn main() { //~^ WARN `...` range patterns are deprecated _ => {} } + + match &despondency { + &1...2 => {} + //~^ WARN `...` range patterns are deprecated + _ => {} + } } diff --git a/src/test/ui/lint/inclusive-range-pattern-syntax.stderr b/src/test/ui/lint/inclusive-range-pattern-syntax.stderr index de04fed589b23..9226137f1152f 100644 --- a/src/test/ui/lint/inclusive-range-pattern-syntax.stderr +++ b/src/test/ui/lint/inclusive-range-pattern-syntax.stderr @@ -10,3 +10,9 @@ note: lint level defined here LL | #![warn(ellipsis_inclusive_range_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +warning: `...` range patterns are deprecated + --> $DIR/inclusive-range-pattern-syntax.rs:25:9 + | +LL | &1...2 => {} + | ^^^^^^ help: use `..=` for an inclusive range + diff --git a/src/test/ui/range/range-inclusive-pattern-precedence.stderr b/src/test/ui/range/range-inclusive-pattern-precedence.stderr index cd5ce3035c683..3ac6be2b8ea6a 100644 --- a/src/test/ui/range/range-inclusive-pattern-precedence.stderr +++ b/src/test/ui/range/range-inclusive-pattern-precedence.stderr @@ -11,10 +11,10 @@ LL | box 10..=15 => {} | ^^^^^^^ help: add parentheses to clarify the precedence: `(10 ..=15)` warning: `...` range patterns are deprecated - --> $DIR/range-inclusive-pattern-precedence.rs:24:11 + --> $DIR/range-inclusive-pattern-precedence.rs:24:9 | LL | &0...9 => {} - | ^^^ help: use `..=` for an inclusive range + | ^^^^^^ help: use `..=` for an inclusive range | note: lint level defined here --> $DIR/range-inclusive-pattern-precedence.rs:19:9 From 9ab3b0fa0032ae539cb1093771c81c6df0b94374 Mon Sep 17 00:00:00 2001 From: varkor Date: Sat, 10 Nov 2018 21:27:40 +0000 Subject: [PATCH 08/31] Use non-short suggestion for parenthesised ..= --- src/librustc_lint/builtin.rs | 28 +++++++++++-------- .../inclusive-range-pattern-syntax.stderr | 2 +- .../range-inclusive-pattern-precedence.stderr | 2 +- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index fec9542680fb0..7291e27048280 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1502,20 +1502,26 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns { if let Some((start, end, join)) = endpoints { let msg = "`...` range patterns are deprecated"; let suggestion = "use `..=` for an inclusive range"; - let (span, replacement) = if parenthesise { + if parenthesise { *visit_subpats = false; - (pat.span, format!("&({}..={})", expr_to_string(&start), expr_to_string(&end))) + let mut err = cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, pat.span, msg); + err.span_suggestion_with_applicability( + pat.span, + suggestion, + format!("&({}..={})", expr_to_string(&start), expr_to_string(&end)), + Applicability::MachineApplicable, + ); + err.emit(); } else { - (join, "..=".to_owned()) + let mut err = cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, join, msg); + err.span_suggestion_short_with_applicability( + join, + suggestion, + "..=".to_owned(), + Applicability::MachineApplicable, + ); + err.emit(); }; - let mut err = cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, span, msg); - err.span_suggestion_short_with_applicability( - span, - suggestion, - replacement, - Applicability::MachineApplicable, - ); - err.emit(); } } } diff --git a/src/test/ui/lint/inclusive-range-pattern-syntax.stderr b/src/test/ui/lint/inclusive-range-pattern-syntax.stderr index 9226137f1152f..b13afdbc023d4 100644 --- a/src/test/ui/lint/inclusive-range-pattern-syntax.stderr +++ b/src/test/ui/lint/inclusive-range-pattern-syntax.stderr @@ -14,5 +14,5 @@ warning: `...` range patterns are deprecated --> $DIR/inclusive-range-pattern-syntax.rs:25:9 | LL | &1...2 => {} - | ^^^^^^ help: use `..=` for an inclusive range + | ^^^^^^ help: use `..=` for an inclusive range: `&(1..=2)` diff --git a/src/test/ui/range/range-inclusive-pattern-precedence.stderr b/src/test/ui/range/range-inclusive-pattern-precedence.stderr index 3ac6be2b8ea6a..6fa67a5d4fa30 100644 --- a/src/test/ui/range/range-inclusive-pattern-precedence.stderr +++ b/src/test/ui/range/range-inclusive-pattern-precedence.stderr @@ -14,7 +14,7 @@ warning: `...` range patterns are deprecated --> $DIR/range-inclusive-pattern-precedence.rs:24:9 | LL | &0...9 => {} - | ^^^^^^ help: use `..=` for an inclusive range + | ^^^^^^ help: use `..=` for an inclusive range: `&(0..=9)` | note: lint level defined here --> $DIR/range-inclusive-pattern-precedence.rs:19:9 From 45418275c2ca9633516d1a302e94afec57b79d1c Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Thu, 8 Nov 2018 19:06:16 -0600 Subject: [PATCH 09/31] don't inline `pub use some_crate` unless directly asked to --- src/doc/rustdoc/src/the-doc-attribute.md | 3 ++ src/librustdoc/clean/mod.rs | 15 +++++++- .../inline_cross/auxiliary/use_crate.rs | 15 ++++++++ .../inline_cross/auxiliary/use_crate_2.rs | 11 ++++++ src/test/rustdoc/inline_cross/use_crate.rs | 37 +++++++++++++++++++ src/test/rustdoc/src-links-external.rs | 1 + 6 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 src/test/rustdoc/inline_cross/auxiliary/use_crate.rs create mode 100644 src/test/rustdoc/inline_cross/auxiliary/use_crate_2.rs create mode 100644 src/test/rustdoc/inline_cross/use_crate.rs diff --git a/src/doc/rustdoc/src/the-doc-attribute.md b/src/doc/rustdoc/src/the-doc-attribute.md index 296422744fa40..61e5b3d0133ff 100644 --- a/src/doc/rustdoc/src/the-doc-attribute.md +++ b/src/doc/rustdoc/src/the-doc-attribute.md @@ -186,6 +186,9 @@ mod bar { Now we'll have a `Re-exports` line, and `Bar` will not link to anywhere. +One special case: In Rust 2018 and later, if you `pub use` one of your dependencies, `rustdoc` will +not eagerly inline it as a module unless you add `#[doc(inline)}`. + ## `#[doc(hidden)]` Any item annotated with `#[doc(hidden)]` will not appear in the documentation, unless diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index bed3f7f99ae02..4fe6cec301546 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -3491,13 +3491,16 @@ impl Clean> for doctree::Import { // forcefully don't inline if this is not public or if the // #[doc(no_inline)] attribute is present. // Don't inline doc(hidden) imports so they can be stripped at a later stage. - let denied = !self.vis.node.is_pub() || self.attrs.iter().any(|a| { + let mut denied = !self.vis.node.is_pub() || self.attrs.iter().any(|a| { a.name() == "doc" && match a.meta_item_list() { Some(l) => attr::list_contains_name(&l, "no_inline") || attr::list_contains_name(&l, "hidden"), None => false, } }); + // Also check whether imports were asked to be inlined, in case we're trying to re-export a + // crate in Rust 2018+ + let please_inline = self.attrs.lists("doc").has_word("inline"); let path = self.path.clean(cx); let inner = if self.glob { if !denied { @@ -3510,6 +3513,16 @@ impl Clean> for doctree::Import { Import::Glob(resolve_use_source(cx, path)) } else { let name = self.name; + if !please_inline { + match path.def { + Def::Mod(did) => if !did.is_local() && did.index == CRATE_DEF_INDEX { + // if we're `pub use`ing an extern crate root, don't inline it unless we + // were specifically asked for it + denied = true; + } + _ => {} + } + } if !denied { let mut visited = FxHashSet::default(); if let Some(items) = inline::try_inline(cx, path.def, name, &mut visited) { diff --git a/src/test/rustdoc/inline_cross/auxiliary/use_crate.rs b/src/test/rustdoc/inline_cross/auxiliary/use_crate.rs new file mode 100644 index 0000000000000..55202de1981be --- /dev/null +++ b/src/test/rustdoc/inline_cross/auxiliary/use_crate.rs @@ -0,0 +1,15 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub mod asdf { + pub struct SomeStruct; +} + +pub trait SomeTrait {} diff --git a/src/test/rustdoc/inline_cross/auxiliary/use_crate_2.rs b/src/test/rustdoc/inline_cross/auxiliary/use_crate_2.rs new file mode 100644 index 0000000000000..1f11cbc4da718 --- /dev/null +++ b/src/test/rustdoc/inline_cross/auxiliary/use_crate_2.rs @@ -0,0 +1,11 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub struct SomethingElse; diff --git a/src/test/rustdoc/inline_cross/use_crate.rs b/src/test/rustdoc/inline_cross/use_crate.rs new file mode 100644 index 0000000000000..a98704446ee76 --- /dev/null +++ b/src/test/rustdoc/inline_cross/use_crate.rs @@ -0,0 +1,37 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:use_crate.rs +// aux-build:use_crate_2.rs +// build-aux-docs +// edition:2018 +// compile-flags:--extern use_crate --extern use_crate_2 -Z unstable-options + +// During the buildup to Rust 2018, rustdoc would eagerly inline `pub use some_crate;` as if it +// were a module, so we changed it to make `pub use`ing crate roots remain as a `pub use` statement +// in docs... unless you added `#[doc(inline)]`. + +#![crate_name = "local"] + +// @!has-dir local/use_crate +// @has local/index.html +// @has - '//code' 'pub use use_crate' +pub use use_crate; + +// @has-dir local/asdf +// @has local/asdf/index.html +// @has local/index.html '//a/@href' 'asdf/index.html' +pub use use_crate::asdf; + +// @has-dir local/use_crate_2 +// @has local/use_crate_2/index.html +// @has local/index.html '//a/@href' 'use_crate_2/index.html' +#[doc(inline)] +pub use use_crate_2; diff --git a/src/test/rustdoc/src-links-external.rs b/src/test/rustdoc/src-links-external.rs index d3307bb4d42c1..6cc7f1743ad07 100644 --- a/src/test/rustdoc/src-links-external.rs +++ b/src/test/rustdoc/src-links-external.rs @@ -18,6 +18,7 @@ extern crate src_links_external; // @has foo/bar/index.html '//a/@href' '../../src/src_links_external/src-links-external.rs.html#11' +#[doc(inline)] pub use src_links_external as bar; // @has foo/bar/struct.Foo.html '//a/@href' '../../src/src_links_external/src-links-external.rs.html#11' From 1d1213f2a9c0836341c4f8a2aa7611e64707b5f2 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 18 Nov 2018 19:08:06 -0800 Subject: [PATCH 10/31] Increase `Duration` approximate equal threshold to 1us Previously this threshold when testing was 100ns, but the Windows documentation states: > which is a high resolution (<1us) time stamp which presumably means that we could have up to 1us resolution, which means that 100ns doesn't capture "equivalent" time intervals due to various bits of rounding here and there. It's hoped that this.. Closes #56034 --- src/libstd/time.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libstd/time.rs b/src/libstd/time.rs index 90ab349159915..bb795a33746e2 100644 --- a/src/libstd/time.rs +++ b/src/libstd/time.rs @@ -481,7 +481,8 @@ mod tests { let (a, b) = ($a, $b); if a != b { let (a, b) = if a > b {(a, b)} else {(b, a)}; - assert!(a - Duration::new(0, 100) <= b); + assert!(a - Duration::new(0, 1000) <= b, + "{:?} is not almost equal to {:?}", a, b); } }) } From e2a9ee48a6cca74e6ec0b93284849b50437eecfc Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 31 Aug 2018 12:01:26 +1200 Subject: [PATCH 11/31] squashed form of #54145 Give each PathSegment a NodeId Store a resolved def on hir::PathSegment save-analysis: remove hacky, unnecessary code now that we have spans for every ident dump data for prefix path segments dump refs for path segments in save-analysis Requires adding path segments to the hir map Fix tests and rustdoc save-analysis: handle missing field names FIxes https://github.com/rust-lang-nursery/rls/issues/1031 rebasing and reviewer changes Primarily refactoring `(Ident, Option)` to `Segment` Fix tests and assertions; add some comments more reviewer changes --- src/librustc/hir/intravisit.rs | 17 +- src/librustc/hir/lowering.rs | 124 ++++++-- src/librustc/hir/map/collector.rs | 22 +- src/librustc/hir/map/hir_id_validator.rs | 12 +- src/librustc/hir/map/mod.rs | 8 +- src/librustc/hir/mod.rs | 20 +- src/librustc/hir/print.rs | 11 + src/librustc/ich/impls_hir.rs | 2 + src/librustc_resolve/build_reduced_graph.rs | 43 +-- src/librustc_resolve/error_reporting.rs | 39 ++- src/librustc_resolve/lib.rs | 231 +++++++++----- src/librustc_resolve/macros.rs | 30 +- src/librustc_resolve/resolve_imports.rs | 24 +- src/librustc_save_analysis/dump_visitor.rs | 295 +++++------------- src/librustc_save_analysis/lib.rs | 165 ++++------ src/librustc_save_analysis/span_utils.rs | 184 +---------- src/librustdoc/clean/mod.rs | 2 + src/librustdoc/core.rs | 2 + src/libsyntax/ast.rs | 4 +- src/libsyntax/ext/build.rs | 8 +- src/libsyntax/fold.rs | 4 +- src/libsyntax/parse/parser.rs | 2 +- .../incremental/hashes/closure_expressions.rs | 2 +- src/test/mir-opt/end_region_1.rs | 6 +- src/test/mir-opt/end_region_2.rs | 14 +- src/test/mir-opt/end_region_3.rs | 14 +- src/test/mir-opt/end_region_4.rs | 14 +- src/test/mir-opt/end_region_5.rs | 16 +- src/test/mir-opt/end_region_6.rs | 20 +- src/test/mir-opt/end_region_7.rs | 12 +- src/test/mir-opt/end_region_8.rs | 20 +- src/test/mir-opt/end_region_9.rs | 6 +- src/test/mir-opt/end_region_cyclic.rs | 50 +-- .../end_region_destruction_extents_1.rs | 64 ++-- .../mir-opt/inline-closure-borrows-arg.rs | 2 +- src/test/mir-opt/inline-closure.rs | 2 +- src/test/mir-opt/validate_1.rs | 22 +- src/test/mir-opt/validate_3.rs | 18 +- src/test/mir-opt/validate_4.rs | 12 +- src/test/mir-opt/validate_5.rs | 10 +- 40 files changed, 724 insertions(+), 829 deletions(-) diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 95b73d5f87b39..dcc0f8545e5d7 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -298,6 +298,9 @@ pub trait Visitor<'v> : Sized { fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: BodyId, s: Span, id: NodeId) { walk_fn(self, fk, fd, b, s, id) } + fn visit_use(&mut self, path: &'v Path, id: NodeId, hir_id: HirId) { + walk_use(self, path, id, hir_id) + } fn visit_trait_item(&mut self, ti: &'v TraitItem) { walk_trait_item(self, ti) } @@ -471,8 +474,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { } } ItemKind::Use(ref path, _) => { - visitor.visit_id(item.id); - visitor.visit_path(path, item.hir_id); + visitor.visit_use(path, item.id, item.hir_id); } ItemKind::Static(ref typ, _, body) | ItemKind::Const(ref typ, body) => { @@ -554,6 +556,14 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { walk_list!(visitor, visit_attribute, &item.attrs); } +pub fn walk_use<'v, V: Visitor<'v>>(visitor: &mut V, + path: &'v Path, + item_id: NodeId, + hir_id: HirId) { + visitor.visit_id(item_id); + visitor.visit_path(path, hir_id); +} + pub fn walk_enum_def<'v, V: Visitor<'v>>(visitor: &mut V, enum_definition: &'v EnumDef, generics: &'v Generics, @@ -652,6 +662,9 @@ pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V, path_span: Span, segment: &'v PathSegment) { visitor.visit_ident(segment.ident); + if let Some(id) = segment.id { + visitor.visit_id(id); + } if let Some(ref args) = segment.args { visitor.visit_generic_args(path_span, args); } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 99a1cf3c78757..9795c0cba6154 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -143,8 +143,12 @@ pub struct LoweringContext<'a> { } pub trait Resolver { - /// Resolve a hir path generated by the lowerer when expanding `for`, `if let`, etc. - fn resolve_hir_path(&mut self, path: &mut hir::Path, is_value: bool); + /// Resolve a path generated by the lowerer when expanding `for`, `if let`, etc. + fn resolve_hir_path( + &mut self, + path: &ast::Path, + is_value: bool, + ) -> hir::Path; /// Obtain the resolution for a node id fn get_resolution(&mut self, id: NodeId) -> Option; @@ -163,7 +167,6 @@ pub trait Resolver { span: Span, crate_root: Option<&str>, components: &[&str], - params: Option>, is_value: bool, ) -> hir::Path; } @@ -1064,6 +1067,9 @@ impl<'a> LoweringContext<'a> { } fn lower_attr(&mut self, attr: &Attribute) -> Attribute { + // Note that we explicitly do not walk the path. Since we don't really + // lower attributes (we use the AST version) there is nowhere to keep + // the HirIds. We don't actually need HIR version of attributes anyway. Attribute { id: attr.id, style: attr.style, @@ -1677,6 +1683,7 @@ impl<'a> LoweringContext<'a> { num_lifetimes, parenthesized_generic_args, itctx.reborrow(), + None, ) }) .collect(), @@ -1720,6 +1727,7 @@ impl<'a> LoweringContext<'a> { 0, ParenthesizedGenericArgs::Warn, itctx.reborrow(), + None, )); let qpath = hir::QPath::TypeRelative(ty, segment); @@ -1748,6 +1756,7 @@ impl<'a> LoweringContext<'a> { p: &Path, ident: Option, param_mode: ParamMode, + explicit_owner: Option, ) -> hir::Path { hir::Path { def, @@ -1761,6 +1770,7 @@ impl<'a> LoweringContext<'a> { 0, ParenthesizedGenericArgs::Err, ImplTraitContext::disallowed(), + explicit_owner, ) }) .chain(ident.map(|ident| hir::PathSegment::from_ident(ident))) @@ -1771,7 +1781,7 @@ impl<'a> LoweringContext<'a> { fn lower_path(&mut self, id: NodeId, p: &Path, param_mode: ParamMode) -> hir::Path { let def = self.expect_full_def(id); - self.lower_path_extra(def, p, None, param_mode) + self.lower_path_extra(def, p, None, param_mode, None) } fn lower_path_segment( @@ -1782,6 +1792,7 @@ impl<'a> LoweringContext<'a> { expected_lifetimes: usize, parenthesized_generic_args: ParenthesizedGenericArgs, itctx: ImplTraitContext<'_>, + explicit_owner: Option, ) -> hir::PathSegment { let (mut generic_args, infer_types) = if let Some(ref generic_args) = segment.args { let msg = "parenthesized parameters may only be used with a trait"; @@ -1852,8 +1863,17 @@ impl<'a> LoweringContext<'a> { } } + let def = self.expect_full_def(segment.id); + let id = if let Some(owner) = explicit_owner { + self.lower_node_id_with_owner(segment.id, owner) + } else { + self.lower_node_id(segment.id) + }; + hir::PathSegment::new( segment.ident, + Some(id.node_id), + Some(def), generic_args, infer_types, ) @@ -2936,6 +2956,12 @@ impl<'a> LoweringContext<'a> { attrs: &hir::HirVec, ) -> hir::ItemKind { let path = &tree.prefix; + let segments = prefix + .segments + .iter() + .chain(path.segments.iter()) + .cloned() + .collect(); match tree.kind { UseTreeKind::Simple(rename, id1, id2) => { @@ -2943,12 +2969,7 @@ impl<'a> LoweringContext<'a> { // First apply the prefix to the path let mut path = Path { - segments: prefix - .segments - .iter() - .chain(path.segments.iter()) - .cloned() - .collect(), + segments, span: path.span, }; @@ -2968,9 +2989,18 @@ impl<'a> LoweringContext<'a> { // for later let ret_def = defs.next().unwrap_or(Def::Err); + // Here, we are looping over namespaces, if they exist for the definition + // being imported. We only handle type and value namespaces because we + // won't be dealing with macros in the rest of the compiler. + // Essentially a single `use` which imports two names is desugared into + // two imports. for (def, &new_node_id) in defs.zip([id1, id2].iter()) { let vis = vis.clone(); let name = name.clone(); + let mut path = path.clone(); + for seg in &mut path.segments { + seg.id = self.sess.next_node_id(); + } let span = path.span; self.resolver.definitions().create_def_with_parent( parent_def_index, @@ -2983,7 +3013,8 @@ impl<'a> LoweringContext<'a> { self.with_hir_id_owner(new_node_id, |this| { let new_id = this.lower_node_id(new_node_id); - let path = this.lower_path_extra(def, &path, None, ParamMode::Explicit); + let path = + this.lower_path_extra(def, &path, None, ParamMode::Explicit, None); let item = hir::ItemKind::Use(P(path), hir::UseKind::Single); let vis_kind = match vis.node { hir::VisibilityKind::Public => hir::VisibilityKind::Public, @@ -2993,7 +3024,6 @@ impl<'a> LoweringContext<'a> { let id = this.next_id(); hir::VisibilityKind::Restricted { path: path.clone(), - // We are allocating a new NodeId here id: id.node_id, hir_id: id.hir_id, } @@ -3016,19 +3046,15 @@ impl<'a> LoweringContext<'a> { }); } - let path = P(self.lower_path_extra(ret_def, &path, None, ParamMode::Explicit)); + let path = + P(self.lower_path_extra(ret_def, &path, None, ParamMode::Explicit, None)); hir::ItemKind::Use(path, hir::UseKind::Single) } UseTreeKind::Glob => { let path = P(self.lower_path( id, &Path { - segments: prefix - .segments - .iter() - .chain(path.segments.iter()) - .cloned() - .collect(), + segments, span: path.span, }, ParamMode::Explicit, @@ -3036,19 +3062,17 @@ impl<'a> LoweringContext<'a> { hir::ItemKind::Use(path, hir::UseKind::Glob) } UseTreeKind::Nested(ref trees) => { + // Nested imports are desugared into simple imports. + let prefix = Path { - segments: prefix - .segments - .iter() - .chain(path.segments.iter()) - .cloned() - .collect(), + segments, span: prefix.span.to(path.span), }; - // Add all the nested PathListItems in the HIR + // Add all the nested PathListItems to the HIR. for &(ref use_tree, id) in trees { self.allocate_hir_id_counter(id, &use_tree); + let LoweredNodeId { node_id: new_id, hir_id: new_hir_id, @@ -3056,10 +3080,26 @@ impl<'a> LoweringContext<'a> { let mut vis = vis.clone(); let mut name = name.clone(); - let item = - self.lower_use_tree(use_tree, &prefix, new_id, &mut vis, &mut name, &attrs); + let mut prefix = prefix.clone(); + // Give the segments new ids since they are being cloned. + for seg in &mut prefix.segments { + seg.id = self.sess.next_node_id(); + } + + // Each `use` import is an item and thus are owners of the + // names in the path. Up to this point the nested import is + // the current owner, since we want each desugared import to + // own its own names, we have to adjust the owner before + // lowering the rest of the import. self.with_hir_id_owner(new_id, |this| { + let item = this.lower_use_tree(use_tree, + &prefix, + new_id, + &mut vis, + &mut name, + attrs); + let vis_kind = match vis.node { hir::VisibilityKind::Public => hir::VisibilityKind::Public, hir::VisibilityKind::Crate(sugar) => hir::VisibilityKind::Crate(sugar), @@ -3068,7 +3108,6 @@ impl<'a> LoweringContext<'a> { let id = this.next_id(); hir::VisibilityKind::Restricted { path: path.clone(), - // We are allocating a new NodeId here id: id.node_id, hir_id: id.hir_id, } @@ -3081,7 +3120,7 @@ impl<'a> LoweringContext<'a> { hir::Item { id: new_id, hir_id: new_hir_id, - name: name, + name, attrs: attrs.clone(), node: item, vis, @@ -3095,7 +3134,7 @@ impl<'a> LoweringContext<'a> { // the stability of `use a::{};`, to avoid it showing up as // a re-export by accident when `pub`, e.g. in documentation. let def = self.expect_full_def_from_use(id).next().unwrap_or(Def::Err); - let path = P(self.lower_path_extra(def, &prefix, None, ParamMode::Explicit)); + let path = P(self.lower_path_extra(def, &prefix, None, ParamMode::Explicit, None)); *vis = respan(prefix.span.shrink_to_lo(), hir::VisibilityKind::Inherited); hir::ItemKind::Use(path, hir::UseKind::ListStem) } @@ -3646,6 +3685,7 @@ impl<'a> LoweringContext<'a> { 0, ParenthesizedGenericArgs::Err, ImplTraitContext::disallowed(), + None, ); let args = args.iter().map(|x| self.lower_expr(x)).collect(); hir::ExprKind::MethodCall(hir_seg, seg.ident.span, args) @@ -4499,8 +4539,15 @@ impl<'a> LoweringContext<'a> { } else { self.lower_node_id(id) }; + let def = self.expect_full_def(id); hir::VisibilityKind::Restricted { - path: P(self.lower_path(id, path, ParamMode::Explicit)), + path: P(self.lower_path_extra( + def, + path, + None, + ParamMode::Explicit, + explicit_owner, + )), id: lowered_id.node_id, hir_id: lowered_id.hir_id, } @@ -4807,8 +4854,17 @@ impl<'a> LoweringContext<'a> { params: Option>, is_value: bool ) -> hir::Path { - self.resolver - .resolve_str_path(span, self.crate_root, components, params, is_value) + let mut path = self.resolver + .resolve_str_path(span, self.crate_root, components, is_value); + path.segments.last_mut().unwrap().args = params; + + + for seg in path.segments.iter_mut() { + if let Some(id) = seg.id { + seg.id = Some(self.lower_node_id(id).node_id); + } + } + path } fn ty_path(&mut self, id: LoweredNodeId, span: Span, qpath: hir::QPath) -> hir::Ty { diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index bd12a5e0cb4d8..8c701d9e4188f 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -210,17 +210,22 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { None => format!("{:?}", node) }; - if hir_id == ::hir::DUMMY_HIR_ID { - debug!("Maybe you forgot to lower the node id {:?}?", id); - } + let forgot_str = if hir_id == ::hir::DUMMY_HIR_ID { + format!("\nMaybe you forgot to lower the node id {:?}?", id) + } else { + String::new() + }; bug!("inconsistent DepNode for `{}`: \ - current_dep_node_owner={}, hir_id.owner={}", + current_dep_node_owner={} ({:?}), hir_id.owner={} ({:?}) {}", node_str, self.definitions .def_path(self.current_dep_node_owner) .to_string_no_crate(), - self.definitions.def_path(hir_id.owner).to_string_no_crate()) + self.current_dep_node_owner, + self.definitions.def_path(hir_id.owner).to_string_no_crate(), + hir_id.owner, + forgot_str) } } @@ -392,6 +397,13 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { }); } + fn visit_path_segment(&mut self, path_span: Span, path_segment: &'hir PathSegment) { + if let Some(id) = path_segment.id { + self.insert(id, Node::PathSegment(path_segment)); + } + intravisit::walk_path_segment(self, path_span, path_segment); + } + fn visit_ty(&mut self, ty: &'hir Ty) { self.insert(ty.id, Node::Ty(ty)); diff --git a/src/librustc/hir/map/hir_id_validator.rs b/src/librustc/hir/map/hir_id_validator.rs index 087efbd4a22dd..896a6163eba64 100644 --- a/src/librustc/hir/map/hir_id_validator.rs +++ b/src/librustc/hir/map/hir_id_validator.rs @@ -88,7 +88,7 @@ impl<'a, 'hir: 'a> HirIdValidator<'a, 'hir> { walk(self); if owner_def_index == CRATE_DEF_INDEX { - return + return; } // There's always at least one entry for the owning item itself @@ -129,13 +129,16 @@ impl<'a, 'hir: 'a> HirIdValidator<'a, 'hir> { local_id, self.hir_map.node_to_string(node_id))); } - self.errors.push(format!( "ItemLocalIds not assigned densely in {}. \ - Max ItemLocalId = {}, missing IDs = {:?}", + Max ItemLocalId = {}, missing IDs = {:?}; seens IDs = {:?}", self.hir_map.def_path(DefId::local(owner_def_index)).to_string_no_crate(), max, - missing_items)); + missing_items, + self.hir_ids_seen + .values() + .map(|n| format!("({:?} {})", n, self.hir_map.node_to_string(*n))) + .collect::>())); } } } @@ -155,6 +158,7 @@ impl<'a, 'hir: 'a> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> { self.errors.push(format!("HirIdValidator: No HirId assigned for NodeId {}: {:?}", node_id, self.hir_map.node_to_string(node_id))); + return; } if owner != stable_id.owner { diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index f5f9bcd3b5ea5..7a20146130d94 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -204,7 +204,7 @@ impl<'hir> Map<'hir> { if let Some(entry) = self.map[id.as_usize()] { self.dep_graph.read_index(entry.dep_node); } else { - bug!("called `HirMap::read()` with invalid `NodeId`") + bug!("called `HirMap::read()` with invalid `NodeId`: {:?}", id) } } @@ -344,6 +344,7 @@ impl<'hir> Map<'hir> { Node::AnonConst(_) | Node::Expr(_) | Node::Stmt(_) | + Node::PathSegment(_) | Node::Ty(_) | Node::TraitRef(_) | Node::Pat(_) | @@ -884,6 +885,7 @@ impl<'hir> Map<'hir> { Some(Node::AnonConst(constant)) => self.body(constant.body).value.span, Some(Node::Expr(expr)) => expr.span, Some(Node::Stmt(stmt)) => stmt.span, + Some(Node::PathSegment(seg)) => seg.ident.span, Some(Node::Ty(ty)) => ty.span, Some(Node::TraitRef(tr)) => tr.path.span, Some(Node::Binding(pat)) => pat.span, @@ -1098,6 +1100,7 @@ impl<'a> print::State<'a> { Node::AnonConst(a) => self.print_anon_const(&a), Node::Expr(a) => self.print_expr(&a), Node::Stmt(a) => self.print_stmt(&a), + Node::PathSegment(a) => self.print_path_segment(&a), Node::Ty(a) => self.print_type(&a), Node::TraitRef(a) => self.print_trait_ref(&a), Node::Binding(a) | @@ -1215,6 +1218,9 @@ fn node_id_to_string(map: &Map<'_>, id: NodeId, include_id: bool) -> String { Some(Node::Stmt(_)) => { format!("stmt {}{}", map.node_to_pretty_string(id), id_str) } + Some(Node::PathSegment(_)) => { + format!("path segment {}{}", map.node_to_pretty_string(id), id_str) + } Some(Node::Ty(_)) => { format!("type {}{}", map.node_to_pretty_string(id), id_str) } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index d5de6197a2e48..a2095ff40c040 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -347,6 +347,13 @@ impl fmt::Display for Path { pub struct PathSegment { /// The identifier portion of this path segment. pub ident: Ident, + // `id` and `def` are optional. We currently only use these in save-analysis, + // any path segments without these will not have save-analysis info and + // therefore will not have 'jump to def' in IDEs, but otherwise will not be + // affected. (In general, we don't bother to get the defs for synthesized + // segments, only for segments which have come from the AST). + pub id: Option, + pub def: Option, /// Type/lifetime parameters attached to this path. They come in /// two flavors: `Path` and `Path(A,B) -> C`. Note that @@ -367,14 +374,24 @@ impl PathSegment { pub fn from_ident(ident: Ident) -> PathSegment { PathSegment { ident, + id: None, + def: None, infer_types: true, args: None, } } - pub fn new(ident: Ident, args: GenericArgs, infer_types: bool) -> Self { + pub fn new( + ident: Ident, + id: Option, + def: Option, + args: GenericArgs, + infer_types: bool, + ) -> Self { PathSegment { ident, + id, + def, infer_types, args: if args.is_empty() { None @@ -2511,6 +2528,7 @@ pub enum Node<'hir> { AnonConst(&'hir AnonConst), Expr(&'hir Expr), Stmt(&'hir Stmt), + PathSegment(&'hir PathSegment), Ty(&'hir Ty), TraitRef(&'hir TraitRef), Binding(&'hir Pat), diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index ad2fa48610b0e..e69d32ad1deaf 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -1633,6 +1633,17 @@ impl<'a> State<'a> { Ok(()) } + pub fn print_path_segment(&mut self, segment: &hir::PathSegment) -> io::Result<()> { + if segment.ident.name != keywords::CrateRoot.name() && + segment.ident.name != keywords::DollarCrate.name() { + self.print_ident(segment.ident)?; + segment.with_generic_args(|generic_args| { + self.print_generic_args(generic_args, segment.infer_types, false) + })?; + } + Ok(()) + } + pub fn print_qpath(&mut self, qpath: &hir::QPath, colons_before_params: bool) diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index a48bd4eeb09a3..b220634d0d903 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -174,6 +174,8 @@ impl_stable_hash_for!(struct hir::Path { impl_stable_hash_for!(struct hir::PathSegment { ident -> (ident.name), + id, + def, infer_types, args }); diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 023a7477cee1b..b3a70c79df144 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -16,7 +16,7 @@ use macros::{InvocationData, ParentScope, LegacyScope}; use resolve_imports::ImportDirective; use resolve_imports::ImportDirectiveSubclass::{self, GlobImport, SingleImport}; -use {Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, ToNameBinding}; +use {Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, Segment, ToNameBinding}; use {ModuleOrUniformRoot, PerNS, Resolver, ResolverArenas, ExternPreludeEntry}; use Namespace::{self, TypeNS, ValueNS, MacroNS}; use {resolve_error, resolve_struct_error, ResolutionError}; @@ -114,7 +114,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { // This particular use tree use_tree: &ast::UseTree, id: NodeId, - parent_prefix: &[Ident], + parent_prefix: &[Segment], nested: bool, // The whole `use` item parent_scope: ParentScope<'a>, @@ -126,7 +126,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { parent_prefix, use_tree, nested); let mut prefix_iter = parent_prefix.iter().cloned() - .chain(use_tree.prefix.segments.iter().map(|seg| seg.ident)).peekable(); + .chain(use_tree.prefix.segments.iter().map(|seg| seg.into())).peekable(); // On 2015 edition imports are resolved as crate-relative by default, // so prefixes are prepended with crate root segment if necessary. @@ -134,8 +134,12 @@ impl<'a, 'cl> Resolver<'a, 'cl> { // appears, so imports in braced groups can have roots prepended independently. let is_glob = if let ast::UseTreeKind::Glob = use_tree.kind { true } else { false }; let crate_root = if !self.session.rust_2018() && - prefix_iter.peek().map_or(is_glob, |ident| !ident.is_path_segment_keyword()) { - Some(Ident::new(keywords::CrateRoot.name(), use_tree.prefix.span.shrink_to_lo())) + prefix_iter.peek().map_or(is_glob, |seg| !seg.ident.is_path_segment_keyword()) + { + Some(Segment::from_ident(Ident::new( + keywords::CrateRoot.name(), + use_tree.prefix.span.shrink_to_lo(), + ))) } else { None }; @@ -143,9 +147,9 @@ impl<'a, 'cl> Resolver<'a, 'cl> { let prefix = crate_root.into_iter().chain(prefix_iter).collect::>(); debug!("build_reduced_graph_for_use_tree: prefix={:?}", prefix); - let empty_for_self = |prefix: &[Ident]| { + let empty_for_self = |prefix: &[Segment]| { prefix.is_empty() || - prefix.len() == 1 && prefix[0].name == keywords::CrateRoot.name() + prefix.len() == 1 && prefix[0].ident.name == keywords::CrateRoot.name() }; match use_tree.kind { ast::UseTreeKind::Simple(rename, ..) => { @@ -156,7 +160,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { if nested { // Correctly handle `self` - if source.name == keywords::SelfValue.name() { + if source.ident.name == keywords::SelfValue.name() { type_ns_only = true; if empty_for_self(&module_path) { @@ -172,20 +176,20 @@ impl<'a, 'cl> Resolver<'a, 'cl> { // Replace `use foo::self;` with `use foo;` source = module_path.pop().unwrap(); if rename.is_none() { - ident = source; + ident = source.ident; } } } else { // Disallow `self` - if source.name == keywords::SelfValue.name() { + if source.ident.name == keywords::SelfValue.name() { resolve_error(self, use_tree.span, ResolutionError::SelfImportsOnlyAllowedWithin); } // Disallow `use $crate;` - if source.name == keywords::DollarCrate.name() && module_path.is_empty() { - let crate_root = self.resolve_crate_root(source); + if source.ident.name == keywords::DollarCrate.name() && module_path.is_empty() { + let crate_root = self.resolve_crate_root(source.ident); let crate_name = match crate_root.kind { ModuleKind::Def(_, name) => name, ModuleKind::Block(..) => unreachable!(), @@ -195,11 +199,14 @@ impl<'a, 'cl> Resolver<'a, 'cl> { // while the current crate doesn't have a valid `crate_name`. if crate_name != keywords::Invalid.name() { // `crate_name` should not be interpreted as relative. - module_path.push(Ident { - name: keywords::CrateRoot.name(), - span: source.span, + module_path.push(Segment { + ident: Ident { + name: keywords::CrateRoot.name(), + span: source.ident.span, + }, + id: Some(self.session.next_node_id()), }); - source.name = crate_name; + source.ident.name = crate_name; } if rename.is_none() { ident.name = crate_name; @@ -220,7 +227,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { let subclass = SingleImport { target: ident, - source, + source: source.ident, result: PerNS { type_ns: Cell::new(Err(Undetermined)), value_ns: Cell::new(Err(Undetermined)), @@ -291,7 +298,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { // `a::b::c::{self as _}`, so that their prefixes are correctly // resolved and checked for privacy/stability/etc. if items.is_empty() && !empty_for_self(&prefix) { - let new_span = prefix[prefix.len() - 1].span; + let new_span = prefix[prefix.len() - 1].ident.span; let tree = ast::UseTree { prefix: ast::Path::from_ident( Ident::new(keywords::SelfValue.name(), new_span) diff --git a/src/librustc_resolve/error_reporting.rs b/src/librustc_resolve/error_reporting.rs index 728023908678d..263d23d133e1c 100644 --- a/src/librustc_resolve/error_reporting.rs +++ b/src/librustc_resolve/error_reporting.rs @@ -8,10 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use {CrateLint, PathResult}; +use {CrateLint, PathResult, Segment}; use macros::ParentScope; -use syntax::ast::Ident; use syntax::symbol::keywords; use syntax_pos::Span; @@ -23,20 +22,20 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { pub(crate) fn make_path_suggestion( &mut self, span: Span, - mut path: Vec, + mut path: Vec, parent_scope: &ParentScope<'b>, - ) -> Option<(Vec, Option)> { + ) -> Option<(Vec, Option)> { debug!("make_path_suggestion: span={:?} path={:?}", span, path); match (path.get(0), path.get(1)) { // `{{root}}::ident::...` on both editions. // On 2015 `{{root}}` is usually added implicitly. - (Some(fst), Some(snd)) if fst.name == keywords::CrateRoot.name() && - !snd.is_path_segment_keyword() => {} + (Some(fst), Some(snd)) if fst.ident.name == keywords::CrateRoot.name() && + !snd.ident.is_path_segment_keyword() => {} // `ident::...` on 2018 - (Some(fst), _) if self.session.rust_2018() && !fst.is_path_segment_keyword() => { + (Some(fst), _) if self.session.rust_2018() && !fst.ident.is_path_segment_keyword() => { // Insert a placeholder that's later replaced by `self`/`super`/etc. - path.insert(0, keywords::Invalid.ident()); + path.insert(0, Segment::from_ident(keywords::Invalid.ident())); } _ => return None, } @@ -57,11 +56,11 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { fn make_missing_self_suggestion( &mut self, span: Span, - mut path: Vec, + mut path: Vec, parent_scope: &ParentScope<'b>, - ) -> Option<(Vec, Option)> { + ) -> Option<(Vec, Option)> { // Replace first ident with `self` and check if that is valid. - path[0].name = keywords::SelfValue.name(); + path[0].ident.name = keywords::SelfValue.name(); let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No); debug!("make_missing_self_suggestion: path={:?} result={:?}", path, result); if let PathResult::Module(..) = result { @@ -81,11 +80,11 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { fn make_missing_crate_suggestion( &mut self, span: Span, - mut path: Vec, + mut path: Vec, parent_scope: &ParentScope<'b>, - ) -> Option<(Vec, Option)> { + ) -> Option<(Vec, Option)> { // Replace first ident with `crate` and check if that is valid. - path[0].name = keywords::Crate.name(); + path[0].ident.name = keywords::Crate.name(); let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No); debug!("make_missing_crate_suggestion: path={:?} result={:?}", path, result); if let PathResult::Module(..) = result { @@ -112,11 +111,11 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { fn make_missing_super_suggestion( &mut self, span: Span, - mut path: Vec, + mut path: Vec, parent_scope: &ParentScope<'b>, - ) -> Option<(Vec, Option)> { + ) -> Option<(Vec, Option)> { // Replace first ident with `crate` and check if that is valid. - path[0].name = keywords::Super.name(); + path[0].ident.name = keywords::Super.name(); let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No); debug!("make_missing_super_suggestion: path={:?} result={:?}", path, result); if let PathResult::Module(..) = result { @@ -139,9 +138,9 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { fn make_external_crate_suggestion( &mut self, span: Span, - mut path: Vec, + mut path: Vec, parent_scope: &ParentScope<'b>, - ) -> Option<(Vec, Option)> { + ) -> Option<(Vec, Option)> { if !self.session.rust_2018() { return None; } @@ -155,7 +154,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { for name in extern_crate_names.into_iter() { // Replace first ident with a crate name and check if that is valid. - path[0].name = name; + path[0].ident.name = name; let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No); debug!("make_external_crate_suggestion: name={:?} path={:?} result={:?}", name, path, result); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 0387b53bff968..f8e3a479611d2 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -629,6 +629,43 @@ impl<'a> PathSource<'a> { } } +// A minimal representation of a path segment. We use this in resolve because +// we synthesize 'path segments' which don't have the rest of an AST or HIR +// PathSegment. +#[derive(Clone, Copy, Debug)] +pub struct Segment { + ident: Ident, + id: Option, +} + +impl Segment { + fn from_path(path: &Path) -> Vec { + path.segments.iter().map(|s| s.into()).collect() + } + + fn from_ident(ident: Ident) -> Segment { + Segment { + ident, + id: None, + } + } + + fn names_to_string(segments: &[Segment]) -> String { + names_to_string(&segments.iter() + .map(|seg| seg.ident) + .collect::>()) + } +} + +impl<'a> From<&'a ast::PathSegment> for Segment { + fn from(seg: &'a ast::PathSegment) -> Segment { + Segment { + ident: seg.ident, + id: Some(seg.id), + } + } +} + struct UsePlacementFinder { target_module: NodeId, span: Option, @@ -1033,7 +1070,7 @@ pub struct ModuleData<'a> { resolutions: RefCell>>>, single_segment_macro_resolutions: RefCell, Option<&'a NameBinding<'a>>)>>, - multi_segment_macro_resolutions: RefCell, Span, MacroKind, ParentScope<'a>, + multi_segment_macro_resolutions: RefCell, Span, MacroKind, ParentScope<'a>, Option)>>, builtin_attrs: RefCell)>>, @@ -1613,7 +1650,11 @@ impl<'a, 'b: 'a, 'cl: 'b> ty::DefIdTree for &'a Resolver<'b, 'cl> { /// This interface is used through the AST→HIR step, to embed full paths into the HIR. After that /// the resolver is no longer needed as all the relevant information is inline. impl<'a, 'cl> hir::lowering::Resolver for Resolver<'a, 'cl> { - fn resolve_hir_path(&mut self, path: &mut hir::Path, is_value: bool) { + fn resolve_hir_path( + &mut self, + path: &ast::Path, + is_value: bool, + ) -> hir::Path { self.resolve_hir_path_cb(path, is_value, |resolver, span, error| resolve_error(resolver, span, error)) } @@ -1623,33 +1664,22 @@ impl<'a, 'cl> hir::lowering::Resolver for Resolver<'a, 'cl> { span: Span, crate_root: Option<&str>, components: &[&str], - args: Option>, is_value: bool ) -> hir::Path { - let mut segments = iter::once(keywords::CrateRoot.ident()) + let segments = iter::once(keywords::CrateRoot.ident()) .chain( crate_root.into_iter() .chain(components.iter().cloned()) .map(Ident::from_str) - ).map(hir::PathSegment::from_ident).collect::>(); + ).map(|i| self.new_ast_path_segment(i)).collect::>(); - if let Some(args) = args { - let ident = segments.last().unwrap().ident; - *segments.last_mut().unwrap() = hir::PathSegment { - ident, - args: Some(args), - infer_types: true, - }; - } - let mut path = hir::Path { + let path = ast::Path { span, - def: Def::Err, - segments: segments.into(), + segments, }; - self.resolve_hir_path(&mut path, is_value); - path + self.resolve_hir_path(&path, is_value) } fn get_resolution(&mut self, id: NodeId) -> Option { @@ -1675,23 +1705,27 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> { use std::iter; let mut errored = false; - let mut path = if path_str.starts_with("::") { - hir::Path { + let path = if path_str.starts_with("::") { + ast::Path { span, - def: Def::Err, - segments: iter::once(keywords::CrateRoot.ident()).chain({ - path_str.split("::").skip(1).map(Ident::from_str) - }).map(hir::PathSegment::from_ident).collect(), + segments: iter::once(keywords::CrateRoot.ident()) + .chain({ + path_str.split("::").skip(1).map(Ident::from_str) + }) + .map(|i| self.new_ast_path_segment(i)) + .collect(), } } else { - hir::Path { + ast::Path { span, - def: Def::Err, - segments: path_str.split("::").map(Ident::from_str) - .map(hir::PathSegment::from_ident).collect(), + segments: path_str + .split("::") + .map(Ident::from_str) + .map(|i| self.new_ast_path_segment(i)) + .collect(), } }; - self.resolve_hir_path_cb(&mut path, is_value, |_, _, _| errored = true); + let path = self.resolve_hir_path_cb(&path, is_value, |_, _, _| errored = true); if errored || path.def == Def::Err { Err(()) } else { @@ -1700,30 +1734,60 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> { } /// resolve_hir_path, but takes a callback in case there was an error - fn resolve_hir_path_cb(&mut self, path: &mut hir::Path, is_value: bool, error_callback: F) + fn resolve_hir_path_cb( + &mut self, + path: &ast::Path, + is_value: bool, + error_callback: F, + ) -> hir::Path where F: for<'c, 'b> FnOnce(&'c mut Resolver, Span, ResolutionError<'b>) { let namespace = if is_value { ValueNS } else { TypeNS }; - let hir::Path { ref segments, span, ref mut def } = *path; - let path: Vec<_> = segments.iter().map(|seg| seg.ident).collect(); + let span = path.span; + let segments = &path.segments; + let path = Segment::from_path(&path); // FIXME (Manishearth): Intra doc links won't get warned of epoch changes - match self.resolve_path_without_parent_scope(&path, Some(namespace), true, span, - CrateLint::No) { + let def = match self.resolve_path_without_parent_scope( + &path, + Some(namespace), + true, + span, + CrateLint::No, + ) { PathResult::Module(ModuleOrUniformRoot::Module(module)) => - *def = module.def().unwrap(), + module.def().unwrap(), PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => - *def = path_res.base_def(), + path_res.base_def(), PathResult::NonModule(..) => { let msg = "type-relative paths are not supported in this context"; error_callback(self, span, ResolutionError::FailedToResolve(msg)); + Def::Err } PathResult::Module(ModuleOrUniformRoot::UniformRoot(_)) | PathResult::Indeterminate => unreachable!(), PathResult::Failed(span, msg, _) => { error_callback(self, span, ResolutionError::FailedToResolve(&msg)); + Def::Err } + }; + + let segments: Vec<_> = segments.iter().map(|seg| { + let mut hir_seg = hir::PathSegment::from_ident(seg.ident); + hir_seg.def = Some(self.def_map.get(&seg.id).map_or(Def::Err, |p| p.base_def())); + hir_seg + }).collect(); + hir::Path { + span, + def, + segments: segments.into(), } } + + fn new_ast_path_segment(&self, ident: Ident) -> ast::PathSegment { + let mut seg = ast::PathSegment::from_ident(ident); + seg.id = self.session.next_node_id(); + seg + } } impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { @@ -2531,9 +2595,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { let mut new_val = None; let mut new_id = None; if let Some(trait_ref) = opt_trait_ref { - let path: Vec<_> = trait_ref.path.segments.iter() - .map(|seg| seg.ident) - .collect(); + let path: Vec<_> = Segment::from_path(&trait_ref.path); let def = self.smart_resolve_path_fragment( trait_ref.ref_id, None, @@ -3029,21 +3091,25 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { source: PathSource, crate_lint: CrateLint ) -> PathResolution { - let segments = &path.segments.iter() - .map(|seg| seg.ident) - .collect::>(); - self.smart_resolve_path_fragment(id, qself, segments, path.span, source, crate_lint) + self.smart_resolve_path_fragment( + id, + qself, + &Segment::from_path(path), + path.span, + source, + crate_lint, + ) } fn smart_resolve_path_fragment(&mut self, id: NodeId, qself: Option<&QSelf>, - path: &[Ident], + path: &[Segment], span: Span, source: PathSource, crate_lint: CrateLint) -> PathResolution { - let ident_span = path.last().map_or(span, |ident| ident.span); + let ident_span = path.last().map_or(span, |ident| ident.ident.span); let ns = source.namespace(); let is_expected = &|def| source.is_expected(def); let is_enum_variant = &|def| if let Def::Variant(..) = def { true } else { false }; @@ -3052,18 +3118,18 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { let report_errors = |this: &mut Self, def: Option| { // Make the base error. let expected = source.descr_expected(); - let path_str = names_to_string(path); - let item_str = path.last().unwrap(); + let path_str = Segment::names_to_string(path); + let item_str = path.last().unwrap().ident; let code = source.error_code(def.is_some()); let (base_msg, fallback_label, base_span) = if let Some(def) = def { (format!("expected {}, found {} `{}`", expected, def.kind_name(), path_str), format!("not a {}", expected), span) } else { - let item_span = path.last().unwrap().span; + let item_span = path.last().unwrap().ident.span; let (mod_prefix, mod_str) = if path.len() == 1 { (String::new(), "this scope".to_string()) - } else if path.len() == 2 && path[0].name == keywords::CrateRoot.name() { + } else if path.len() == 2 && path[0].ident.name == keywords::CrateRoot.name() { (String::new(), "the crate root".to_string()) } else { let mod_path = &path[..path.len() - 1]; @@ -3074,7 +3140,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { module.def(), _ => None, }.map_or(String::new(), |def| format!("{} ", def.kind_name())); - (mod_prefix, format!("`{}`", names_to_string(mod_path))) + (mod_prefix, format!("`{}`", Segment::names_to_string(mod_path))) }; (format!("cannot find {} `{}` in {}{}", expected, item_str, mod_prefix, mod_str), format!("not found in {}", mod_str), @@ -3085,7 +3151,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { // Emit help message for fake-self from other languages like `this`(javascript) if ["this", "my"].contains(&&*item_str.as_str()) - && this.self_value_is_available(path[0].span, span) { + && this.self_value_is_available(path[0].ident.span, span) { err.span_suggestion_with_applicability( span, "did you mean", @@ -3120,7 +3186,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { } // Try to lookup the name in more relaxed fashion for better error reporting. - let ident = *path.last().unwrap(); + let ident = path.last().unwrap().ident; let candidates = this.lookup_import_candidates(ident.name, ns, is_expected); if candidates.is_empty() && is_expected(Def::Enum(DefId::local(CRATE_DEF_INDEX))) { let enum_candidates = @@ -3147,7 +3213,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { } if path.len() == 1 && this.self_type_is_available(span) { if let Some(candidate) = this.lookup_assoc_candidate(ident, ns, is_expected) { - let self_is_available = this.self_value_is_available(path[0].span, span); + let self_is_available = this.self_value_is_available(path[0].ident.span, span); match candidate { AssocSuggestion::Field => { err.span_suggestion_with_applicability( @@ -3382,7 +3448,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { // or `::A::B`. If `B` should be resolved in value namespace then // it needs to be added to the trait map. if ns == ValueNS { - let item_name = *path.last().unwrap(); + let item_name = path.last().unwrap().ident; let traits = self.get_traits_containing_item(item_name, ns); self.trait_map.insert(id, traits); } @@ -3452,7 +3518,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { fn resolve_qpath_anywhere(&mut self, id: NodeId, qself: Option<&QSelf>, - path: &[Ident], + path: &[Segment], primary_ns: Namespace, span: Span, defer_to_typeck: bool, @@ -3474,10 +3540,10 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { } } if primary_ns != MacroNS && - (self.macro_names.contains(&path[0].modern()) || - self.builtin_macros.get(&path[0].name).cloned() + (self.macro_names.contains(&path[0].ident.modern()) || + self.builtin_macros.get(&path[0].ident.name).cloned() .and_then(NameBinding::macro_kind) == Some(MacroKind::Bang) || - self.macro_use_prelude.get(&path[0].name).cloned() + self.macro_use_prelude.get(&path[0].ident.name).cloned() .and_then(NameBinding::macro_kind) == Some(MacroKind::Bang)) { // Return some dummy definition, it's enough for error reporting. return Some( @@ -3491,7 +3557,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { fn resolve_qpath(&mut self, id: NodeId, qself: Option<&QSelf>, - path: &[Ident], + path: &[Segment], ns: Namespace, span: Span, global_by_default: bool, @@ -3580,8 +3646,8 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { PathResult::Failed(..) if (ns == TypeNS || path.len() > 1) && self.primitive_type_table.primitive_types - .contains_key(&path[0].name) => { - let prim = self.primitive_type_table.primitive_types[&path[0].name]; + .contains_key(&path[0].ident.name) => { + let prim = self.primitive_type_table.primitive_types[&path[0].ident.name]; PathResolution::with_unresolved_segments(Def::PrimTy(prim), path.len() - 1) } PathResult::Module(ModuleOrUniformRoot::Module(module)) => @@ -3596,8 +3662,8 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { }; if path.len() > 1 && !global_by_default && result.base_def() != Def::Err && - path[0].name != keywords::CrateRoot.name() && - path[0].name != keywords::DollarCrate.name() { + path[0].ident.name != keywords::CrateRoot.name() && + path[0].ident.name != keywords::DollarCrate.name() { let unqualified_result = { match self.resolve_path_without_parent_scope( &[*path.last().unwrap()], @@ -3623,7 +3689,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { fn resolve_path_without_parent_scope( &mut self, - path: &[Ident], + path: &[Segment], opt_ns: Option, // `None` indicates a module path in import record_used: bool, path_span: Span, @@ -3638,7 +3704,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { fn resolve_path( &mut self, - path: &[Ident], + path: &[Segment], opt_ns: Option, // `None` indicates a module path in import parent_scope: &ParentScope<'a>, record_used: bool, @@ -3660,8 +3726,9 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { crate_lint, ); - for (i, &ident) in path.iter().enumerate() { + for (i, &Segment { ident, id }) in path.iter().enumerate() { debug!("resolve_path ident {} {:?}", i, ident); + let is_last = i == path.len() - 1; let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS }; let name = ident.name; @@ -3721,7 +3788,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { } else { format!("`{}`", name) }; - let msg = if i == 1 && path[0].name == keywords::CrateRoot.name() { + let msg = if i == 1 && path[0].ident.name == keywords::CrateRoot.name() { format!("global paths cannot start with {}", name_str) } else { format!("{} in paths can only be used in start position", name_str) @@ -3762,6 +3829,14 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { let maybe_assoc = opt_ns != Some(MacroNS) && PathSource::Type.is_expected(def); if let Some(next_module) = binding.module() { module = Some(ModuleOrUniformRoot::Module(next_module)); + if record_used { + if let Some(id) = id { + if !self.def_map.contains_key(&id) { + assert!(id != ast::DUMMY_NODE_ID, "Trying to resolve dummy id"); + self.record_def(id, PathResolution::new(def)); + } + } + } } else if def == Def::ToolMod && i + 1 != path.len() { let def = Def::NonMacroAttr(NonMacroAttrKind::Tool); return PathResult::NonModule(PathResolution::new(def)); @@ -3811,7 +3886,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { } else if i == 0 { format!("use of undeclared type or module `{}`", ident) } else { - format!("could not find `{}` in `{}`", ident, path[i - 1]) + format!("could not find `{}` in `{}`", ident, path[i - 1].ident) }; return PathResult::Failed(ident.span, msg, is_last); } @@ -3831,7 +3906,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { fn lint_if_path_starts_with_module( &self, crate_lint: CrateLint, - path: &[Ident], + path: &[Segment], path_span: Span, second_binding: Option<&NameBinding>, ) { @@ -3848,7 +3923,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { }; let first_name = match path.get(0) { - Some(ident) => ident.name, + Some(ident) => ident.ident.name, None => return, }; @@ -3860,7 +3935,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { match path.get(1) { // If this import looks like `crate::...` it's already good - Some(ident) if ident.name == keywords::Crate.name() => return, + Some(Segment { ident, .. }) if ident.name == keywords::Crate.name() => return, // Otherwise go below to see if it's an extern crate Some(_) => {} // If the path has length one (and it's `CrateRoot` most likely) @@ -4054,7 +4129,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { } fn lookup_typo_candidate(&mut self, - path: &[Ident], + path: &[Segment], ns: Namespace, filter_fn: FilterFn, span: Span) @@ -4119,7 +4194,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { } } - let name = path[path.len() - 1].name; + let name = path[path.len() - 1].ident.name; // Make sure error reporting is deterministic. names.sort_by_cached_key(|name| name.as_str()); match find_best_match_for_name(names.iter(), &name.as_str(), None) { @@ -4647,7 +4722,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { // On 2015 visibilities are resolved as crate-relative by default, // add starting root segment if necessary. let segments = path.make_root().iter().chain(path.segments.iter()) - .map(|seg| seg.ident) + .map(|seg| Segment { ident: seg.ident, id: Some(seg.id) }) .collect::>(); let def = self.smart_resolve_path_fragment( id, @@ -4990,12 +5065,12 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { } } -fn is_self_type(path: &[Ident], namespace: Namespace) -> bool { - namespace == TypeNS && path.len() == 1 && path[0].name == keywords::SelfType.name() +fn is_self_type(path: &[Segment], namespace: Namespace) -> bool { + namespace == TypeNS && path.len() == 1 && path[0].ident.name == keywords::SelfType.name() } -fn is_self_value(path: &[Ident], namespace: Namespace) -> bool { - namespace == ValueNS && path.len() == 1 && path[0].name == keywords::SelfValue.name() +fn is_self_value(path: &[Segment], namespace: Namespace) -> bool { + namespace == ValueNS && path.len() == 1 && path[0].ident.name == keywords::SelfValue.name() } fn names_to_string(idents: &[Ident]) -> String { diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 2877e6a436795..352b50768e654 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -10,8 +10,8 @@ use {AmbiguityError, AmbiguityKind, AmbiguityErrorMisc}; use {CrateLint, Resolver, ResolutionError, Weak}; -use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult, ToNameBinding}; -use {is_known_tool, names_to_string, resolve_error}; +use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult, Segment, ToNameBinding}; +use {is_known_tool, resolve_error}; use ModuleOrUniformRoot; use Namespace::{self, *}; use build_reduced_graph::{BuildReducedGraphVisitor, IsMacroExport}; @@ -470,13 +470,14 @@ impl<'a, 'cl> Resolver<'a, 'cl> { force: bool, ) -> Result { let path_span = path.span; - let mut path = path.segments.iter().map(|s| s.ident).collect::>(); + let mut path = Segment::from_path(path); // Possibly apply the macro helper hack if kind == MacroKind::Bang && path.len() == 1 && - path[0].span.ctxt().outer().expn_info().map_or(false, |info| info.local_inner_macros) { - let root = Ident::new(keywords::DollarCrate.name(), path[0].span); - path.insert(0, root); + path[0].ident.span.ctxt().outer().expn_info() + .map_or(false, |info| info.local_inner_macros) { + let root = Ident::new(keywords::DollarCrate.name(), path[0].ident.span); + path.insert(0, Segment::from_ident(root)); } if path.len() > 1 { @@ -501,7 +502,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { def } else { let binding = self.early_resolve_ident_in_lexical_scope( - path[0], MacroNS, Some(kind), false, parent_scope, false, force, path_span + path[0].ident, MacroNS, Some(kind), false, parent_scope, false, force, path_span ); match binding { Ok(..) => {} @@ -511,7 +512,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { if trace { parent_scope.module.single_segment_macro_resolutions.borrow_mut() - .push((path[0], kind, parent_scope.clone(), binding.ok())); + .push((path[0].ident, kind, parent_scope.clone(), binding.ok())); } binding.map(|binding| binding.def_ignoring_ambiguity()) @@ -945,7 +946,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { pub fn finalize_current_module_macro_resolutions(&mut self) { let module = self.current_module; - let check_consistency = |this: &mut Self, path: &[Ident], span, + let check_consistency = |this: &mut Self, path: &[Segment], span, kind: MacroKind, initial_def, def| { if let Some(initial_def) = initial_def { if def != initial_def && def != Def::Err && this.ambiguity_errors.is_empty() { @@ -964,7 +965,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { // less informative error if the privacy error is reported elsewhere. if this.privacy_errors.is_empty() { let msg = format!("cannot determine resolution for the {} `{}`", - kind.descr(), names_to_string(path)); + kind.descr(), Segment::names_to_string(path)); let msg_note = "import resolution is stuck, try simplifying macro imports"; this.session.struct_span_err(span, &msg).note(msg_note).emit(); } @@ -973,7 +974,9 @@ impl<'a, 'cl> Resolver<'a, 'cl> { let macro_resolutions = mem::replace(&mut *module.multi_segment_macro_resolutions.borrow_mut(), Vec::new()); - for (path, path_span, kind, parent_scope, initial_def) in macro_resolutions { + for (mut path, path_span, kind, parent_scope, initial_def) in macro_resolutions { + // FIXME: Path resolution will ICE if segment IDs present. + for seg in &mut path { seg.id = None; } match self.resolve_path(&path, Some(MacroNS), &parent_scope, true, path_span, CrateLint::No) { PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => { @@ -1004,7 +1007,8 @@ impl<'a, 'cl> Resolver<'a, 'cl> { initial_binding.def_ignoring_ambiguity() }); let def = binding.def_ignoring_ambiguity(); - check_consistency(self, &[ident], ident.span, kind, initial_def, def); + let seg = Segment::from_ident(ident); + check_consistency(self, &[seg], ident.span, kind, initial_def, def); } Err(..) => { assert!(initial_binding.is_none()); @@ -1050,7 +1054,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { } }; let ident = Ident::new(Symbol::intern(name), span); - self.lookup_typo_candidate(&[ident], MacroNS, is_macro, span) + self.lookup_typo_candidate(&[Segment::from_ident(ident)], MacroNS, is_macro, span) }); if let Some(suggestion) = suggestion { diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index e744fae7cafff..87a9b97344ad5 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -14,7 +14,7 @@ use {AmbiguityError, AmbiguityKind, AmbiguityErrorMisc}; use {CrateLint, Module, ModuleOrUniformRoot, PerNS, UniformRootKind, Weak}; use Namespace::{self, TypeNS, MacroNS}; use {NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyError}; -use Resolver; +use {Resolver, Segment}; use {names_to_string, module_to_string}; use {resolve_error, ResolutionError}; use macros::ParentScope; @@ -89,7 +89,7 @@ crate struct ImportDirective<'a> { pub root_span: Span, pub parent_scope: ParentScope<'a>, - pub module_path: Vec, + pub module_path: Vec, /// The resolution of `module_path`. pub imported_module: Cell>>, pub subclass: ImportDirectiveSubclass<'a>, @@ -367,7 +367,7 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> { // Add an import directive to the current module. pub fn add_import_directive(&mut self, - module_path: Vec, + module_path: Vec, subclass: ImportDirectiveSubclass<'a>, span: Span, id: NodeId, @@ -657,9 +657,11 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { self.throw_unresolved_import_error(empty_vec, None); } if !seen_spans.contains(&span) { - let path = import_path_to_string(&import.module_path[..], - &import.subclass, - span); + let path = import_path_to_string( + &import.module_path.iter().map(|seg| seg.ident).collect::>(), + &import.subclass, + span, + ); error_vec.push((span, path, err, note)); seen_spans.insert(span); prev_root_id = import.root_id; @@ -727,7 +729,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { /// If successful, the resolved bindings are written into the module. fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> bool { debug!("(resolving import for module) resolving import `{}::...` in `{}`", - names_to_string(&directive.module_path), + Segment::names_to_string(&directive.module_path), module_to_string(self.current_module).unwrap_or_else(|| "???".to_string())); self.current_module = directive.parent_scope.module; @@ -852,7 +854,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { ) { Some(( span, - format!("did you mean `{}`?", names_to_string(&suggested_path[..])), + format!("did you mean `{}`?", Segment::names_to_string(&suggested_path)), note, )) } else { @@ -874,7 +876,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { // HACK(eddyb) `lint_if_path_starts_with_module` needs at least // 2 segments, so the `resolve_path` above won't trigger it. let mut full_path = directive.module_path.clone(); - full_path.push(keywords::Invalid.ident()); + full_path.push(Segment::from_ident(keywords::Invalid.ident())); self.lint_if_path_starts_with_module( directive.crate_lint(), &full_path, @@ -1065,7 +1067,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { // HACK(eddyb) `lint_if_path_starts_with_module` needs at least // 2 segments, so the `resolve_path` above won't trigger it. let mut full_path = directive.module_path.clone(); - full_path.push(ident); + full_path.push(Segment::from_ident(ident)); self.per_ns(|this, ns| { if let Ok(binding) = result[ns].get() { this.lint_if_path_starts_with_module( @@ -1211,7 +1213,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { let resolutions = imported_module.parent.expect("parent should exist") .resolutions.borrow(); let enum_path_segment_index = directive.module_path.len() - 1; - let enum_ident = directive.module_path[enum_path_segment_index]; + let enum_ident = directive.module_path[enum_path_segment_index].ident; let enum_resolution = resolutions.get(&(enum_ident, TypeNS)) .expect("resolution should exist"); diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 01859d683e0f8..c0b718e4863fc 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -34,12 +34,10 @@ use std::env; use syntax::ast::{self, Attribute, NodeId, PatKind, CRATE_NODE_ID}; use syntax::parse::token; -use syntax::symbol::keywords; use syntax::visit::{self, Visitor}; use syntax::print::pprust::{ bounds_to_string, generic_params_to_string, - path_to_string, ty_to_string }; use syntax::ptr::P; @@ -219,95 +217,21 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { self.dumper.compilation_opts(data); } - // Return all non-empty prefixes of a path. - // For each prefix, we return the span for the last segment in the prefix and - // a str representation of the entire prefix. - fn process_path_prefixes(&self, path: &ast::Path) -> Vec<(Span, String)> { - let segments = &path.segments[if path.is_global() { 1 } else { 0 }..]; - - let mut result = Vec::with_capacity(segments.len()); - let mut segs = Vec::with_capacity(segments.len()); - - for (i, seg) in segments.iter().enumerate() { - segs.push(seg.clone()); - let sub_path = ast::Path { - span: seg.ident.span, // span for the last segment - segments: segs, - }; - let qualname = if i == 0 && path.is_global() { - format!("::{}", path_to_string(&sub_path)) - } else { - path_to_string(&sub_path) - }; - result.push((seg.ident.span, qualname)); - segs = sub_path.segments; - } - - result - } - fn write_sub_paths(&mut self, path: &ast::Path) { - let sub_paths = self.process_path_prefixes(path); - for (span, _) in sub_paths { - let span = self.span_from_span(span); - self.dumper.dump_ref(Ref { - kind: RefKind::Mod, - span, - ref_id: ::null_id(), - }); + for seg in &path.segments { + if let Some(data) = self.save_ctxt.get_path_segment_data(seg) { + self.dumper.dump_ref(data); + } } } // As write_sub_paths, but does not process the last ident in the path (assuming it // will be processed elsewhere). See note on write_sub_paths about global. fn write_sub_paths_truncated(&mut self, path: &ast::Path) { - let sub_paths = self.process_path_prefixes(path); - let len = sub_paths.len(); - if len <= 1 { - return; - } - - for (span, _) in sub_paths.into_iter().take(len - 1) { - let span = self.span_from_span(span); - self.dumper.dump_ref(Ref { - kind: RefKind::Mod, - span, - ref_id: ::null_id(), - }); - } - } - - // As write_sub_paths, but expects a path of the form module_path::trait::method - // Where trait could actually be a struct too. - fn write_sub_path_trait_truncated(&mut self, path: &ast::Path) { - let sub_paths = self.process_path_prefixes(path); - let len = sub_paths.len(); - if len <= 1 { - return; - } - let sub_paths = &sub_paths[..(len - 1)]; - - // write the trait part of the sub-path - let (ref span, _) = sub_paths[len - 2]; - let span = self.span_from_span(*span); - self.dumper.dump_ref(Ref { - kind: RefKind::Type, - ref_id: ::null_id(), - span, - }); - - // write the other sub-paths - if len <= 2 { - return; - } - let sub_paths = &sub_paths[..len - 2]; - for &(ref span, _) in sub_paths { - let span = self.span_from_span(*span); - self.dumper.dump_ref(Ref { - kind: RefKind::Mod, - span, - ref_id: ::null_id(), - }); + for seg in &path.segments[..path.segments.len() - 1] { + if let Some(data) = self.save_ctxt.get_path_segment_data(seg) { + self.dumper.dump_ref(data); + } } } @@ -323,7 +247,6 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { self.visit_pat(&arg.pat); let mut collector = PathCollector::new(); collector.visit_pat(&arg.pat); - let span_utils = self.span.clone(); for (id, ident, ..) in collector.collected_idents { let hir_id = self.tcx.hir.node_to_hir_id(id); @@ -331,10 +254,9 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { Some(s) => s.to_string(), None => continue, }; - let sub_span = span_utils.span_for_last_ident(ident.span); - if !self.span.filter_generated(sub_span, ident.span) { + if !self.span.filter_generated(ident.span) { let id = ::id_from_node_id(id, &self.save_ctxt); - let span = self.span_from_span(sub_span.expect("No span found for variable")); + let span = self.span_from_span(ident.span); self.dumper.dump_def( &Access { @@ -373,7 +295,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { ) { debug!("process_method: {}:{}", id, ident); - if let Some(mut method_data) = self.save_ctxt.get_method_data(id, ident.name, span) { + if let Some(mut method_data) = self.save_ctxt.get_method_data(id, ident, span) { let sig_str = ::make_signature(&sig.decl, &generics); if body.is_some() { self.nest_tables( @@ -382,7 +304,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { ); } - self.process_generic_params(&generics, span, &method_data.qualname, id); + self.process_generic_params(&generics, &method_data.qualname, id); method_data.value = sig_str; method_data.sig = sig::method_signature(id, ident, generics, sig, &self.save_ctxt); @@ -415,7 +337,6 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { fn process_generic_params( &mut self, generics: &'l ast::Generics, - full_span: Span, prefix: &str, id: NodeId, ) { @@ -427,7 +348,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { let name = escape(self.span.snippet(param_ss)); // Append $id to name to make sure each one is unique. let qualname = format!("{}::{}${}", prefix, name, id); - if !self.span.filter_generated(Some(param_ss), full_span) { + if !self.span.filter_generated(param_ss) { let id = ::id_from_node_id(param.id, &self.save_ctxt); let span = self.span_from_span(param_ss); @@ -471,7 +392,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { item.id, |v| v.process_formals(&decl.inputs, &fn_data.qualname), ); - self.process_generic_params(ty_params, item.span, &fn_data.qualname, item.id); + self.process_generic_params(ty_params, &fn_data.qualname, item.id); self.dumper.dump_def(&access_from!(self.save_ctxt, item), fn_data); } @@ -505,8 +426,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { fn process_assoc_const( &mut self, id: ast::NodeId, - name: ast::Name, - span: Span, + ident: ast::Ident, typ: &'l ast::Ty, expr: Option<&'l ast::Expr>, parent_id: DefId, @@ -515,11 +435,9 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { ) { let qualname = format!("::{}", self.tcx.node_path_str(id)); - let sub_span = self.span.sub_span_after_keyword(span, keywords::Const); - - if !self.span.filter_generated(sub_span, span) { - let sig = sig::assoc_const_signature(id, name, typ, expr, &self.save_ctxt); - let span = self.span_from_span(sub_span.expect("No span found for variable")); + if !self.span.filter_generated(ident.span) { + let sig = sig::assoc_const_signature(id, ident.name, typ, expr, &self.save_ctxt); + let span = self.span_from_span(ident.span); self.dumper.dump_def( &access_from!(self.save_ctxt, vis, id), @@ -527,7 +445,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { kind: DefKind::Const, id: ::id_from_node_id(id, &self.save_ctxt), span, - name: name.to_string(), + name: ident.name.to_string(), qualname, value: ty_to_string(&typ), parent: Some(::id_from_def_id(parent_id)), @@ -558,13 +476,12 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { let name = item.ident.to_string(); let qualname = format!("::{}", self.tcx.node_path_str(item.id)); - let (kind, keyword) = match item.node { - ast::ItemKind::Struct(_, _) => (DefKind::Struct, keywords::Struct), - ast::ItemKind::Union(_, _) => (DefKind::Union, keywords::Union), + let kind = match item.node { + ast::ItemKind::Struct(_, _) => DefKind::Struct, + ast::ItemKind::Union(_, _) => DefKind::Union, _ => unreachable!(), }; - let sub_span = self.span.sub_span_after_keyword(item.span, keyword); let (value, fields) = match item.node { ast::ItemKind::Struct(ast::VariantData::Struct(ref fields, _), _) | ast::ItemKind::Union(ast::VariantData::Struct(ref fields, _), _) => { @@ -595,8 +512,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { _ => (String::new(), vec![]), }; - if !self.span.filter_generated(sub_span, item.span) { - let span = self.span_from_span(sub_span.expect("No span found for struct")); + if !self.span.filter_generated(item.ident.span) { + let span = self.span_from_span(item.ident.span); self.dumper.dump_def( &access_from!(self.save_ctxt, item), Def { @@ -621,7 +538,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { self.visit_ty(&field.ty); } - self.process_generic_params(ty_params, item.span, &qualname, item.id); + self.process_generic_params(ty_params, &qualname, item.id); } fn process_enum( @@ -642,10 +559,10 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { for variant in &enum_definition.variants { let name = variant.node.ident.name.to_string(); let qualname = format!("{}::{}", enum_data.qualname, name); + let name_span = variant.node.ident.span; match variant.node.data { ast::VariantData::Struct(ref fields, _) => { - let sub_span = self.span.span_for_first_ident(variant.span); let fields_str = fields .iter() .enumerate() @@ -655,9 +572,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { .collect::>() .join(", "); let value = format!("{}::{} {{ {} }}", enum_data.name, name, fields_str); - if !self.span.filter_generated(sub_span, variant.span) { - let span = self - .span_from_span(sub_span.expect("No span found for struct variant")); + if !self.span.filter_generated(name_span) { + let span = self.span_from_span(name_span); let id = ::id_from_node_id(variant.node.data.id(), &self.save_ctxt); let parent = Some(::id_from_node_id(item.id, &self.save_ctxt)); @@ -684,7 +600,6 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { } } ref v => { - let sub_span = self.span.span_for_first_ident(variant.span); let mut value = format!("{}::{}", enum_data.name, name); if let &ast::VariantData::Tuple(ref fields, _) = v { value.push('('); @@ -695,9 +610,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { .join(", ")); value.push(')'); } - if !self.span.filter_generated(sub_span, variant.span) { - let span = - self.span_from_span(sub_span.expect("No span found for tuple variant")); + if !self.span.filter_generated(name_span) { + let span = self.span_from_span(name_span); let id = ::id_from_node_id(variant.node.data.id(), &self.save_ctxt); let parent = Some(::id_from_node_id(item.id, &self.save_ctxt)); @@ -731,7 +645,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { self.visit_ty(&field.ty); } } - self.process_generic_params(ty_params, item.span, &enum_data.qualname, item.id); + self.process_generic_params(ty_params, &enum_data.qualname, item.id); self.dumper.dump_def(&access, enum_data); } @@ -755,7 +669,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { if let &Some(ref trait_ref) = trait_ref { self.process_path(trait_ref.ref_id, &trait_ref.path); } - self.process_generic_params(type_parameters, item.span, "", item.id); + self.process_generic_params(type_parameters, "", item.id); for impl_item in impl_items { let map = &self.tcx.hir; self.process_impl_item(impl_item, map.local_def_id(item.id)); @@ -779,10 +693,9 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { val.push_str(": "); val.push_str(&bounds_to_string(trait_refs)); } - let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Trait); - if !self.span.filter_generated(sub_span, item.span) { + if !self.span.filter_generated(item.ident.span) { let id = ::id_from_node_id(item.id, &self.save_ctxt); - let span = self.span_from_span(sub_span.expect("No span found for trait")); + let span = self.span_from_span(item.ident.span); let children = methods .iter() .map(|i| ::id_from_node_id(i.id, &self.save_ctxt)) @@ -815,21 +728,18 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { let trait_ref = &trait_ref.trait_ref; if let Some(id) = self.lookup_def_id(trait_ref.ref_id) { - let sub_span = self.span.sub_span_for_type_name(trait_ref.path.span); - if !self.span.filter_generated(sub_span, trait_ref.path.span) { - let span = self.span_from_span(sub_span.expect("No span found for trait ref")); + let sub_span = trait_ref.path.segments.last().unwrap().ident.span; + if !self.span.filter_generated(sub_span) { + let span = self.span_from_span(sub_span); self.dumper.dump_ref(Ref { kind: RefKind::Type, - span, + span: span.clone(), ref_id: ::id_from_def_id(id), }); - } - if !self.span.filter_generated(sub_span, trait_ref.path.span) { - let sub_span = self.span_from_span(sub_span.expect("No span for inheritance")); self.dumper.dump_relation(Relation { kind: RelationKind::SuperTrait, - span: sub_span, + span, from: ::id_from_def_id(id), to: ::id_from_node_id(item.id, &self.save_ctxt), }); @@ -838,7 +748,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { } // walk generics and methods - self.process_generic_params(generics, item.span, &qualname, item.id); + self.process_generic_params(generics, &qualname, item.id); for method in methods { let map = &self.tcx.hir; self.process_trait_item(method, map.local_def_id(item.id)) @@ -891,29 +801,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { } } - // Modules or types in the path prefix. - match self.save_ctxt.get_path_def(id) { - HirDef::Method(did) => { - let ti = self.tcx.associated_item(did); - if ti.kind == ty::AssociatedKind::Method && ti.method_has_self_argument { - self.write_sub_path_trait_truncated(path); - } - } - HirDef::Fn(..) | - HirDef::Const(..) | - HirDef::Static(..) | - HirDef::StructCtor(..) | - HirDef::VariantCtor(..) | - HirDef::AssociatedConst(..) | - HirDef::Local(..) | - HirDef::Upvar(..) | - HirDef::Struct(..) | - HirDef::Union(..) | - HirDef::Variant(..) | - HirDef::TyAlias(..) | - HirDef::AssociatedTy(..) => self.write_sub_paths_truncated(path), - _ => {} - } + self.write_sub_paths_truncated(path); } fn process_struct_lit( @@ -924,9 +812,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { variant: &'l ty::VariantDef, base: &'l Option>, ) { - self.write_sub_paths_truncated(path); - if let Some(struct_lit_data) = self.save_ctxt.get_expr_data(ex) { + self.write_sub_paths_truncated(path); down_cast_data!(struct_lit_data, RefData, ex.span); if !generated_code(ex.span) { self.dumper.dump_ref(struct_lit_data); @@ -988,12 +875,10 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { }; let variant = adt.variant_of_def(self.save_ctxt.get_path_def(p.id)); - for &Spanned { node: ref field, span } in fields { - let sub_span = self.span.span_for_first_ident(span); + for &Spanned { node: ref field, .. } in fields { if let Some(index) = self.tcx.find_field_index(field.ident, variant) { - if !self.span.filter_generated(sub_span, span) { - let span = - self.span_from_span(sub_span.expect("No span fund for var ref")); + if !self.span.filter_generated(field.ident.span) { + let span = self.span_from_span(field.ident.span); self.dumper.dump_ref(Ref { kind: RefKind::Variable, span, @@ -1034,7 +919,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { value.push_str(": "); value.push_str(&typ); - if !self.span.filter_generated(Some(ident.span), ident.span) { + if !self.span.filter_generated(ident.span) { let qualname = format!("{}${}", ident.to_string(), id); let id = ::id_from_node_id(id, &self.save_ctxt); let span = self.span_from_span(ident.span); @@ -1109,14 +994,11 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { None => String::new(), }; - // Get the span only for the name of the variable (I hope the path - // is only ever a variable name, but who knows?). - let sub_span = self.span.span_for_last_ident(ident.span); // Rust uses the id of the pattern for var lookups, so we'll use it too. - if !self.span.filter_generated(sub_span, ident.span) { + if !self.span.filter_generated(ident.span) { let qualname = format!("{}${}", ident.to_string(), id); let id = ::id_from_node_id(id, &self.save_ctxt); - let span = self.span_from_span(sub_span.expect("No span found for variable")); + let span = self.span_from_span(ident.span); self.dumper.dump_def( &Access { @@ -1190,8 +1072,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { ast::TraitItemKind::Const(ref ty, ref expr) => { self.process_assoc_const( trait_item.id, - trait_item.ident.name, - trait_item.span, + trait_item.ident, &ty, expr.as_ref().map(|e| &**e), trait_id, @@ -1214,11 +1095,9 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { // FIXME do something with _bounds (for type refs) let name = trait_item.ident.name.to_string(); let qualname = format!("::{}", self.tcx.node_path_str(trait_item.id)); - let sub_span = self.span - .sub_span_after_keyword(trait_item.span, keywords::Type); - if !self.span.filter_generated(sub_span, trait_item.span) { - let span = self.span_from_span(sub_span.expect("No span found for assoc type")); + if !self.span.filter_generated(trait_item.ident.span) { + let span = self.span_from_span(trait_item.ident.span); let id = ::id_from_node_id(trait_item.id, &self.save_ctxt); self.dumper.dump_def( @@ -1263,8 +1142,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { ast::ImplItemKind::Const(ref ty, ref expr) => { self.process_assoc_const( impl_item.id, - impl_item.ident.name, - impl_item.span, + impl_item.ident, &ty, Some(expr), impl_id, @@ -1328,7 +1206,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { .map(::id_from_def_id); match use_tree.kind { - ast::UseTreeKind::Simple(..) => { + ast::UseTreeKind::Simple(alias, ..) => { let ident = use_tree.ident(); let path = ast::Path { segments: prefix.segments @@ -1339,24 +1217,22 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { span: path.span, }; - let sub_span = self.span.span_for_last_ident(path.span); - let alias_span = self.span.sub_span_after_keyword(use_tree.span, keywords::As); - let ref_id = self.lookup_def_id(id); - - if !self.span.filter_generated(sub_span, path.span) { - let span = self.span_from_span(sub_span.expect("No span found for use")); - let alias_span = alias_span.map(|sp| self.span_from_span(sp)); + let sub_span = path.segments.last().unwrap().ident.span; + if !self.span.filter_generated(sub_span) { + let ref_id = self.lookup_def_id(id).map(|id| ::id_from_def_id(id)); + let alias_span = alias.map(|i| self.span_from_span(i.span)); + let span = self.span_from_span(sub_span); self.dumper.import(&access, Import { kind: ImportKind::Use, - ref_id: ref_id.map(|id| ::id_from_def_id(id)), + ref_id, span, alias_span, name: ident.to_string(), value: String::new(), parent, }); + self.write_sub_paths_truncated(&path); } - self.write_sub_paths_truncated(&path); } ast::UseTreeKind::Glob => { let path = ast::Path { @@ -1377,9 +1253,9 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { Vec::new() }; - let sub_span = self.span.sub_span_of_token(use_tree.span, - token::BinOp(token::Star)); - if !self.span.filter_generated(sub_span, use_tree.span) { + let sub_span = + self.span.sub_span_of_token(use_tree.span, token::BinOp(token::Star)); + if !self.span.filter_generated(use_tree.span) { let span = self.span_from_span(sub_span.expect("No span found for use glob")); self.dumper.import(&access, Import { @@ -1391,8 +1267,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { value: names.join(", "), parent, }); + self.write_sub_paths(&path); } - self.write_sub_paths(&path); } ast::UseTreeKind::Nested(ref nested_items) => { let prefix = ast::Path { @@ -1471,11 +1347,9 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc self.process_use_tree(use_tree, item.id, item, &prefix); } ExternCrate(_) => { - let alias_span = self.span.span_for_last_ident(item.span); - - if !self.span.filter_generated(alias_span, item.span) { - let span = - self.span_from_span(alias_span.expect("No span found for extern crate")); + let name_span = item.ident.span; + if !self.span.filter_generated(name_span) { + let span = self.span_from_span(name_span); let parent = self.save_ctxt.tcx.hir.opt_local_def_id(item.id) .and_then(|id| self.save_ctxt.tcx.parent_def_id(id)) .map(::id_from_def_id); @@ -1518,9 +1392,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc Ty(ref ty, ref ty_params) => { let qualname = format!("::{}", self.tcx.node_path_str(item.id)); let value = ty_to_string(&ty); - let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Type); - if !self.span.filter_generated(sub_span, item.span) { - let span = self.span_from_span(sub_span.expect("No span found for typedef")); + if !self.span.filter_generated(item.ident.span) { + let span = self.span_from_span(item.ident.span); let id = ::id_from_node_id(item.id, &self.save_ctxt); self.dumper.dump_def( @@ -1543,15 +1416,14 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc } self.visit_ty(&ty); - self.process_generic_params(ty_params, item.span, &qualname, item.id); + self.process_generic_params(ty_params, &qualname, item.id); } Existential(ref _bounds, ref ty_params) => { let qualname = format!("::{}", self.tcx.node_path_str(item.id)); // FIXME do something with _bounds let value = String::new(); - let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Type); - if !self.span.filter_generated(sub_span, item.span) { - let span = self.span_from_span(sub_span.expect("No span found for typedef")); + if !self.span.filter_generated(item.ident.span) { + let span = self.span_from_span(item.ident.span); let id = ::id_from_node_id(item.id, &self.save_ctxt); self.dumper.dump_def( @@ -1573,7 +1445,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc ); } - self.process_generic_params(ty_params, item.span, &qualname, item.id); + self.process_generic_params(ty_params, &qualname, item.id); } Mac(_) => (), _ => visit::walk_item(self, item), @@ -1606,14 +1478,13 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc } if let Some(id) = self.lookup_def_id(t.id) { - if let Some(sub_span) = self.span.sub_span_for_type_name(t.span) { - let span = self.span_from_span(sub_span); - self.dumper.dump_ref(Ref { - kind: RefKind::Type, - span, - ref_id: ::id_from_def_id(id), - }); - } + let sub_span = path.segments.last().unwrap().ident.span; + let span = self.span_from_span(sub_span); + self.dumper.dump_ref(Ref { + kind: RefKind::Type, + span, + ref_id: ::id_from_def_id(id), + }); } self.write_sub_paths_truncated(path); @@ -1753,11 +1624,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc if let Some(fn_data) = self.save_ctxt.get_extern_item_data(item) { down_cast_data!(fn_data, DefData, item.span); - self.nest_tables( - item.id, - |v| v.process_formals(&decl.inputs, &fn_data.qualname), - ); - self.process_generic_params(generics, item.span, &fn_data.qualname, item.id); + self.process_generic_params(generics, &fn_data.qualname, item.id); self.dumper.dump_def(&access, fn_data); } diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 4b43a1a6270f8..7689406b59a04 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -57,12 +57,10 @@ use std::env; use std::fs::File; use std::path::{Path, PathBuf}; -use syntax::ast::{self, Attribute, NodeId, PatKind}; +use syntax::ast::{self, Attribute, DUMMY_NODE_ID, NodeId, PatKind}; use syntax::source_map::Spanned; use syntax::parse::lexer::comments::strip_doc_comment_decoration; -use syntax::parse::token; use syntax::print::pprust; -use syntax::symbol::keywords; use syntax::visit::{self, Visitor}; use syntax::print::pprust::{arg_to_string, ty_to_string}; use syntax::source_map::MacroAttribute; @@ -162,14 +160,12 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { let qualname = format!("::{}", self.tcx.node_path_str(item.id)); match item.node { ast::ForeignItemKind::Fn(ref decl, ref generics) => { - let sub_span = self.span_utils - .sub_span_after_keyword(item.span, keywords::Fn); - filter!(self.span_utils, sub_span, item.span, None); + filter!(self.span_utils, item.ident.span); Some(Data::DefData(Def { kind: DefKind::ForeignFunction, id: id_from_node_id(item.id, self), - span: self.span_from_span(sub_span.unwrap()), + span: self.span_from_span(item.ident.span), name: item.ident.to_string(), qualname, value: make_signature(decl, generics), @@ -181,13 +177,11 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { attributes: lower_attributes(item.attrs.clone(), self), })) } - ast::ForeignItemKind::Static(ref ty, m) => { - let keyword = if m { keywords::Mut } else { keywords::Static }; - let sub_span = self.span_utils.sub_span_after_keyword(item.span, keyword); - filter!(self.span_utils, sub_span, item.span, None); + ast::ForeignItemKind::Static(ref ty, _) => { + filter!(self.span_utils, item.ident.span); let id = ::id_from_node_id(item.id, self); - let span = self.span_from_span(sub_span.unwrap()); + let span = self.span_from_span(item.ident.span); Some(Data::DefData(Def { kind: DefKind::ForeignStatic, @@ -214,13 +208,11 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { match item.node { ast::ItemKind::Fn(ref decl, .., ref generics, _) => { let qualname = format!("::{}", self.tcx.node_path_str(item.id)); - let sub_span = self.span_utils - .sub_span_after_keyword(item.span, keywords::Fn); - filter!(self.span_utils, sub_span, item.span, None); + filter!(self.span_utils, item.ident.span); Some(Data::DefData(Def { kind: DefKind::Function, id: id_from_node_id(item.id, self), - span: self.span_from_span(sub_span.unwrap()), + span: self.span_from_span(item.ident.span), name: item.ident.to_string(), qualname, value: make_signature(decl, generics), @@ -232,19 +224,13 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { attributes: lower_attributes(item.attrs.clone(), self), })) } - ast::ItemKind::Static(ref typ, mt, _) => { + ast::ItemKind::Static(ref typ, ..) => { let qualname = format!("::{}", self.tcx.node_path_str(item.id)); - let keyword = match mt { - ast::Mutability::Mutable => keywords::Mut, - ast::Mutability::Immutable => keywords::Static, - }; - - let sub_span = self.span_utils.sub_span_after_keyword(item.span, keyword); - filter!(self.span_utils, sub_span, item.span, None); + filter!(self.span_utils, item.ident.span); let id = id_from_node_id(item.id, self); - let span = self.span_from_span(sub_span.unwrap()); + let span = self.span_from_span(item.ident.span); Some(Data::DefData(Def { kind: DefKind::Static, @@ -263,12 +249,10 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } ast::ItemKind::Const(ref typ, _) => { let qualname = format!("::{}", self.tcx.node_path_str(item.id)); - let sub_span = self.span_utils - .sub_span_after_keyword(item.span, keywords::Const); - filter!(self.span_utils, sub_span, item.span, None); + filter!(self.span_utils, item.ident.span); let id = id_from_node_id(item.id, self); - let span = self.span_from_span(sub_span.unwrap()); + let span = self.span_from_span(item.ident.span); Some(Data::DefData(Def { kind: DefKind::Const, @@ -291,16 +275,14 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { let cm = self.tcx.sess.source_map(); let filename = cm.span_to_filename(m.inner); - let sub_span = self.span_utils - .sub_span_after_keyword(item.span, keywords::Mod); - filter!(self.span_utils, sub_span, item.span, None); + filter!(self.span_utils, item.ident.span); Some(Data::DefData(Def { kind: DefKind::Mod, id: id_from_node_id(item.id, self), name: item.ident.to_string(), qualname, - span: self.span_from_span(sub_span.unwrap()), + span: self.span_from_span(item.ident.span), value: filename.to_string(), parent: None, children: m.items @@ -316,9 +298,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { ast::ItemKind::Enum(ref def, _) => { let name = item.ident.to_string(); let qualname = format!("::{}", self.tcx.node_path_str(item.id)); - let sub_span = self.span_utils - .sub_span_after_keyword(item.span, keywords::Enum); - filter!(self.span_utils, sub_span, item.span, None); + filter!(self.span_utils, item.ident.span); let variants_str = def.variants .iter() .map(|v| v.node.ident.to_string()) @@ -328,7 +308,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { Some(Data::DefData(Def { kind: DefKind::Enum, id: id_from_node_id(item.id, self), - span: self.span_from_span(sub_span.unwrap()), + span: self.span_from_span(item.ident.span), name, qualname, value, @@ -349,11 +329,11 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { if generated_code(path.span) { return None; } - let sub_span = self.span_utils.sub_span_for_type_name(path.span); - filter!(self.span_utils, sub_span, typ.span, None); + let sub_span = path.segments.last().unwrap().ident.span; + filter!(self.span_utils, sub_span); let impl_id = self.next_impl_id(); - let span = self.span_from_span(sub_span.unwrap()); + let span = self.span_from_span(sub_span); let type_data = self.lookup_ref_id(typ.id); type_data.map(|type_data| { @@ -402,15 +382,13 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { if let Some(ident) = field.ident { let name = ident.to_string(); let qualname = format!("::{}::{}", self.tcx.node_path_str(scope), ident); - let sub_span = self.span_utils - .sub_span_before_token(field.span, token::Colon); - filter!(self.span_utils, sub_span, field.span, None); + filter!(self.span_utils, ident.span); let def_id = self.tcx.hir.local_def_id(field.id); let typ = self.tcx.type_of(def_id).to_string(); let id = id_from_node_id(field.id, self); - let span = self.span_from_span(sub_span.unwrap()); + let span = self.span_from_span(ident.span); Some(Def { kind: DefKind::Field, @@ -433,7 +411,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { // FIXME would be nice to take a MethodItem here, but the ast provides both // trait and impl flavours, so the caller must do the disassembly. - pub fn get_method_data(&self, id: ast::NodeId, name: ast::Name, span: Span) -> Option { + pub fn get_method_data(&self, id: ast::NodeId, ident: ast::Ident, span: Span) -> Option { // The qualname for a method is the trait name or name of the struct in an impl in // which the method is declared in, followed by the method's name. let (qualname, parent_scope, decl_id, docs, attributes) = @@ -459,7 +437,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { qualname.push_str(&self.tcx.item_path_str(def_id)); self.tcx .associated_items(def_id) - .find(|item| item.ident.name == name) + .find(|item| item.ident.name == ident.name) .map(|item| decl_id = Some(item.def_id)); } qualname.push_str(">"); @@ -512,16 +490,15 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { }, }; - let qualname = format!("{}::{}", qualname, name); + let qualname = format!("{}::{}", qualname, ident.name); - let sub_span = self.span_utils.sub_span_after_keyword(span, keywords::Fn); - filter!(self.span_utils, sub_span, span, None); + filter!(self.span_utils, ident.span); Some(Def { kind: DefKind::Method, id: id_from_node_id(id, self), - span: self.span_from_span(sub_span.unwrap()), - name: name.to_string(), + span: self.span_from_span(ident.span), + name: ident.name.to_string(), qualname, // FIXME you get better data here by using the visitor. value: String::new(), @@ -540,9 +517,9 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { if generated_code(span) { return None; } - let sub_span = self.span_utils.sub_span_for_type_name(span).or(Some(span)); - filter!(self.span_utils, sub_span, span, None); - let span = self.span_from_span(sub_span.unwrap()); + let sub_span = trait_ref.path.segments.last().unwrap().ident.span; + filter!(self.span_utils, sub_span); + let span = self.span_from_span(sub_span); Some(Ref { kind: RefKind::Type, span, @@ -574,9 +551,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { ty::Adt(def, _) if !def.is_enum() => { let variant = &def.non_enum_variant(); let index = self.tcx.find_field_index(ident, variant).unwrap(); - let sub_span = self.span_utils.span_for_last_ident(expr.span); - filter!(self.span_utils, sub_span, expr.span, None); - let span = self.span_from_span(sub_span.unwrap()); + filter!(self.span_utils, ident.span); + let span = self.span_from_span(ident.span); return Some(Data::RefData(Ref { kind: RefKind::Variable, span, @@ -593,9 +569,9 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { ast::ExprKind::Struct(ref path, ..) => { match self.tables.expr_ty_adjusted(&hir_node).sty { ty::Adt(def, _) if !def.is_enum() => { - let sub_span = self.span_utils.span_for_last_ident(path.span); - filter!(self.span_utils, sub_span, path.span, None); - let span = self.span_from_span(sub_span.unwrap()); + let sub_span = path.segments.last().unwrap().ident.span; + filter!(self.span_utils, sub_span); + let span = self.span_from_span(sub_span); Some(Data::RefData(Ref { kind: RefKind::Type, span, @@ -624,7 +600,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { ty::TraitContainer(_) => (None, Some(method_id)), }; let sub_span = seg.ident.span; - filter!(self.span_utils, Some(sub_span), expr.span, None); + filter!(self.span_utils, sub_span); let span = self.span_from_span(sub_span); Some(Data::RefData(Ref { kind: RefKind::Function, @@ -656,6 +632,10 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { Node::Visibility(&Spanned { node: hir::VisibilityKind::Restricted { ref path, .. }, .. }) => path.def, + Node::PathSegment(seg) => match seg.def { + Some(def) => def, + None => HirDef::Err, + }, Node::Expr(&hir::Expr { node: hir::ExprKind::Struct(ref qpath, ..), .. @@ -708,13 +688,14 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } } - pub fn get_path_data(&self, id: NodeId, path: &ast::Path) -> Option { + pub fn get_path_data(&self, _id: NodeId, path: &ast::Path) -> Option { + path.segments.last().and_then(|seg| self.get_path_segment_data(seg)) + } + + pub fn get_path_segment_data(&self, path_seg: &ast::PathSegment) -> Option { // Returns true if the path is function type sugar, e.g., `Fn(A) -> B`. - fn fn_type(path: &ast::Path) -> bool { - if path.segments.len() != 1 { - return false; - } - if let Some(ref generic_args) = path.segments[0].args { + fn fn_type(seg: &ast::PathSegment) -> bool { + if let Some(ref generic_args) = seg.args { if let ast::GenericArgs::Parenthesized(_) = **generic_args { return true; } @@ -722,17 +703,17 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { false } - if path.segments.is_empty() { + if path_seg.id == DUMMY_NODE_ID { return None; } - let def = self.get_path_def(id); - let last_seg = &path.segments[path.segments.len() - 1]; - let sub_span = last_seg.ident.span; - filter!(self.span_utils, Some(sub_span), path.span, None); + let def = self.get_path_def(path_seg.id); + let span = path_seg.ident.span; + filter!(self.span_utils, span); + let span = self.span_from_span(span); + match def { HirDef::Upvar(id, ..) | HirDef::Local(id) => { - let span = self.span_from_span(sub_span); Some(Ref { kind: RefKind::Variable, span, @@ -743,23 +724,17 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { HirDef::Const(..) | HirDef::AssociatedConst(..) | HirDef::VariantCtor(..) => { - let span = self.span_from_span(sub_span); Some(Ref { kind: RefKind::Variable, span, ref_id: id_from_def_id(def.def_id()), }) } - HirDef::Trait(def_id) if fn_type(path) => { - // Function type bounds are desugared in the parser, so we have to - // special case them here. - let fn_span = self.span_utils.span_for_first_ident(path.span); - fn_span.map(|span| { - Ref { - kind: RefKind::Type, - span: self.span_from_span(span), - ref_id: id_from_def_id(def_id), - } + HirDef::Trait(def_id) if fn_type(path_seg) => { + Some(Ref { + kind: RefKind::Type, + span, + ref_id: id_from_def_id(def_id), }) } HirDef::Struct(def_id) | @@ -774,7 +749,6 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { HirDef::Trait(def_id) | HirDef::Existential(def_id) | HirDef::TyParam(def_id) => { - let span = self.span_from_span(sub_span); Some(Ref { kind: RefKind::Type, span, @@ -785,7 +759,6 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { // This is a reference to a tuple struct where the def_id points // to an invisible constructor function. That is not a very useful // def, so adjust to point to the tuple struct itself. - let span = self.span_from_span(sub_span); let parent_def_id = self.tcx.parent_def_id(def_id).unwrap(); Some(Ref { kind: RefKind::Type, @@ -804,7 +777,6 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } else { None }; - let span = self.span_from_span(sub_span); Some(Ref { kind: RefKind::Function, span, @@ -812,7 +784,6 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { }) } HirDef::Fn(def_id) => { - let span = self.span_from_span(sub_span); Some(Ref { kind: RefKind::Function, span, @@ -820,7 +791,6 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { }) } HirDef::Mod(def_id) => { - let span = self.span_from_span(sub_span); Some(Ref { kind: RefKind::Mod, span, @@ -843,15 +813,14 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { field_ref: &ast::Field, variant: &ty::VariantDef, ) -> Option { - let index = self.tcx.find_field_index(field_ref.ident, variant).unwrap(); - // We don't really need a sub-span here, but no harm done - let sub_span = self.span_utils.span_for_last_ident(field_ref.ident.span); - filter!(self.span_utils, sub_span, field_ref.ident.span, None); - let span = self.span_from_span(sub_span.unwrap()); - Some(Ref { - kind: RefKind::Variable, - span, - ref_id: id_from_def_id(variant.fields[index].did), + filter!(self.span_utils, field_ref.ident.span); + self.tcx.find_field_index(field_ref.ident, variant).map(|index| { + let span = self.span_from_span(field_ref.ident.span); + Ref { + kind: RefKind::Variable, + span, + ref_id: id_from_def_id(variant.fields[index].did), + } }) } diff --git a/src/librustc_save_analysis/span_utils.rs b/src/librustc_save_analysis/span_utils.rs index 47677a751712e..902353da13f76 100644 --- a/src/librustc_save_analysis/span_utils.rs +++ b/src/librustc_save_analysis/span_utils.rs @@ -16,7 +16,6 @@ use std::cell::Cell; use syntax::parse::lexer::{self, StringReader}; use syntax::parse::token::{self, Token}; -use syntax::symbol::keywords; use syntax_pos::*; #[derive(Clone)] @@ -67,131 +66,6 @@ impl<'a> SpanUtils<'a> { lexer::StringReader::retokenize(&self.sess.parse_sess, span) } - // Re-parses a path and returns the span for the last identifier in the path - pub fn span_for_last_ident(&self, span: Span) -> Option { - let mut result = None; - - let mut toks = self.retokenise_span(span); - let mut bracket_count = 0; - loop { - let ts = toks.real_token(); - if ts.tok == token::Eof { - return result; - } - if bracket_count == 0 && (ts.tok.is_ident() || ts.tok.is_keyword(keywords::SelfValue)) { - result = Some(ts.sp); - } - - bracket_count += match ts.tok { - token::Lt => 1, - token::Gt => -1, - token::BinOp(token::Shr) => -2, - _ => 0, - } - } - } - - // Return the span for the first identifier in the path. - pub fn span_for_first_ident(&self, span: Span) -> Option { - let mut toks = self.retokenise_span(span); - let mut bracket_count = 0; - loop { - let ts = toks.real_token(); - if ts.tok == token::Eof { - return None; - } - if bracket_count == 0 && (ts.tok.is_ident() || ts.tok.is_keyword(keywords::SelfValue)) { - return Some(ts.sp); - } - - bracket_count += match ts.tok { - token::Lt => 1, - token::Gt => -1, - token::BinOp(token::Shr) => -2, - _ => 0, - } - } - } - - // Return the span for the last ident before a `<` and outside any - // angle brackets, or the last span. - pub fn sub_span_for_type_name(&self, span: Span) -> Option { - let mut toks = self.retokenise_span(span); - let mut prev = toks.real_token(); - let mut result = None; - - // We keep track of the following two counts - the depth of nesting of - // angle brackets, and the depth of nesting of square brackets. For the - // angle bracket count, we only count tokens which occur outside of any - // square brackets (i.e. bracket_count == 0). The intuition here is - // that we want to count angle brackets in the type, but not any which - // could be in expression context (because these could mean 'less than', - // etc.). - let mut angle_count = 0; - let mut bracket_count = 0; - loop { - let next = toks.real_token(); - - if (next.tok == token::Lt || next.tok == token::Colon) && angle_count == 0 - && bracket_count == 0 && prev.tok.is_ident() - { - result = Some(prev.sp); - } - - if bracket_count == 0 { - angle_count += match prev.tok { - token::Lt => 1, - token::Gt => -1, - token::BinOp(token::Shl) => 2, - token::BinOp(token::Shr) => -2, - _ => 0, - }; - } - - bracket_count += match prev.tok { - token::OpenDelim(token::Bracket) => 1, - token::CloseDelim(token::Bracket) => -1, - _ => 0, - }; - - if next.tok == token::Eof { - break; - } - prev = next; - } - #[cfg(debug_assertions)] { - if angle_count != 0 || bracket_count != 0 { - let loc = self.sess.source_map().lookup_char_pos(span.lo()); - span_bug!( - span, - "Mis-counted brackets when breaking path? Parsing '{}' in {}, line {}", - self.snippet(span), - loc.file.name, - loc.line - ); - } - } - if result.is_none() && prev.tok.is_ident() { - return Some(prev.sp); - } - result - } - - pub fn sub_span_before_token(&self, span: Span, tok: Token) -> Option { - let mut toks = self.retokenise_span(span); - let mut prev = toks.real_token(); - loop { - if prev.tok == token::Eof { - return None; - } - let next = toks.real_token(); - if next.tok == tok { - return Some(prev.sp); - } - prev = next; - } - } - pub fn sub_span_of_token(&self, span: Span, tok: Token) -> Option { let mut toks = self.retokenise_span(span); loop { @@ -205,28 +79,6 @@ impl<'a> SpanUtils<'a> { } } - pub fn sub_span_after_keyword(&self, span: Span, keyword: keywords::Keyword) -> Option { - self.sub_span_after(span, |t| t.is_keyword(keyword)) - } - - fn sub_span_after bool>(&self, span: Span, f: F) -> Option { - let mut toks = self.retokenise_span(span); - loop { - let ts = toks.real_token(); - if ts.tok == token::Eof { - return None; - } - if f(ts.tok) { - let ts = toks.real_token(); - if ts.tok == token::Eof { - return None; - } else { - return Some(ts.sp); - } - } - } - } - // // Return the name for a macro definition (identifier after first `!`) // pub fn span_for_macro_def_name(&self, span: Span) -> Option { // let mut toks = self.retokenise_span(span); @@ -271,42 +123,28 @@ impl<'a> SpanUtils<'a> { /// /// Used to filter out spans of minimal value, /// such as references to macro internal variables. - pub fn filter_generated(&self, sub_span: Option, parent: Span) -> bool { - if !generated_code(parent) { - // Edge case - this occurs on generated code with incorrect expansion info. - return sub_span.is_none() + pub fn filter_generated(&self, span: Span) -> bool { + if span.is_dummy() { + return true; + } + + if !generated_code(span) { + return false; } - // If sub_span is none, filter out generated code. - let sub_span = match sub_span { - Some(ss) => ss, - None => return true, - }; //If the span comes from a fake source_file, filter it. - if !self.sess + !self.sess .source_map() - .lookup_char_pos(parent.lo()) + .lookup_char_pos(span.lo()) .file .is_real_file() - { - return true; - } - - // Otherwise, a generated span is deemed invalid if it is not a sub-span of the root - // callsite. This filters out macro internal variables and most malformed spans. - !parent.source_callsite().contains(sub_span) } } macro_rules! filter { - ($util: expr, $span: expr, $parent: expr, None) => { - if $util.filter_generated($span, $parent) { + ($util: expr, $parent: expr) => { + if $util.filter_generated($parent) { return None; } }; - ($util: expr, $span: ident, $parent: expr) => { - if $util.filter_generated($span, $parent) { - return; - } - }; } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 4fe6cec301546..4281ccf5f67ee 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -4025,6 +4025,8 @@ where F: Fn(DefId) -> Def { def: def_ctor(def_id), segments: hir::HirVec::from_vec(apb.names.iter().map(|s| hir::PathSegment { ident: ast::Ident::from_str(&s), + id: None, + def: None, args: None, infer_types: false, }).collect()) diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 8f9c3fa4b7f20..d6b0127e44d01 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -186,6 +186,8 @@ impl<'a, 'tcx, 'rcx, 'cstore> DocContext<'a, 'tcx, 'rcx, 'cstore> { segments.push(hir::PathSegment::new( real_name.unwrap_or(last.ident), + None, + None, self.generics_to_path_params(generics.clone()), false, )); diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 9ed628e2ed337..ee82b9860058a 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -129,6 +129,8 @@ pub struct PathSegment { /// The identifier portion of this path segment. pub ident: Ident, + pub id: NodeId, + /// Type/lifetime parameters attached to this path. They come in /// two flavors: `Path` and `Path(A,B) -> C`. /// `None` means that no parameter list is supplied (`Path`), @@ -140,7 +142,7 @@ pub struct PathSegment { impl PathSegment { pub fn from_ident(ident: Ident) -> Self { - PathSegment { ident, args: None } + PathSegment { ident, id: DUMMY_NODE_ID, args: None } } pub fn crate_root(span: Span) -> Self { PathSegment::from_ident(Ident::new(keywords::CrateRoot.name(), span)) diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 6210003a40da4..7928ec1606b1d 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -329,7 +329,11 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } else { None }; - segments.push(ast::PathSegment { ident: last_ident.with_span_pos(span), args }); + segments.push(ast::PathSegment { + ident: last_ident.with_span_pos(span), + id: ast::DUMMY_NODE_ID, + args, + }); let mut path = ast::Path { span, segments }; if global { if let Some(seg) = path.make_root() { @@ -366,7 +370,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } else { None }; - path.segments.push(ast::PathSegment { ident, args }); + path.segments.push(ast::PathSegment { ident, id: ast::DUMMY_NODE_ID, args }); (ast::QSelf { ty: self_type, diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 18d5970462f63..bec193548e176 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -468,8 +468,9 @@ pub fn noop_fold_usize(i: usize, _: &mut T) -> usize { pub fn noop_fold_path(Path { segments, span }: Path, fld: &mut T) -> Path { Path { - segments: segments.move_map(|PathSegment { ident, args }| PathSegment { + segments: segments.move_map(|PathSegment { ident, id, args }| PathSegment { ident: fld.fold_ident(ident), + id: fld.new_id(id), args: args.map(|args| args.map(|args| fld.fold_generic_args(args))), }), span: fld.new_span(span) @@ -1234,6 +1235,7 @@ pub fn noop_fold_expr(Expr {id, node, span, attrs}: Expr, folder: &mu ExprKind::MethodCall( PathSegment { ident: folder.fold_ident(seg.ident), + id: folder.new_id(seg.id), args: seg.args.map(|args| { args.map(|args| folder.fold_generic_args(args)) }), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 964d7fcab2052..be448f960df3f 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2134,7 +2134,7 @@ impl<'a> Parser<'a> { ParenthesisedArgs { inputs, output, span }.into() }; - PathSegment { ident, args } + PathSegment { ident, args, id: ast::DUMMY_NODE_ID } } else { // Generic arguments are not found. PathSegment::from_ident(ident) diff --git a/src/test/incremental/hashes/closure_expressions.rs b/src/test/incremental/hashes/closure_expressions.rs index 8469f0aa6645d..85d1f3df05b1d 100644 --- a/src/test/incremental/hashes/closure_expressions.rs +++ b/src/test/incremental/hashes/closure_expressions.rs @@ -95,7 +95,7 @@ pub fn add_type_ascription_to_parameter() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, TypeckTables")] +#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, TypeckTables")] #[rustc_clean(cfg="cfail3")] pub fn add_type_ascription_to_parameter() { let closure = |x: u32| x + 1u32; diff --git a/src/test/mir-opt/end_region_1.rs b/src/test/mir-opt/end_region_1.rs index 23c00c3bce1d8..dd1c2bd51260b 100644 --- a/src/test/mir-opt/end_region_1.rs +++ b/src/test/mir-opt/end_region_1.rs @@ -22,7 +22,7 @@ fn main() { // START rustc.main.SimplifyCfg-qualify-consts.after.mir // let mut _0: (); // ... -// let _2: &'10_1rs i32; +// let _2: &'11_1rs i32; // ... // let _1: i32; // ... @@ -31,10 +31,10 @@ fn main() { // _1 = const 3i32; // FakeRead(ForLet, _1); // StorageLive(_2); -// _2 = &'10_1rs _1; +// _2 = &'11_1rs _1; // FakeRead(ForLet, _2); // _0 = (); -// EndRegion('10_1rs); +// EndRegion('11_1rs); // StorageDead(_2); // StorageDead(_1); // return; diff --git a/src/test/mir-opt/end_region_2.rs b/src/test/mir-opt/end_region_2.rs index 08de5320a2b32..6b0a28b811007 100644 --- a/src/test/mir-opt/end_region_2.rs +++ b/src/test/mir-opt/end_region_2.rs @@ -27,9 +27,9 @@ fn main() { // START rustc.main.SimplifyCfg-qualify-consts.after.mir // let mut _0: (); // ... -// let _7: &'23_3rs bool; +// let _7: &'26_3rs bool; // ... -// let _3: &'23_1rs bool; +// let _3: &'26_1rs bool; // ... // let _2: bool; // ... @@ -47,7 +47,7 @@ fn main() { // _2 = const true; // FakeRead(ForLet, _2); // StorageLive(_3); -// _3 = &'23_1rs _2; +// _3 = &'26_1rs _2; // FakeRead(ForLet, _3); // StorageLive(_5); // _5 = _2; @@ -59,7 +59,7 @@ fn main() { // bb4: { // _0 = (); // StorageDead(_5); -// EndRegion('23_1rs); +// EndRegion('26_1rs); // StorageDead(_3); // StorageDead(_2); // return; @@ -68,12 +68,12 @@ fn main() { // _4 = (); // StorageDead(_5); // StorageLive(_7); -// _7 = &'23_3rs _2; +// _7 = &'26_3rs _2; // FakeRead(ForLet, _7); // _1 = (); -// EndRegion('23_3rs); +// EndRegion('26_3rs); // StorageDead(_7); -// EndRegion('23_1rs); +// EndRegion('26_1rs); // StorageDead(_3); // StorageDead(_2); // goto -> bb1; diff --git a/src/test/mir-opt/end_region_3.rs b/src/test/mir-opt/end_region_3.rs index 189154332b85a..d8d48358e53fc 100644 --- a/src/test/mir-opt/end_region_3.rs +++ b/src/test/mir-opt/end_region_3.rs @@ -28,9 +28,9 @@ fn main() { // START rustc.main.SimplifyCfg-qualify-consts.after.mir // let mut _0: (); // ... -// let _7: &'26_3rs bool; +// let _7: &'30_3rs bool; // ... -// let _3: &'26_1rs bool; +// let _3: &'30_1rs bool; // ... // let mut _1: bool; // ... @@ -48,7 +48,7 @@ fn main() { // bb2: { // _1 = const true; // StorageLive(_3); -// _3 = &'26_1rs _1; +// _3 = &'30_1rs _1; // FakeRead(ForLet, _3); // StorageLive(_5); // _5 = _1; @@ -60,7 +60,7 @@ fn main() { // bb4: { // _0 = (); // StorageDead(_5); -// EndRegion('26_1rs); +// EndRegion('30_1rs); // StorageDead(_3); // StorageDead(_1); // return; @@ -69,12 +69,12 @@ fn main() { // _4 = (); // StorageDead(_5); // StorageLive(_7); -// _7 = &'26_3rs _1; +// _7 = &'30_3rs _1; // FakeRead(ForLet, _7); // _2 = (); -// EndRegion('26_3rs); +// EndRegion('30_3rs); // StorageDead(_7); -// EndRegion('26_1rs); +// EndRegion('30_1rs); // StorageDead(_3); // goto -> bb1; // } diff --git a/src/test/mir-opt/end_region_4.rs b/src/test/mir-opt/end_region_4.rs index d5701669d2bdd..359ed07a9c095 100644 --- a/src/test/mir-opt/end_region_4.rs +++ b/src/test/mir-opt/end_region_4.rs @@ -32,9 +32,9 @@ fn foo(i: i32) { // START rustc.main.SimplifyCfg-qualify-consts.after.mir // let mut _0: (); // ... -// let _6: &'26_4rs i32; +// let _6: &'31_4rs i32; // ... -// let _3: &'26_2rs i32; +// let _3: &'31_2rs i32; // ... // let _2: i32; // ... @@ -50,7 +50,7 @@ fn foo(i: i32) { // _2 = const 0i32; // FakeRead(ForLet, _2); // StorageLive(_3); -// _3 = &'26_2rs _2; +// _3 = &'31_2rs _2; // FakeRead(ForLet, _3); // StorageLive(_5); // _5 = (*_3); @@ -62,18 +62,18 @@ fn foo(i: i32) { // bb2: { // StorageDead(_5); // StorageLive(_6); -// _6 = &'26_4rs _2; +// _6 = &'31_4rs _2; // FakeRead(ForLet, _6); // _0 = (); -// EndRegion('26_4rs); +// EndRegion('31_4rs); // StorageDead(_6); -// EndRegion('26_2rs); +// EndRegion('31_2rs); // StorageDead(_3); // StorageDead(_2); // drop(_1) -> [return: bb4, unwind: bb1]; // } // bb3: { -// EndRegion('26_2rs); +// EndRegion('31_2rs); // drop(_1) -> bb1; // } // bb4: { diff --git a/src/test/mir-opt/end_region_5.rs b/src/test/mir-opt/end_region_5.rs index 7a5d71ee21b93..3b632e198cd66 100644 --- a/src/test/mir-opt/end_region_5.rs +++ b/src/test/mir-opt/end_region_5.rs @@ -33,16 +33,16 @@ fn foo(f: F) where F: FnOnce() -> i32 { // let _1: D; // ... // let mut _2: (); -// let mut _3: [closure@NodeId(18) d:&'14s D]; -// let mut _4: &'14s D; +// let mut _3: [closure@NodeId(28) d:&'18s D]; +// let mut _4: &'18s D; // bb0: { // StorageLive(_1); // _1 = D::{{constructor}}(const 0i32,); // FakeRead(ForLet, _1); // StorageLive(_3); // StorageLive(_4); -// _4 = &'14s _1; -// _3 = [closure@NodeId(18)] { d: move _4 }; +// _4 = &'18s _1; +// _3 = [closure@NodeId(28)] { d: move _4 }; // StorageDead(_4); // _2 = const foo(move _3) -> [return: bb2, unwind: bb3]; // } @@ -50,13 +50,13 @@ fn foo(f: F) where F: FnOnce() -> i32 { // resume; // } // bb2: { -// EndRegion('14s); +// EndRegion('18s); // StorageDead(_3); // _0 = (); // drop(_1) -> [return: bb4, unwind: bb1]; // } // bb3: { -// EndRegion('14s); +// EndRegion('18s); // drop(_1) -> bb1; // } // bb4: { @@ -67,11 +67,11 @@ fn foo(f: F) where F: FnOnce() -> i32 { // END rustc.main.SimplifyCfg-qualify-consts.after.mir // START rustc.main-{{closure}}.SimplifyCfg-qualify-consts.after.mir -// fn main::{{closure}}(_1: [closure@NodeId(18) d:&'14s D]) -> i32 { +// fn main::{{closure}}(_1: [closure@NodeId(28) d:&'18s D]) -> i32 { // let mut _0: i32; // // bb0: { -// _0 = ((*(_1.0: &'14s D)).0: i32); +// _0 = ((*(_1.0: &'18s D)).0: i32); // return; // } // END rustc.main-{{closure}}.SimplifyCfg-qualify-consts.after.mir diff --git a/src/test/mir-opt/end_region_6.rs b/src/test/mir-opt/end_region_6.rs index b9162f85fa71e..03c7de02ec111 100644 --- a/src/test/mir-opt/end_region_6.rs +++ b/src/test/mir-opt/end_region_6.rs @@ -33,16 +33,16 @@ fn foo(f: F) where F: FnOnce() -> i32 { // let _1: D; // ... // let mut _2: (); -// let mut _3: [closure@NodeId(22) d:&'19s D]; -// let mut _4: &'19s D; +// let mut _3: [closure@NodeId(33) d:&'24s D]; +// let mut _4: &'24s D; // bb0: { // StorageLive(_1); // _1 = D::{{constructor}}(const 0i32,); // FakeRead(ForLet, _1); // StorageLive(_3); // StorageLive(_4); -// _4 = &'19s _1; -// _3 = [closure@NodeId(22)] { d: move _4 }; +// _4 = &'24s _1; +// _3 = [closure@NodeId(33)] { d: move _4 }; // StorageDead(_4); // _2 = const foo(move _3) -> [return: bb2, unwind: bb3]; // } @@ -50,13 +50,13 @@ fn foo(f: F) where F: FnOnce() -> i32 { // resume; // } // bb2: { -// EndRegion('19s); +// EndRegion('24s); // StorageDead(_3); // _0 = (); // drop(_1) -> [return: bb4, unwind: bb1]; // } // bb3: { -// EndRegion('19s); +// EndRegion('24s); // drop(_1) -> bb1; // } // bb4: { @@ -66,17 +66,17 @@ fn foo(f: F) where F: FnOnce() -> i32 { // END rustc.main.SimplifyCfg-qualify-consts.after.mir // START rustc.main-{{closure}}.SimplifyCfg-qualify-consts.after.mir -// fn main::{{closure}}(_1: [closure@NodeId(22) d:&'19s D]) -> i32 { +// fn main::{{closure}}(_1: [closure@NodeId(33) d:&'24s D]) -> i32 { // let mut _0: i32; // ... -// let _2: &'16_0rs D; +// let _2: &'21_0rs D; // ... // bb0: { // StorageLive(_2); -// _2 = &'16_0rs (*(_1.0: &'19s D)); +// _2 = &'21_0rs (*(_1.0: &'24s D)); // FakeRead(ForLet, _2); // _0 = ((*_2).0: i32); -// EndRegion('16_0rs); +// EndRegion('21_0rs); // StorageDead(_2); // return; // } diff --git a/src/test/mir-opt/end_region_7.rs b/src/test/mir-opt/end_region_7.rs index 4deea75e56b04..56e3e0aa6f7a9 100644 --- a/src/test/mir-opt/end_region_7.rs +++ b/src/test/mir-opt/end_region_7.rs @@ -33,13 +33,13 @@ fn foo(f: F) where F: FnOnce() -> i32 { // let _1: D; // ... // let mut _2: (); -// let mut _3: [closure@NodeId(22) d:D]; +// let mut _3: [closure@NodeId(33) d:D]; // bb0: { // StorageLive(_1); // _1 = D::{{constructor}}(const 0i32,); // FakeRead(ForLet, _1); // StorageLive(_3); -// _3 = [closure@NodeId(22)] { d: move _1 }; +// _3 = [closure@NodeId(33)] { d: move _1 }; // _2 = const foo(move _3) -> [return: bb2, unwind: bb4]; // } // bb1: { @@ -67,17 +67,17 @@ fn foo(f: F) where F: FnOnce() -> i32 { // END rustc.main.SimplifyCfg-qualify-consts.after.mir // START rustc.main-{{closure}}.SimplifyCfg-qualify-consts.after.mir -// fn main::{{closure}}(_1: [closure@NodeId(22) d:D]) -> i32 { +// fn main::{{closure}}(_1: [closure@NodeId(33) d:D]) -> i32 { // let mut _0: i32; // ... -// let _2: &'16_0rs D; +// let _2: &'21_0rs D; // ... // bb0: { // StorageLive(_2); -// _2 = &'16_0rs (_1.0: D); +// _2 = &'21_0rs (_1.0: D); // FakeRead(ForLet, _2); // _0 = ((*_2).0: i32); -// EndRegion('16_0rs); +// EndRegion('21_0rs); // StorageDead(_2); // drop(_1) -> [return: bb2, unwind: bb1]; // } diff --git a/src/test/mir-opt/end_region_8.rs b/src/test/mir-opt/end_region_8.rs index 6f899a0db15d9..0a54dcaa0d33f 100644 --- a/src/test/mir-opt/end_region_8.rs +++ b/src/test/mir-opt/end_region_8.rs @@ -31,37 +31,37 @@ fn foo(f: F) where F: FnOnce() -> i32 { // fn main() -> () { // let mut _0: (); // ... -// let _2: &'21_1rs D; +// let _2: &'26_1rs D; // ... // let _1: D; // ... // let mut _3: (); -// let mut _4: [closure@NodeId(22) r:&'19s D]; +// let mut _4: [closure@NodeId(33) r:&'24s D]; // bb0: { // StorageLive(_1); // _1 = D::{{constructor}}(const 0i32,); // FakeRead(ForLet, _1); // StorageLive(_2); -// _2 = &'21_1rs _1; +// _2 = &'26_1rs _1; // FakeRead(ForLet, _2); // StorageLive(_4); -// _4 = [closure@NodeId(22)] { r: _2 }; +// _4 = [closure@NodeId(33)] { r: _2 }; // _3 = const foo(move _4) -> [return: bb2, unwind: bb3]; // } // bb1: { // resume; // } // bb2: { -// EndRegion('19s); +// EndRegion('24s); // StorageDead(_4); // _0 = (); -// EndRegion('21_1rs); +// EndRegion('26_1rs); // StorageDead(_2); // drop(_1) -> [return: bb4, unwind: bb1]; // } // bb3: { -// EndRegion('19s); -// EndRegion('21_1rs); +// EndRegion('24s); +// EndRegion('26_1rs); // drop(_1) -> bb1; // } // bb4: { @@ -72,11 +72,11 @@ fn foo(f: F) where F: FnOnce() -> i32 { // END rustc.main.SimplifyCfg-qualify-consts.after.mir // START rustc.main-{{closure}}.SimplifyCfg-qualify-consts.after.mir -// fn main::{{closure}}(_1: [closure@NodeId(22) r:&'19s D]) -> i32 { +// fn main::{{closure}}(_1: [closure@NodeId(33) r:&'24s D]) -> i32 { // let mut _0: i32; // // bb0: { -// _0 = ((*(_1.0: &'21_1rs D)).0: i32); +// _0 = ((*(_1.0: &'26_1rs D)).0: i32); // return; // } // } diff --git a/src/test/mir-opt/end_region_9.rs b/src/test/mir-opt/end_region_9.rs index b43f25e6f548c..ef2d949d3074e 100644 --- a/src/test/mir-opt/end_region_9.rs +++ b/src/test/mir-opt/end_region_9.rs @@ -41,7 +41,7 @@ fn main() { // fn main() -> () { // let mut _0: (); // ... -// let mut _4: &'33_0rs i32; +// let mut _4: &'37_0rs i32; // ... // let _2: i32; // ... @@ -79,14 +79,14 @@ fn main() { // bb5: { // _0 = (); // StorageDead(_7); -// EndRegion('33_0rs); +// EndRegion('37_0rs); // StorageDead(_4); // StorageDead(_2); // StorageDead(_1); // return; // } // bb6: { -// _4 = &'33_0rs _2; +// _4 = &'37_0rs _2; // _6 = (); // StorageDead(_7); // _1 = const true; diff --git a/src/test/mir-opt/end_region_cyclic.rs b/src/test/mir-opt/end_region_cyclic.rs index 75cfb5c2f6239..3dbc73caf65d8 100644 --- a/src/test/mir-opt/end_region_cyclic.rs +++ b/src/test/mir-opt/end_region_cyclic.rs @@ -45,24 +45,24 @@ fn query() -> bool { true } // scope 1 { // } // scope 2 { -// let _2: S<'36_0rs>; +// let _2: S<'49_0rs>; // } // let mut _1: (); -// let mut _3: std::cell::Cell>>; -// let mut _4: std::option::Option<&'36_0rs S<'36_0rs>>; +// let mut _3: std::cell::Cell>>; +// let mut _4: std::option::Option<&'49_0rs S<'49_0rs>>; // let mut _5: (); -// let mut _6: &'17s std::cell::Cell>>; -// let mut _7: std::option::Option<&'36_0rs S<'36_0rs>>; -// let mut _8: &'36_0rs S<'36_0rs>; -// let mut _9: &'36_0rs S<'36_0rs>; +// let mut _6: &'25s std::cell::Cell>>; +// let mut _7: std::option::Option<&'49_0rs S<'49_0rs>>; +// let mut _8: &'49_0rs S<'49_0rs>; +// let mut _9: &'49_0rs S<'49_0rs>; // let mut _10: (); // let mut _11: bool; // let mut _12: !; // let mut _13: (); -// let mut _14: &'34s std::cell::Cell>>; -// let mut _15: std::option::Option<&'36_0rs S<'36_0rs>>; -// let mut _16: &'36_0rs S<'36_0rs>; -// let mut _17: &'36_0rs S<'36_0rs>; +// let mut _14: &'47s std::cell::Cell>>; +// let mut _15: std::option::Option<&'49_0rs S<'49_0rs>>; +// let mut _16: &'49_0rs S<'49_0rs>; +// let mut _17: &'49_0rs S<'49_0rs>; // bb0: { // goto -> bb1; // } @@ -73,7 +73,7 @@ fn query() -> bool { true } // StorageLive(_2); // StorageLive(_3); // StorageLive(_4); -// _4 = std::option::Option<&'36_0rs S<'36_0rs>>::None; +// _4 = std::option::Option<&'49_0rs S<'49_0rs>>::None; // _3 = const >::new(move _4) -> [return: bb4, unwind: bb3]; // } // bb3: { @@ -81,22 +81,22 @@ fn query() -> bool { true } // } // bb4: { // StorageDead(_4); -// _2 = S<'36_0rs> { r: move _3 }; +// _2 = S<'49_0rs> { r: move _3 }; // StorageDead(_3); // FakeRead(ForLet, _2); // StorageLive(_6); -// _6 = &'17s (_2.0: std::cell::Cell>>); +// _6 = &'25s (_2.0: std::cell::Cell>>); // StorageLive(_7); // StorageLive(_8); // StorageLive(_9); -// _9 = &'36_0rs _2; -// _8 = &'36_0rs (*_9); -// _7 = std::option::Option<&'36_0rs S<'36_0rs>>::Some(move _8,); +// _9 = &'49_0rs _2; +// _8 = &'49_0rs (*_9); +// _7 = std::option::Option<&'49_0rs S<'49_0rs>>::Some(move _8,); // StorageDead(_8); // _5 = const >::set(move _6, move _7) -> [return: bb5, unwind: bb3]; // } // bb5: { -// EndRegion('17s); +// EndRegion('25s); // StorageDead(_7); // StorageDead(_6); // StorageDead(_9); @@ -109,7 +109,7 @@ fn query() -> bool { true } // bb7: { // _0 = (); // StorageDead(_11); -// EndRegion('36_0rs); +// EndRegion('49_0rs); // StorageDead(_2); // return; // } @@ -117,23 +117,23 @@ fn query() -> bool { true } // _10 = (); // StorageDead(_11); // StorageLive(_14); -// _14 = &'34s (_2.0: std::cell::Cell>>); +// _14 = &'47s (_2.0: std::cell::Cell>>); // StorageLive(_15); // StorageLive(_16); // StorageLive(_17); -// _17 = &'36_0rs _2; -// _16 = &'36_0rs (*_17); -// _15 = std::option::Option<&'36_0rs S<'36_0rs>>::Some(move _16,); +// _17 = &'49_0rs _2; +// _16 = &'49_0rs (*_17); +// _15 = std::option::Option<&'49_0rs S<'49_0rs>>::Some(move _16,); // StorageDead(_16); // _13 = const >::set(move _14, move _15) -> [return: bb9, unwind: bb3]; // } // bb9: { -// EndRegion('34s); +// EndRegion('47s); // StorageDead(_15); // StorageDead(_14); // StorageDead(_17); // _1 = (); -// EndRegion('36_0rs); +// EndRegion('49_0rs); // StorageDead(_2); // goto -> bb1; // } diff --git a/src/test/mir-opt/end_region_destruction_extents_1.rs b/src/test/mir-opt/end_region_destruction_extents_1.rs index 16e2fe046fb69..a5107d304386f 100644 --- a/src/test/mir-opt/end_region_destruction_extents_1.rs +++ b/src/test/mir-opt/end_region_destruction_extents_1.rs @@ -41,16 +41,16 @@ unsafe impl<'a, #[may_dangle] 'b> Drop for D1<'a, 'b> { // Notes on the MIR output below: // -// 1. The `EndRegion('10s)` is allowed to precede the `drop(_3)` +// 1. The `EndRegion('13s)` is allowed to precede the `drop(_3)` // solely because of the #[may_dangle] mentioned above. // -// 2. Regarding the occurrence of `EndRegion('12ds)` *after* `StorageDead(_6)` -// (where we have borrows `&'12ds _6`): Eventually: +// 2. Regarding the occurrence of `EndRegion('15ds)` *after* `StorageDead(_6)` +// (where we have borrows `&'15ds _6`): Eventually: // // i. this code should be rejected (by mir-borrowck), or // // ii. the MIR code generation should be changed so that the -// EndRegion('12ds)` precedes `StorageDead(_6)` in the +// EndRegion('15ds)` precedes `StorageDead(_6)` in the // control-flow. (Note: arielb1 views drop+storagedead as one // unit, and does not see this option as a useful avenue to // explore.), or @@ -66,13 +66,13 @@ unsafe impl<'a, #[may_dangle] 'b> Drop for D1<'a, 'b> { // START rustc.main.QualifyAndPromoteConstants.before.mir // fn main() -> () { // let mut _0: (); -// let mut _1: &'12ds S1; -// let mut _2: D1<'12ds, '10s>; -// let mut _3: &'12ds S1; -// let mut _4: &'12ds S1; +// let mut _1: &'15ds S1; +// let mut _2: D1<'15ds, '13s>; +// let mut _3: &'15ds S1; +// let mut _4: &'15ds S1; // let _5: S1; -// let mut _6: &'10s S1; -// let mut _7: &'10s S1; +// let mut _6: &'13s S1; +// let mut _7: &'13s S1; // let _8: S1; // bb0: { // StorageLive(_2); @@ -80,19 +80,19 @@ unsafe impl<'a, #[may_dangle] 'b> Drop for D1<'a, 'b> { // StorageLive(_4); // StorageLive(_5); // _5 = S1::{{constructor}}(const "ex1",); -// _4 = &'12ds _5; -// _3 = &'12ds (*_4); +// _4 = &'15ds _5; +// _3 = &'15ds (*_4); // StorageLive(_6); // StorageLive(_7); // StorageLive(_8); // _8 = S1::{{constructor}}(const "dang1",); -// _7 = &'10s _8; -// _6 = &'10s (*_7); -// _2 = D1<'12ds, '10s>::{{constructor}}(move _3, move _6); -// EndRegion('10s); +// _7 = &'13s _8; +// _6 = &'13s (*_7); +// _2 = D1<'15ds, '13s>::{{constructor}}(move _3, move _6); +// EndRegion('13s); // StorageDead(_6); // StorageDead(_3); -// _1 = (_2.0: &'12ds S1); +// _1 = (_2.0: &'15ds S1); // drop(_2) -> [return: bb2, unwind: bb1]; // } // bb1: { @@ -104,7 +104,7 @@ unsafe impl<'a, #[may_dangle] 'b> Drop for D1<'a, 'b> { // StorageDead(_8); // StorageDead(_4); // StorageDead(_5); -// EndRegion('12ds); +// EndRegion('15ds); // _0 = (); // return; // } @@ -114,29 +114,29 @@ unsafe impl<'a, #[may_dangle] 'b> Drop for D1<'a, 'b> { // START rustc.main.QualifyAndPromoteConstants.after.mir // fn main() -> (){ // let mut _0: (); -// let mut _1: &'12ds S1; -// let mut _2: D1<'12ds, '10s>; -// let mut _3: &'12ds S1; -// let mut _4: &'12ds S1; +// let mut _1: &'15ds S1; +// let mut _2: D1<'15ds, '13s>; +// let mut _3: &'15ds S1; +// let mut _4: &'15ds S1; // let _5: S1; -// let mut _6: &'10s S1; -// let mut _7: &'10s S1; +// let mut _6: &'13s S1; +// let mut _7: &'13s S1; // let _8: S1; // bb0: { // StorageLive(_2); // StorageLive(_3); // StorageLive(_4); -// _4 = &'12ds (promoted[1]: S1); -// _3 = &'12ds (*_4); +// _4 = &'15ds (promoted[1]: S1); +// _3 = &'15ds (*_4); // StorageLive(_6); // StorageLive(_7); -// _7 = &'10s (promoted[0]: S1); -// _6 = &'10s (*_7); -// _2 = D1<'12ds, '10s>::{{constructor}}(move _3, move _6); -// EndRegion('10s); +// _7 = &'13s (promoted[0]: S1); +// _6 = &'13s (*_7); +// _2 = D1<'15ds, '13s>::{{constructor}}(move _3, move _6); +// EndRegion('13s); // StorageDead(_6); // StorageDead(_3); -// _1 = (_2.0: &'12ds S1); +// _1 = (_2.0: &'15ds S1); // drop(_2) -> [return: bb2, unwind: bb1]; // } // bb1: { @@ -146,7 +146,7 @@ unsafe impl<'a, #[may_dangle] 'b> Drop for D1<'a, 'b> { // StorageDead(_2); // StorageDead(_7); // StorageDead(_4); -// EndRegion('12ds); +// EndRegion('15ds); // _0 = (); // return; // } diff --git a/src/test/mir-opt/inline-closure-borrows-arg.rs b/src/test/mir-opt/inline-closure-borrows-arg.rs index aab432ddc8700..ba1712f4ca398 100644 --- a/src/test/mir-opt/inline-closure-borrows-arg.rs +++ b/src/test/mir-opt/inline-closure-borrows-arg.rs @@ -30,7 +30,7 @@ fn foo(_t: T, q: &i32) -> i32 { // ... // bb0: { // ... -// _3 = [closure@NodeId(39)]; +// _3 = [closure@NodeId(53)]; // ... // _4 = &_3; // ... diff --git a/src/test/mir-opt/inline-closure.rs b/src/test/mir-opt/inline-closure.rs index 22e7de31e90cf..9cb0a4dc2bfac 100644 --- a/src/test/mir-opt/inline-closure.rs +++ b/src/test/mir-opt/inline-closure.rs @@ -26,7 +26,7 @@ fn foo(_t: T, q: i32) -> i32 { // ... // bb0: { // ... -// _3 = [closure@NodeId(28)]; +// _3 = [closure@NodeId(39)]; // ... // _4 = &_3; // ... diff --git a/src/test/mir-opt/validate_1.rs b/src/test/mir-opt/validate_1.rs index 882579c571086..f1544968adb6a 100644 --- a/src/test/mir-opt/validate_1.rs +++ b/src/test/mir-opt/validate_1.rs @@ -40,35 +40,35 @@ fn main() { // ... // bb0: { // ... -// Validate(Suspend(ReScope(Node(ItemLocalId(10)))), [_1: i32]); +// Validate(Suspend(ReScope(Node(ItemLocalId(13)))), [_1: i32]); // _6 = &ReErased mut _1; -// Validate(Acquire, [(*_6): i32/ReScope(Node(ItemLocalId(10)))]); -// Validate(Suspend(ReScope(Node(ItemLocalId(10)))), [(*_6): i32/ReScope(Node(ItemLocalId(10)))]); +// Validate(Acquire, [(*_6): i32/ReScope(Node(ItemLocalId(13)))]); +// Validate(Suspend(ReScope(Node(ItemLocalId(13)))), [(*_6): i32/ReScope(Node(ItemLocalId(13)))]); // _5 = &ReErased mut (*_6); -// Validate(Acquire, [(*_5): i32/ReScope(Node(ItemLocalId(10)))]); -// Validate(Release, [_2: (), _3: &ReScope(Node(ItemLocalId(10))) Test, _5: &ReScope(Node(ItemLocalId(10))) mut i32]); +// Validate(Acquire, [(*_5): i32/ReScope(Node(ItemLocalId(13)))]); +// Validate(Release, [_2: (), _3: &ReScope(Node(ItemLocalId(13))) Test, _5: &ReScope(Node(ItemLocalId(13))) mut i32]); // _2 = const Test::foo(move _3, move _5) -> bb1; // } // // bb1: { // Validate(Acquire, [_2: ()]); -// EndRegion(ReScope(Node(ItemLocalId(10)))); +// EndRegion(ReScope(Node(ItemLocalId(13)))); // ... // return; // } // } // END rustc.main.EraseRegions.after.mir // START rustc.main-{{closure}}.EraseRegions.after.mir -// fn main::{{closure}}(_1: &ReErased [closure@NodeId(50)], _2: &ReErased mut i32) -> i32 { +// fn main::{{closure}}(_1: &ReErased [closure@NodeId(65)], _2: &ReErased mut i32) -> i32 { // ... // bb0: { -// Validate(Acquire, [_1: &ReFree(DefId(0/1:11 ~ validate_1[317d]::main[0]::{{closure}}[0]), BrEnv) [closure@NodeId(50)], _2: &ReFree(DefId(0/1:11 ~ validate_1[317d]::main[0]::{{closure}}[0]), BrAnon(0)) mut i32]); +// Validate(Acquire, [_1: &ReFree(DefId(0/1:11 ~ validate_1[317d]::main[0]::{{closure}}[0]), BrEnv) [closure@NodeId(65)], _2: &ReFree(DefId(0/1:11 ~ validate_1[317d]::main[0]::{{closure}}[0]), BrAnon(0)) mut i32]); // StorageLive(_3); -// Validate(Suspend(ReScope(Remainder { block: ItemLocalId(25), first_statement_index: 0 })), [(*_2): i32]); +// Validate(Suspend(ReScope(Remainder { block: ItemLocalId(31), first_statement_index: 0 })), [(*_2): i32]); // _3 = &ReErased (*_2); -// Validate(Acquire, [(*_3): i32/ReScope(Remainder { block: ItemLocalId(25), first_statement_index: 0 }) (imm)]); +// Validate(Acquire, [(*_3): i32/ReScope(Remainder { block: ItemLocalId(31), first_statement_index: 0 }) (imm)]); // _0 = (*_3); -// EndRegion(ReScope(Remainder { block: ItemLocalId(25), first_statement_index: 0 })); +// EndRegion(ReScope(Remainder { block: ItemLocalId(31), first_statement_index: 0 })); // StorageDead(_3); // return; // } diff --git a/src/test/mir-opt/validate_3.rs b/src/test/mir-opt/validate_3.rs index 07f5b2aa84b7d..ce840397713ad 100644 --- a/src/test/mir-opt/validate_3.rs +++ b/src/test/mir-opt/validate_3.rs @@ -48,27 +48,27 @@ fn main() { // StorageLive(_1); // _1 = Test { x: const 0i32 }; // StorageLive(_2); -// Validate(Suspend(ReScope(Remainder { block: ItemLocalId(20), first_statement_index: 3 })), [_1: Test]); +// Validate(Suspend(ReScope(Remainder { block: ItemLocalId(24), first_statement_index: 3 })), [_1: Test]); // _2 = &ReErased _1; -// Validate(Acquire, [(*_2): Test/ReScope(Remainder { block: ItemLocalId(20), first_statement_index: 3 }) (imm)]); +// Validate(Acquire, [(*_2): Test/ReScope(Remainder { block: ItemLocalId(24), first_statement_index: 3 }) (imm)]); // StorageLive(_4); // StorageLive(_5); -// Validate(Suspend(ReScope(Node(ItemLocalId(18)))), [((*_2).0: i32): i32/ReScope(Remainder { block: ItemLocalId(20), first_statement_index: 3 }) (imm)]); +// Validate(Suspend(ReScope(Node(ItemLocalId(22)))), [((*_2).0: i32): i32/ReScope(Remainder { block: ItemLocalId(24), first_statement_index: 3 }) (imm)]); // _5 = &ReErased ((*_2).0: i32); -// Validate(Acquire, [(*_5): i32/ReScope(Node(ItemLocalId(18))) (imm)]); -// Validate(Suspend(ReScope(Node(ItemLocalId(18)))), [(*_5): i32/ReScope(Node(ItemLocalId(18))) (imm)]); +// Validate(Acquire, [(*_5): i32/ReScope(Node(ItemLocalId(22))) (imm)]); +// Validate(Suspend(ReScope(Node(ItemLocalId(22)))), [(*_5): i32/ReScope(Node(ItemLocalId(22))) (imm)]); // _4 = &ReErased (*_5); -// Validate(Acquire, [(*_4): i32/ReScope(Node(ItemLocalId(18))) (imm)]); -// Validate(Release, [_3: (), _4: &ReScope(Node(ItemLocalId(18))) i32]); +// Validate(Acquire, [(*_4): i32/ReScope(Node(ItemLocalId(22))) (imm)]); +// Validate(Release, [_3: (), _4: &ReScope(Node(ItemLocalId(22))) i32]); // _3 = const foo(move _4) -> bb1; // } // bb1: { // Validate(Acquire, [_3: ()]); -// EndRegion(ReScope(Node(ItemLocalId(18)))); +// EndRegion(ReScope(Node(ItemLocalId(22)))); // StorageDead(_4); // StorageDead(_5); // _0 = (); -// EndRegion(ReScope(Remainder { block: ItemLocalId(20), first_statement_index: 3 })); +// EndRegion(ReScope(Remainder { block: ItemLocalId(24), first_statement_index: 3 })); // StorageDead(_2); // StorageDead(_1); // return; diff --git a/src/test/mir-opt/validate_4.rs b/src/test/mir-opt/validate_4.rs index 24a4ebd8429df..542ac8a42411f 100644 --- a/src/test/mir-opt/validate_4.rs +++ b/src/test/mir-opt/validate_4.rs @@ -48,11 +48,11 @@ fn main() { // } // END rustc.write_42.EraseRegions.after.mir // START rustc.write_42-{{closure}}.EraseRegions.after.mir -// fn write_42::{{closure}}(_1: &ReErased [closure@NodeId(22)], _2: *mut i32) -> () { +// fn write_42::{{closure}}(_1: &ReErased [closure@NodeId(32)], _2: *mut i32) -> () { // ... // bb0: { -// Validate(Acquire, [_1: &ReFree(DefId(0/1:9 ~ validate_4[317d]::write_42[0]::{{closure}}[0]), BrEnv) [closure@NodeId(22)], _2: *mut i32]); -// Validate(Release, [_1: &ReFree(DefId(0/1:9 ~ validate_4[317d]::write_42[0]::{{closure}}[0]), BrEnv) [closure@NodeId(22)], _2: *mut i32]); +// Validate(Acquire, [_1: &ReFree(DefId(0/1:9 ~ validate_4[317d]::write_42[0]::{{closure}}[0]), BrEnv) [closure@NodeId(32)], _2: *mut i32]); +// Validate(Release, [_1: &ReFree(DefId(0/1:9 ~ validate_4[317d]::write_42[0]::{{closure}}[0]), BrEnv) [closure@NodeId(32)], _2: *mut i32]); // (*_2) = const 23i32; // _0 = (); // return; @@ -76,11 +76,11 @@ fn main() { // } // END rustc.test.EraseRegions.after.mir // START rustc.main-{{closure}}.EraseRegions.after.mir -// fn main::{{closure}}(_1: &ReErased [closure@NodeId(60)], _2: &ReErased mut i32) -> bool { +// fn main::{{closure}}(_1: &ReErased [closure@NodeId(80)], _2: &ReErased mut i32) -> bool { // ... // bb0: { -// Validate(Acquire, [_1: &ReFree(DefId(0/1:10 ~ validate_4[317d]::main[0]::{{closure}}[0]), BrEnv) [closure@NodeId(60)], _2: &ReFree(DefId(0/1:10 ~ validate_4[317d]::main[0]::{{closure}}[0]), BrAnon(0)) mut i32]); -// Validate(Release, [_1: &ReFree(DefId(0/1:10 ~ validate_4[317d]::main[0]::{{closure}}[0]), BrEnv) [closure@NodeId(60)], _2: &ReFree(DefId(0/1:10 ~ validate_4[317d]::main[0]::{{closure}}[0]), BrAnon(0)) mut i32]); +// Validate(Acquire, [_1: &ReFree(DefId(0/1:10 ~ validate_4[317d]::main[0]::{{closure}}[0]), BrEnv) [closure@NodeId(80)], _2: &ReFree(DefId(0/1:10 ~ validate_4[317d]::main[0]::{{closure}}[0]), BrAnon(0)) mut i32]); +// Validate(Release, [_1: &ReFree(DefId(0/1:10 ~ validate_4[317d]::main[0]::{{closure}}[0]), BrEnv) [closure@NodeId(80)], _2: &ReFree(DefId(0/1:10 ~ validate_4[317d]::main[0]::{{closure}}[0]), BrAnon(0)) mut i32]); // StorageLive(_3); // ... // _0 = const write_42(move _3) -> bb1; diff --git a/src/test/mir-opt/validate_5.rs b/src/test/mir-opt/validate_5.rs index b4d4479bab94a..955de0c3bad04 100644 --- a/src/test/mir-opt/validate_5.rs +++ b/src/test/mir-opt/validate_5.rs @@ -46,19 +46,19 @@ fn main() { // } // END rustc.test.EraseRegions.after.mir // START rustc.main-{{closure}}.EraseRegions.after.mir -// fn main::{{closure}}(_1: &ReErased [closure@NodeId(46)], _2: &ReErased mut i32) -> bool { +// fn main::{{closure}}(_1: &ReErased [closure@NodeId(62)], _2: &ReErased mut i32) -> bool { // ... // bb0: { -// Validate(Acquire, [_1: &ReFree(DefId(0/1:9 ~ validate_5[317d]::main[0]::{{closure}}[0]), BrEnv) [closure@NodeId(46)], _2: &ReFree(DefId(0/1:9 ~ validate_5[317d]::main[0]::{{closure}}[0]), BrAnon(0)) mut i32]); +// Validate(Acquire, [_1: &ReFree(DefId(0/1:9 ~ validate_5[317d]::main[0]::{{closure}}[0]), BrEnv) [closure@NodeId(62)], _2: &ReFree(DefId(0/1:9 ~ validate_5[317d]::main[0]::{{closure}}[0]), BrAnon(0)) mut i32]); // StorageLive(_3); // StorageLive(_4); // StorageLive(_5); -// Validate(Suspend(ReScope(Node(ItemLocalId(12)))), [(*_2): i32]); +// Validate(Suspend(ReScope(Node(ItemLocalId(16)))), [(*_2): i32]); // _5 = &ReErased mut (*_2); -// Validate(Acquire, [(*_5): i32/ReScope(Node(ItemLocalId(12)))]); +// Validate(Acquire, [(*_5): i32/ReScope(Node(ItemLocalId(16)))]); // _4 = move _5 as *mut i32 (Misc); // _3 = move _4; -// EndRegion(ReScope(Node(ItemLocalId(12)))); +// EndRegion(ReScope(Node(ItemLocalId(16)))); // StorageDead(_4); // StorageDead(_5); // Validate(Release, [_0: bool, _3: *mut i32]); From 14bf3476bb4d9c1a5e4ec0547d8a6a8408dad5ca Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 29 Oct 2018 21:06:27 +1300 Subject: [PATCH 12/31] Adjust Ids of path segments in visibility modifiers Fixes #55376 --- src/librustc/hir/lowering.rs | 8 +++++++- src/librustc/hir/map/collector.rs | 2 +- src/test/run-pass/issue-55376.rs | 25 +++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 src/test/run-pass/issue-55376.rs diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 9795c0cba6154..c3c65816b2615 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -3022,8 +3022,14 @@ impl<'a> LoweringContext<'a> { hir::VisibilityKind::Inherited => hir::VisibilityKind::Inherited, hir::VisibilityKind::Restricted { ref path, id: _, hir_id: _ } => { let id = this.next_id(); + let mut path = path.clone(); + for seg in path.segments.iter_mut() { + if seg.id.is_some() { + seg.id = Some(this.next_id().node_id); + } + } hir::VisibilityKind::Restricted { - path: path.clone(), + path, id: id.node_id, hir_id: id.hir_id, } diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 8c701d9e4188f..4fbcd83adb555 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -217,7 +217,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { }; bug!("inconsistent DepNode for `{}`: \ - current_dep_node_owner={} ({:?}), hir_id.owner={} ({:?}) {}", + current_dep_node_owner={} ({:?}), hir_id.owner={} ({:?}){}", node_str, self.definitions .def_path(self.current_dep_node_owner) diff --git a/src/test/run-pass/issue-55376.rs b/src/test/run-pass/issue-55376.rs new file mode 100644 index 0000000000000..9c7256fd26fed --- /dev/null +++ b/src/test/run-pass/issue-55376.rs @@ -0,0 +1,25 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Tests that paths in `pub(...)` don't fail HIR verification. + +#![allow(unused_imports)] +#![allow(dead_code)] + +pub(self) use self::my_mod::Foo; + +mod my_mod { + pub(super) use self::Foo as Bar; + pub(in super::my_mod) use self::Foo as Baz; + + pub struct Foo; +} + +fn main() {} From beb61b49750bc2a056ec0b271986b3b880369ba1 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 31 Oct 2018 11:56:11 +1300 Subject: [PATCH 13/31] save analysis: don't dump macro refs --- src/librustc_save_analysis/dump_visitor.rs | 26 ++++++++++++---------- src/librustc_save_analysis/json_dumper.rs | 2 +- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index c0b718e4863fc..5cc5566b814fd 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -92,7 +92,7 @@ pub struct DumpVisitor<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> { // we only write one macro def per unique macro definition, and // one macro use per unique callsite span. // mac_defs: FxHashSet, - macro_calls: FxHashSet, + // macro_calls: FxHashSet, } impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { @@ -108,7 +108,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { span: span_utils, cur_scope: CRATE_NODE_ID, // mac_defs: FxHashSet::default(), - macro_calls: FxHashSet::default(), + // macro_calls: FxHashSet::default(), } } @@ -1031,18 +1031,20 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { /// If the span is not macro-generated, do nothing, else use callee and /// callsite spans to record macro definition and use data, using the /// mac_uses and mac_defs sets to prevent multiples. - fn process_macro_use(&mut self, span: Span) { - let source_span = span.source_callsite(); - if !self.macro_calls.insert(source_span) { - return; - } + fn process_macro_use(&mut self, _span: Span) { + // FIXME if we're not dumping the defs (see below), there is no point + // dumping refs either. + // let source_span = span.source_callsite(); + // if !self.macro_calls.insert(source_span) { + // return; + // } - let data = match self.save_ctxt.get_macro_use_data(span) { - None => return, - Some(data) => data, - }; + // let data = match self.save_ctxt.get_macro_use_data(span) { + // None => return, + // Some(data) => data, + // }; - self.dumper.macro_use(data); + // self.dumper.macro_use(data); // FIXME write the macro def // let mut hasher = DefaultHasher::new(); diff --git a/src/librustc_save_analysis/json_dumper.rs b/src/librustc_save_analysis/json_dumper.rs index e14ac73ee1020..d2354f38e2685 100644 --- a/src/librustc_save_analysis/json_dumper.rs +++ b/src/librustc_save_analysis/json_dumper.rs @@ -93,7 +93,7 @@ impl<'b, O: DumpOutput + 'b> JsonDumper { self.result.compilation = Some(data); } - pub fn macro_use(&mut self, data: MacroRef) { + pub fn _macro_use(&mut self, data: MacroRef) { if self.config.pub_only || self.config.reachable_only { return; } From 92012608cb9ee7748298de97062a8800a003007b Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 31 Oct 2018 11:05:58 +1300 Subject: [PATCH 14/31] save-analysis: make sure we save the def for the last segment of a path --- src/librustc/hir/lowering.rs | 11 ++++------- src/librustc_resolve/lib.rs | 22 +++++++++++++--------- src/librustc_save_analysis/dump_visitor.rs | 3 +-- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index c3c65816b2615..b6621e0962cf6 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1754,7 +1754,6 @@ impl<'a> LoweringContext<'a> { &mut self, def: Def, p: &Path, - ident: Option, param_mode: ParamMode, explicit_owner: Option, ) -> hir::Path { @@ -1773,7 +1772,6 @@ impl<'a> LoweringContext<'a> { explicit_owner, ) }) - .chain(ident.map(|ident| hir::PathSegment::from_ident(ident))) .collect(), span: p.span, } @@ -1781,7 +1779,7 @@ impl<'a> LoweringContext<'a> { fn lower_path(&mut self, id: NodeId, p: &Path, param_mode: ParamMode) -> hir::Path { let def = self.expect_full_def(id); - self.lower_path_extra(def, p, None, param_mode, None) + self.lower_path_extra(def, p, param_mode, None) } fn lower_path_segment( @@ -3014,7 +3012,7 @@ impl<'a> LoweringContext<'a> { self.with_hir_id_owner(new_node_id, |this| { let new_id = this.lower_node_id(new_node_id); let path = - this.lower_path_extra(def, &path, None, ParamMode::Explicit, None); + this.lower_path_extra(def, &path, ParamMode::Explicit, None); let item = hir::ItemKind::Use(P(path), hir::UseKind::Single); let vis_kind = match vis.node { hir::VisibilityKind::Public => hir::VisibilityKind::Public, @@ -3053,7 +3051,7 @@ impl<'a> LoweringContext<'a> { } let path = - P(self.lower_path_extra(ret_def, &path, None, ParamMode::Explicit, None)); + P(self.lower_path_extra(ret_def, &path, ParamMode::Explicit, None)); hir::ItemKind::Use(path, hir::UseKind::Single) } UseTreeKind::Glob => { @@ -3140,7 +3138,7 @@ impl<'a> LoweringContext<'a> { // the stability of `use a::{};`, to avoid it showing up as // a re-export by accident when `pub`, e.g. in documentation. let def = self.expect_full_def_from_use(id).next().unwrap_or(Def::Err); - let path = P(self.lower_path_extra(def, &prefix, None, ParamMode::Explicit, None)); + let path = P(self.lower_path_extra(def, &prefix, ParamMode::Explicit, None)); *vis = respan(prefix.span.shrink_to_lo(), hir::VisibilityKind::Inherited); hir::ItemKind::Use(path, hir::UseKind::ListStem) } @@ -4550,7 +4548,6 @@ impl<'a> LoweringContext<'a> { path: P(self.lower_path_extra( def, path, - None, ParamMode::Explicit, explicit_owner, )), diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index f8e3a479611d2..abd34ce8e7ee2 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -3727,7 +3727,17 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { ); for (i, &Segment { ident, id }) in path.iter().enumerate() { - debug!("resolve_path ident {} {:?}", i, ident); + debug!("resolve_path ident {} {:?} {:?}", i, ident, id); + let record_segment_def = |this: &mut Self, def| { + if record_used { + if let Some(id) = id { + if !this.def_map.contains_key(&id) { + assert!(id != ast::DUMMY_NODE_ID, "Trying to resolve dummy id"); + this.record_def(id, PathResolution::new(def)); + } + } + } + }; let is_last = i == path.len() - 1; let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS }; @@ -3812,6 +3822,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { // we found a local variable or type param Some(LexicalScopeBinding::Def(def)) if opt_ns == Some(TypeNS) || opt_ns == Some(ValueNS) => { + record_segment_def(self, def); return PathResult::NonModule(PathResolution::with_unresolved_segments( def, path.len() - 1 )); @@ -3829,14 +3840,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { let maybe_assoc = opt_ns != Some(MacroNS) && PathSource::Type.is_expected(def); if let Some(next_module) = binding.module() { module = Some(ModuleOrUniformRoot::Module(next_module)); - if record_used { - if let Some(id) = id { - if !self.def_map.contains_key(&id) { - assert!(id != ast::DUMMY_NODE_ID, "Trying to resolve dummy id"); - self.record_def(id, PathResolution::new(def)); - } - } - } + record_segment_def(self, def); } else if def == Def::ToolMod && i + 1 != path.len() { let def = Def::NonMacroAttr(NonMacroAttrKind::Tool); return PathResult::NonModule(PathResolution::new(def)); diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 5cc5566b814fd..9bc3fbe7c245a 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -771,8 +771,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { } fn process_path(&mut self, id: NodeId, path: &'l ast::Path) { - debug!("process_path {:?}", path); - if generated_code(path.span) { + if self.span.filter_generated(path.span) { return; } self.dump_path_ref(id, path); From 0af02602c287e4b1782736867d27902a6e4b2a43 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 14 Nov 2018 10:56:45 +1300 Subject: [PATCH 15/31] save-analysis: be even more aggressive about ignorning macro-generated defs --- src/librustc_save_analysis/dump_visitor.rs | 12 +++++++----- src/librustc_save_analysis/span_utils.rs | 6 +----- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 9bc3fbe7c245a..c65cd6a5ba74d 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -658,11 +658,13 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { impl_items: &'l [ast::ImplItem], ) { if let Some(impl_data) = self.save_ctxt.get_item_data(item) { - if let super::Data::RelationData(rel, imp) = impl_data { - self.dumper.dump_relation(rel); - self.dumper.dump_impl(imp); - } else { - span_bug!(item.span, "unexpected data kind: {:?}", impl_data); + if !self.span.filter_generated(item.span) { + if let super::Data::RelationData(rel, imp) = impl_data { + self.dumper.dump_relation(rel); + self.dumper.dump_impl(imp); + } else { + span_bug!(item.span, "unexpected data kind: {:?}", impl_data); + } } } self.visit_ty(&typ); diff --git a/src/librustc_save_analysis/span_utils.rs b/src/librustc_save_analysis/span_utils.rs index 902353da13f76..06b4f33b5db3e 100644 --- a/src/librustc_save_analysis/span_utils.rs +++ b/src/librustc_save_analysis/span_utils.rs @@ -124,14 +124,10 @@ impl<'a> SpanUtils<'a> { /// Used to filter out spans of minimal value, /// such as references to macro internal variables. pub fn filter_generated(&self, span: Span) -> bool { - if span.is_dummy() { + if generated_code(span) { return true; } - if !generated_code(span) { - return false; - } - //If the span comes from a fake source_file, filter it. !self.sess .source_map() From 396e009020613cba4e5e5995993fa15381818231 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 19 Nov 2018 16:28:57 +1300 Subject: [PATCH 16/31] save-analysis: fallback to using path id --- src/librustc_save_analysis/lib.rs | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 7689406b59a04..82c4795a29d4b 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -688,11 +688,24 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } } - pub fn get_path_data(&self, _id: NodeId, path: &ast::Path) -> Option { - path.segments.last().and_then(|seg| self.get_path_segment_data(seg)) + pub fn get_path_data(&self, id: NodeId, path: &ast::Path) -> Option { + path.segments + .last() + .and_then(|seg| { + self.get_path_segment_data(seg) + .or_else(|| self.get_path_segment_data_with_id(seg, id)) + }) } pub fn get_path_segment_data(&self, path_seg: &ast::PathSegment) -> Option { + self.get_path_segment_data_with_id(path_seg, path_seg.id) + } + + fn get_path_segment_data_with_id( + &self, + path_seg: &ast::PathSegment, + id: NodeId, + ) -> Option { // Returns true if the path is function type sugar, e.g., `Fn(A) -> B`. fn fn_type(seg: &ast::PathSegment) -> bool { if let Some(ref generic_args) = seg.args { @@ -703,11 +716,11 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { false } - if path_seg.id == DUMMY_NODE_ID { + if id == DUMMY_NODE_ID { return None; } - let def = self.get_path_def(path_seg.id); + let def = self.get_path_def(id); let span = path_seg.ident.span; filter!(self.span_utils, span); let span = self.span_from_span(span); From 90580ca5e30bbbe1ccc1d9f0cd93c6e71da6b401 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Sun, 11 Nov 2018 21:05:09 +0100 Subject: [PATCH 17/31] save-analysis: Don't panic for macro-generated use globs Follow-up to https://github.com/rust-lang/rust/commit/c2bb7cadf24e82b80f403c09e800fe5fad504caf. --- src/librustc_save_analysis/dump_visitor.rs | 34 ++++++++++++---------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index c65cd6a5ba74d..15c8861eb3f1f 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1256,21 +1256,25 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { Vec::new() }; - let sub_span = - self.span.sub_span_of_token(use_tree.span, token::BinOp(token::Star)); - if !self.span.filter_generated(use_tree.span) { - let span = - self.span_from_span(sub_span.expect("No span found for use glob")); - self.dumper.import(&access, Import { - kind: ImportKind::GlobUse, - ref_id: None, - span, - alias_span: None, - name: "*".to_owned(), - value: names.join(", "), - parent, - }); - self.write_sub_paths(&path); + // Otherwise it's a span with wrong macro expansion info, which + // we don't want to track anyway, since it's probably macro-internal `use` + if let Some(sub_span) = + self.span.sub_span_of_token(use_tree.span, token::BinOp(token::Star)) + { + if !self.span.filter_generated(use_tree.span) { + let span = self.span_from_span(sub_span); + + self.dumper.import(&access, Import { + kind: ImportKind::GlobUse, + ref_id: None, + span, + alias_span: None, + name: "*".to_owned(), + value: names.join(", "), + parent, + }); + self.write_sub_paths(&path); + } } } ast::UseTreeKind::Nested(ref nested_items) => { From ddeb85f4cb34c9affb39ba8e9826243d128777c6 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 19 Nov 2018 14:22:41 -0800 Subject: [PATCH 18/31] Add temporary renames to manifests for rustfmt/clippy This will be part of our strategy for shipping renamed versions of these components for the Rust 2018 edition. Closes #55967 --- src/tools/build-manifest/src/main.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index f81964ccbc23c..0a39135ad8a76 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -360,6 +360,8 @@ impl Builder { self.package("lldb-preview", &mut manifest.pkg, TARGETS); manifest.renames.insert("rls".to_owned(), Rename { to: "rls-preview".to_owned() }); + manifest.renames.insert("rustfmt".to_owned(), Rename { to: "rustfmt-preview".to_owned() }); + manifest.renames.insert("clippy".to_owned(), Rename { to: "clippy-preview".to_owned() }); let mut pkg = Package { version: self.cached_version("rust") From c8feb633dffbaa4853168a0dd1416e22bc1d124a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= Date: Sun, 18 Nov 2018 21:39:23 +0300 Subject: [PATCH 19/31] revert --- src/libcore/iter/mod.rs | 82 ++++----------------------------------- src/libcore/tests/iter.rs | 7 +--- 2 files changed, 9 insertions(+), 80 deletions(-) diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index c42fb7019c771..509068843d193 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -319,10 +319,9 @@ use cmp; use fmt; use iter_private::TrustedRandomAccess; -use ops::{self, Try}; +use ops::Try; use usize; use intrinsics; -use mem; #[stable(feature = "rust1", since = "1.0.0")] pub use self::iterator::Iterator; @@ -673,7 +672,12 @@ impl Iterator for StepBy where I: Iterator { #[inline] fn next(&mut self) -> Option { - ::spec_next(self) + if self.first_take { + self.first_take = false; + self.iter.next() + } else { + self.iter.nth(self.step) + } } #[inline] @@ -733,78 +737,6 @@ impl Iterator for StepBy where I: Iterator { } } -// hidden trait for specializing iterator methods -// could be generalized but is currently only used for StepBy -trait StepBySpecIterator { - type Item; - fn spec_next(&mut self) -> Option; -} - -impl StepBySpecIterator for StepBy -where - I: Iterator, -{ - type Item = I::Item; - - #[inline] - default fn spec_next(&mut self) -> Option { - if self.first_take { - self.first_take = false; - self.iter.next() - } else { - self.iter.nth(self.step) - } - } -} - -impl StepBySpecIterator for StepBy> -where - T: Step, -{ - #[inline] - fn spec_next(&mut self) -> Option { - self.first_take = false; - if !(self.iter.start < self.iter.end) { - return None; - } - // add 1 to self.step to get original step size back - // it was decremented for the general case on construction - if let Some(n) = self.iter.start.add_usize(self.step+1) { - let next = mem::replace(&mut self.iter.start, n); - Some(next) - } else { - let last = self.iter.start.clone(); - self.iter.start = self.iter.end.clone(); - Some(last) - } - } -} - -impl StepBySpecIterator for StepBy> -where - T: Step, -{ - #[inline] - fn spec_next(&mut self) -> Option { - self.first_take = false; - self.iter.compute_is_empty(); - if self.iter.is_empty.unwrap_or_default() { - return None; - } - // add 1 to self.step to get original step size back - // it was decremented for the general case on construction - if let Some(n) = self.iter.start.add_usize(self.step+1) { - self.iter.is_empty = Some(!(n <= self.iter.end)); - let next = mem::replace(&mut self.iter.start, n); - Some(next) - } else { - let last = self.iter.start.clone(); - self.iter.is_empty = Some(true); - Some(last) - } - } -} - // StepBy can only make the iterator shorter, so the len will still fit. #[stable(feature = "iterator_step_by", since = "1.28.0")] impl ExactSizeIterator for StepBy where I: ExactSizeIterator {} diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 2476c07cbd9ca..fcf7f0cd5d705 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -1619,11 +1619,8 @@ fn test_range_step() { } #[test] -fn test_range_inclusive_step() { - assert_eq!((0..=50).step_by(10).collect::>(), [0, 10, 20, 30, 40, 50]); - assert_eq!((0..=5).step_by(1).collect::>(), [0, 1, 2, 3, 4, 5]); - assert_eq!((200..=255u8).step_by(10).collect::>(), [200, 210, 220, 230, 240, 250]); - assert_eq!((250..=255u8).step_by(1).collect::>(), [250, 251, 252, 253, 254, 255]); +fn test_step_by_skip() { + assert_eq!((0..640).step_by(128).skip(1).collect::>(), [128, 256, 384, 512]); } #[test] From 224eb8325ee3a226bc4cb9eb9cada1e00e583d8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= Date: Sun, 18 Nov 2018 23:14:52 +0300 Subject: [PATCH 20/31] tests --- src/libcore/tests/iter.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index fcf7f0cd5d705..b9452e65ae3bd 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -1621,6 +1621,16 @@ fn test_range_step() { #[test] fn test_step_by_skip() { assert_eq!((0..640).step_by(128).skip(1).collect::>(), [128, 256, 384, 512]); + assert_eq!((0..=50).step_by(10).nth(3), Some(30)); + assert_eq!((250..=255u8).step_by(10).nth(3), Some(230)); +} + +#[test] +fn test_range_inclusive_step() { + assert_eq!((0..=50).step_by(10).collect::>(), [0, 10, 20, 30, 40, 50]); + assert_eq!((0..=5).step_by(1).collect::>(), [0, 1, 2, 3, 4, 5]); + assert_eq!((200..=255u8).step_by(10).collect::>(), [200, 210, 220, 230, 240, 250]); + assert_eq!((250..=255u8).step_by(1).collect::>(), [250, 251, 252, 253, 254, 255]); } #[test] From beaf59f79b9f758e61c789b8a647de69573e53a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= Date: Mon, 19 Nov 2018 01:01:06 +0300 Subject: [PATCH 21/31] fix test --- src/libcore/tests/iter.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index b9452e65ae3bd..ec09071b3d0f0 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -1622,7 +1622,7 @@ fn test_range_step() { fn test_step_by_skip() { assert_eq!((0..640).step_by(128).skip(1).collect::>(), [128, 256, 384, 512]); assert_eq!((0..=50).step_by(10).nth(3), Some(30)); - assert_eq!((250..=255u8).step_by(10).nth(3), Some(230)); + assert_eq!((200..=255u8).step_by(10).nth(3), Some(230)); } #[test] From a830c06e18a7e529eae2794d35059a3de45dcf12 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Thu, 15 Nov 2018 16:16:34 +0100 Subject: [PATCH 22/31] Fix stability hole with `static _` --- src/libsyntax/feature_gate.rs | 1 + .../ui/underscore_const_names_feature_gate.rs | 14 ++++++++++++++ ...underscore_const_names_feature_gate.stderr | 19 +++++++++++++++++++ 3 files changed, 34 insertions(+) create mode 100644 src/test/ui/underscore_const_names_feature_gate.rs create mode 100644 src/test/ui/underscore_const_names_feature_gate.stderr diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 2cd4fd92bc81e..c1b2e796d8234 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1591,6 +1591,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } } + ast::ItemKind::Static(..) | ast::ItemKind::Const(_,_) => { if i.ident.name == "_" { gate_feature_post!(&self, underscore_const_names, i.span, diff --git a/src/test/ui/underscore_const_names_feature_gate.rs b/src/test/ui/underscore_const_names_feature_gate.rs new file mode 100644 index 0000000000000..b2174036dede0 --- /dev/null +++ b/src/test/ui/underscore_const_names_feature_gate.rs @@ -0,0 +1,14 @@ +// Copyright 2012-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +const _: () = (); //~ ERROR is unstable +static _: () = (); //~ ERROR is unstable + +fn main() {} diff --git a/src/test/ui/underscore_const_names_feature_gate.stderr b/src/test/ui/underscore_const_names_feature_gate.stderr new file mode 100644 index 0000000000000..4cce252bcaed7 --- /dev/null +++ b/src/test/ui/underscore_const_names_feature_gate.stderr @@ -0,0 +1,19 @@ +error[E0658]: naming constants with `_` is unstable (see issue #54912) + --> $DIR/underscore_const_names_feature_gate.rs:11:1 + | +LL | const _: () = (); + | ^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(underscore_const_names)] to the crate attributes to enable + +error[E0658]: naming constants with `_` is unstable (see issue #54912) + --> $DIR/underscore_const_names_feature_gate.rs:12:1 + | +LL | static _: () = (); + | ^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(underscore_const_names)] to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. From 46dd614f55ebb96f00b61de125c6eb81f30cd21a Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 16 Nov 2018 09:04:35 +0100 Subject: [PATCH 23/31] Update stderr file --- src/test/ui/underscore_const_names_feature_gate.stderr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/underscore_const_names_feature_gate.stderr b/src/test/ui/underscore_const_names_feature_gate.stderr index 4cce252bcaed7..c97b3f8d4d3cd 100644 --- a/src/test/ui/underscore_const_names_feature_gate.stderr +++ b/src/test/ui/underscore_const_names_feature_gate.stderr @@ -1,7 +1,7 @@ error[E0658]: naming constants with `_` is unstable (see issue #54912) --> $DIR/underscore_const_names_feature_gate.rs:11:1 | -LL | const _: () = (); +LL | const _: () = (); //~ ERROR is unstable | ^^^^^^^^^^^^^^^^^ | = help: add #![feature(underscore_const_names)] to the crate attributes to enable @@ -9,7 +9,7 @@ LL | const _: () = (); error[E0658]: naming constants with `_` is unstable (see issue #54912) --> $DIR/underscore_const_names_feature_gate.rs:12:1 | -LL | static _: () = (); +LL | static _: () = (); //~ ERROR is unstable | ^^^^^^^^^^^^^^^^^^ | = help: add #![feature(underscore_const_names)] to the crate attributes to enable From feede07f33dc02bd6ee5a9351d876f1a7bd9a0e5 Mon Sep 17 00:00:00 2001 From: Aaron Power Date: Sun, 4 Nov 2018 17:48:30 +0000 Subject: [PATCH 24/31] Updated RELEASES.md for 1.31.0 --- RELEASES.md | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index 21134d50bdcc8..d16a50cd0b64a 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,76 @@ +Version 1.31.0 (2018-12-06) +========================== + +Language +-------- +- 🎉 [This version marks the release of the 2018 edition of Rust.][54057] 🎉 +- [New lifetime elision rules now allow for eliding lifetimes in functions and + impl headers.][54778] E.g. `impl<'a> Reader for BufReader<'a> {}` can now be + `impl Reader for BufReader<'_> {}`. Lifetimes are still required to be defined + in structs. +- [You can now define and use `const` functions.][54835] These are currently + a strict minimal subset of the [const fn RFC][RFC-911]. Refer to the + [language reference][const-reference] for what exactly is available. +- [You can now use tool lints, which allow you to scope lints from external + tools using attributes.][54870] E.g. `#[allow(clippy::filter_map)]`. +- [`#[no_mangle]` and `#[export_name]` attributes can now be located anywhere in + a crate, not just in exported functions.][54451] +- [You can now use parentheses in pattern matches.][54497] + +Compiler +-------- +- [Updated musl to 1.1.20][54430] + +Libraries +--------- +- [You can now convert `num::NonZero*` types to their raw equivalvents using the + `From` trait.][54240] E.g. `u8` now implements `From`. +- [You can now convert a `&Option` into `Option<&T>` and `&mut Option` + into `Option<&mut T>` using the `From` trait.][53218] +- [You can now multiply (`*`) a `time::Duration` by a `u32`.][52813] + + +Stabilized APIs +--------------- +- [`slice::align_to`] +- [`slice::align_to_mut`] +- [`slice::chunks_exact`] +- [`slice::chunks_exact_mut`] +- [`slice::rchunks`] +- [`slice::rchunks_mut`] +- [`slice::rchunks_exact`] +- [`slice::rchunks_exact_mut`] +- [`Option::replace`] + +Cargo +----- +- [Cargo will now download crates in parallel using HTTP/2.][cargo/6005] + +[52813]: https://github.com/rust-lang/rust/pull/52813/ +[53218]: https://github.com/rust-lang/rust/pull/53218/ +[53555]: https://github.com/rust-lang/rust/issues/53555/ +[54057]: https://github.com/rust-lang/rust/pull/54057/ +[54240]: https://github.com/rust-lang/rust/pull/54240/ +[54430]: https://github.com/rust-lang/rust/pull/54430/ +[54451]: https://github.com/rust-lang/rust/pull/54451/ +[54497]: https://github.com/rust-lang/rust/pull/54497/ +[54778]: https://github.com/rust-lang/rust/pull/54778/ +[54835]: https://github.com/rust-lang/rust/pull/54835/ +[54870]: https://github.com/rust-lang/rust/pull/54870/ +[RFC-911]: https://github.com/rust-lang/rfcs/pull/911 +[`Option::replace`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.replace +[`slice::align_to_mut`]: https://doc.rust-lang.org/std/primitive.slice.html#method.align_to_mut +[`slice::align_to`]: https://doc.rust-lang.org/std/primitive.slice.html#method.align_to +[`slice::chunks_exact_mut`]: https://doc.rust-lang.org/std/primitive.slice.html#method.chunks_exact_mut +[`slice::chunks_exact`]: https://doc.rust-lang.org/std/primitive.slice.html#method.chunks_exact +[`slice::rchunks_exact_mut`]: https://doc.rust-lang.org/std/primitive.slice.html#method.rchunks_mut +[`slice::rchunks_exact`]: https://doc.rust-lang.org/std/primitive.slice.html#method.rchunks_exact +[`slice::rchunks_mut`]: https://doc.rust-lang.org/std/primitive.slice.html#method.rchunks_mut +[`slice::rchunks`]: https://doc.rust-lang.org/std/primitive.slice.html#method.rchunks +[cargo/6005]: https://github.com/rust-lang/cargo/pull/6005/ +[const-reference]: https://doc.rust-lang.org/reference/items/functions.html#const-functions + + Version 1.30.0 (2018-10-25) ========================== From 74bcc4c55523ba51154eb03a32a4a84fdf104108 Mon Sep 17 00:00:00 2001 From: Aaron Power Date: Tue, 20 Nov 2018 10:47:28 +0100 Subject: [PATCH 25/31] Update releases to add rename dependencies feature --- RELEASES.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index d16a50cd0b64a..fc76fbc95bd3b 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -45,6 +45,8 @@ Stabilized APIs Cargo ----- - [Cargo will now download crates in parallel using HTTP/2.][cargo/6005] +- [You can now rename packages in your Cargo.toml][cargo/6319] We have a guide + on [how to use the `package` key in your dependencies.][cargo-rename-reference] [52813]: https://github.com/rust-lang/rust/pull/52813/ [53218]: https://github.com/rust-lang/rust/pull/53218/ @@ -68,6 +70,8 @@ Cargo [`slice::rchunks_mut`]: https://doc.rust-lang.org/std/primitive.slice.html#method.rchunks_mut [`slice::rchunks`]: https://doc.rust-lang.org/std/primitive.slice.html#method.rchunks [cargo/6005]: https://github.com/rust-lang/cargo/pull/6005/ +[cargo/6319]: https://github.com/rust-lang/cargo/pull/6319/ +[cargo-rename-reference]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#renaming-dependencies-in-cargotoml [const-reference]: https://doc.rust-lang.org/reference/items/functions.html#const-functions From 01e090d685ddf000b850a8e476b5011c260540d2 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Mon, 22 Oct 2018 00:12:16 -0400 Subject: [PATCH 26/31] Fix Rustdoc ICE when checking blanket impls Fixes #55001, #54744 Previously, SelectionContext would unconditionally cache the selection result for an obligation. This worked fine for most users of SelectionContext, but it caused an issue when used by Rustdoc's blanket impl finder. The issue occured when SelectionContext chose a ParamCandidate which contained inference variables. Since inference variables can change between calls to select(), it's not safe to cache the selection result - the chosen candidate might not be applicable for future results, leading to an ICE when we try to run confirmation. This commit prevents SelectionContext from caching any ParamCandidate that contains inference variables. This should always be completely safe, as trait selection should never depend on a particular result being cached. I've also added some extra debug!() statements, which I found helpful in tracking down this bug. --- src/librustc/infer/combine.rs | 10 +++++++- src/librustc/infer/equate.rs | 3 +++ src/librustc/traits/select.rs | 35 ++++++++++++++++++++++++++++ src/librustdoc/clean/blanket_impl.rs | 11 +++++++-- src/test/rustdoc/issue-55001.rs | 31 ++++++++++++++++++++++++ 5 files changed, 87 insertions(+), 3 deletions(-) create mode 100644 src/test/rustdoc/issue-55001.rs diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs index de8f57ee79666..0ee03bc4c6e00 100644 --- a/src/librustc/infer/combine.rs +++ b/src/librustc/infer/combine.rs @@ -251,6 +251,7 @@ impl<'infcx, 'gcx, 'tcx> CombineFields<'infcx, 'gcx, 'tcx> { dir: RelationDir) -> RelateResult<'tcx, Generalization<'tcx>> { + debug!("generalize(ty={:?}, for_vid={:?}, dir={:?}", ty, for_vid, dir); // Determine the ambient variance within which `ty` appears. // The surrounding equation is: // @@ -273,8 +274,15 @@ impl<'infcx, 'gcx, 'tcx> CombineFields<'infcx, 'gcx, 'tcx> { root_ty: ty, }; - let ty = generalize.relate(&ty, &ty)?; + let ty = match generalize.relate(&ty, &ty) { + Ok(ty) => ty, + Err(e) => { + debug!("generalize: failure {:?}", e); + return Err(e); + } + }; let needs_wf = generalize.needs_wf; + debug!("generalize: success {{ {:?}, {:?} }}", ty, needs_wf); Ok(Generalization { ty, needs_wf }) } } diff --git a/src/librustc/infer/equate.rs b/src/librustc/infer/equate.rs index 854960492c9bd..c7b5ddb83410f 100644 --- a/src/librustc/infer/equate.rs +++ b/src/librustc/infer/equate.rs @@ -74,6 +74,9 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx> let infcx = self.fields.infcx; let a = infcx.type_variables.borrow_mut().replace_if_possible(a); let b = infcx.type_variables.borrow_mut().replace_if_possible(b); + + debug!("{}.tys: replacements ({:?}, {:?})", self.tag(), a, b); + match (&a.sty, &b.sty) { (&ty::Infer(TyVar(a_id)), &ty::Infer(TyVar(b_id))) => { infcx.type_variables.borrow_mut().equate(a_id, b_id); diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 49f3717935493..2ea16823cc65d 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1522,6 +1522,33 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { .map(|v| v.get(tcx)) } + /// Determines whether can we safely cache the result + /// of selecting an obligation. This is almost always 'true', + /// except when dealing with certain ParamCandidates. + /// + /// Ordinarily, a ParamCandidate will contain no inference variables, + /// since it was usually produced directly from a DefId. However, + /// certain cases (currently only librustdoc's blanket impl finder), + /// a ParamEnv may be explicitly constructed with inference types. + /// When this is the case, we do *not* want to cache the resulting selection + /// candidate. This is due to the fact that it might not always be possible + /// to equate the obligation's trait ref and the candidate's trait ref, + /// if more constraints end up getting added to an inference variable. + /// + /// Because of this, we always want to re-run the full selection + /// process for our obligation the next time we see it, since + /// we might end up picking a different SelectionCandidate (or none at all) + fn can_cache_candidate(&self, + result: &SelectionResult<'tcx, SelectionCandidate<'tcx>> + ) -> bool { + match result { + Ok(Some(SelectionCandidate::ParamCandidate(trait_ref))) => { + !trait_ref.skip_binder().input_types().any(|t| t.walk().any(|t_| t_.is_ty_infer())) + }, + _ => true + } + } + fn insert_candidate_cache( &mut self, param_env: ty::ParamEnv<'tcx>, @@ -1531,6 +1558,14 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ) { let tcx = self.tcx(); let trait_ref = cache_fresh_trait_pred.skip_binder().trait_ref; + + if !self.can_cache_candidate(&candidate) { + debug!("insert_candidate_cache(trait_ref={:?}, candidate={:?} -\ + candidate is not cacheable", trait_ref, candidate); + return; + + } + if self.can_use_global_caches(param_env) { if let Err(Overflow) = candidate { // Don't cache overflow globally; we only produce this diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index 858685ef00e37..8246c7bab27af 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -50,6 +50,7 @@ impl<'a, 'tcx, 'rcx, 'cstore> BlanketImplFinder <'a, 'tcx, 'rcx, 'cstore> { name: Option, ) -> Vec where F: Fn(DefId) -> Def { + debug!("get_blanket_impls(def_id={:?}, ...)", def_id); let mut impls = Vec::new(); if self.cx .tcx @@ -78,6 +79,8 @@ impl<'a, 'tcx, 'rcx, 'cstore> BlanketImplFinder <'a, 'tcx, 'rcx, 'cstore> { } self.cx.tcx.for_each_relevant_impl(trait_def_id, ty, |impl_def_id| { self.cx.tcx.infer_ctxt().enter(|infcx| { + debug!("get_blanet_impls: Considering impl for trait '{:?}' {:?}", + trait_def_id, impl_def_id); let t_generics = infcx.tcx.generics_of(impl_def_id); let trait_ref = infcx.tcx.impl_trait_ref(impl_def_id) .expect("Cannot get impl trait"); @@ -104,8 +107,8 @@ impl<'a, 'tcx, 'rcx, 'cstore> BlanketImplFinder <'a, 'tcx, 'rcx, 'cstore> { drop(obligations); debug!( - "invoking predicate_may_hold: {:?}", - trait_ref, + "invoking predicate_may_hold: param_env={:?}, trait_ref={:?}, ty={:?}", + param_env, trait_ref, ty ); let may_apply = match infcx.evaluate_obligation( &traits::Obligation::new( @@ -117,6 +120,10 @@ impl<'a, 'tcx, 'rcx, 'cstore> BlanketImplFinder <'a, 'tcx, 'rcx, 'cstore> { Ok(eval_result) => eval_result.may_apply(), Err(traits::OverflowError) => true, // overflow doesn't mean yes *or* no }; + debug!("get_blanket_impls: found applicable impl: {}\ + for trait_ref={:?}, ty={:?}", + may_apply, trait_ref, ty); + if !may_apply { return } diff --git a/src/test/rustdoc/issue-55001.rs b/src/test/rustdoc/issue-55001.rs new file mode 100644 index 0000000000000..f6c7f9a3d082c --- /dev/null +++ b/src/test/rustdoc/issue-55001.rs @@ -0,0 +1,31 @@ +// Regression test for issue #55001. Previously, we would incorrectly +// cache certain trait selection results when checking for blanket impls, +// resulting in an ICE when we tried to confirm the cached ParamCandidate +// against an obligation. + +pub struct DefaultAllocator; +pub struct Standard; +pub struct Inner; + +pub trait Rand {} + +pub trait Distribution {} +pub trait Allocator {} + +impl Rand for T where Standard: Distribution {} + +impl Distribution> for Standard +where +DefaultAllocator: Allocator, +Standard: Distribution {} + +impl Distribution for Standard {} + + +pub struct Point +where DefaultAllocator: Allocator +{ + field: N +} + +fn main() {} From 0f84c8ef8f61b9e845cbdbe3668d626ca79b3594 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 20 Nov 2018 13:48:12 -0800 Subject: [PATCH 27/31] Update clippy module to fix breakage --- src/tools/clippy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/clippy b/src/tools/clippy index b1d0343749bdc..246a77ebe8c9d 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit b1d0343749bdc87e5cbbe7f1aeaa9d2a2c9dbc5b +Subproject commit 246a77ebe8c9d640c76a82f3869c5272ba51346d From 5ea8c58c2dca1cbfe8701bf03517c6bfd254b06b Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 20 Nov 2018 16:51:56 -0500 Subject: [PATCH 28/31] Update RLS and Rustfmt --- src/Cargo.lock | 153 ++++++++++++++++++++++++++-------------------- src/tools/rls | 2 +- src/tools/rustfmt | 2 +- 3 files changed, 89 insertions(+), 68 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 98529bdab3ffd..7e845e3634b25 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -617,12 +617,13 @@ dependencies = [ [[package]] name = "derive_more" -version = "0.11.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.21 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -724,7 +725,7 @@ name = "failure_derive" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1315,7 +1316,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1565,7 +1566,7 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "0.4.13" +version = "0.4.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1644,23 +1645,23 @@ name = "quote" version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "racer" -version = "2.1.9" +version = "2.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "derive_more 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1782,7 +1783,7 @@ dependencies = [ [[package]] name = "rls" -version = "0.130.5" +version = "1.31.6" dependencies = [ "cargo 0.32.0", "cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1797,20 +1798,20 @@ dependencies = [ "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "ordslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "racer 2.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "racer 2.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-analysis 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-blacklist 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rls-analysis 0.16.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rls-blacklist 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "rls-data 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", "rls-rustc 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-vfs 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rls-vfs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0", "rustc_tools_util 0.1.0", - "rustfmt-nightly 0.99.6", + "rustfmt-nightly 1.0.0", "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1821,7 +1822,7 @@ dependencies = [ [[package]] name = "rls-analysis" -version = "0.16.1" +version = "0.16.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1836,7 +1837,7 @@ dependencies = [ [[package]] name = "rls-blacklist" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1867,9 +1868,10 @@ dependencies = [ [[package]] name = "rls-vfs" -version = "0.4.6" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1916,15 +1918,20 @@ dependencies = [ [[package]] name = "rustc-ap-arena" -version = "274.0.0" +version = "297.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rustc-ap-graphviz" +version = "297.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "rustc-ap-rustc_cratesio_shim" -version = "274.0.0" +version = "297.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1934,7 +1941,7 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_data_structures" -version = "274.0.0" +version = "297.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1942,8 +1949,9 @@ dependencies = [ "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-graphviz 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1953,33 +1961,34 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_errors" -version = "274.0.0" +version = "297.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_target" -version = "274.0.0" +version = "297.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-serialize" -version = "274.0.0" +version = "297.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1987,29 +1996,29 @@ dependencies = [ [[package]] name = "rustc-ap-syntax" -version = "274.0.0" +version = "297.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax_pos" -version = "274.0.0" +version = "297.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-arena 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-arena 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2507,7 +2516,7 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "0.99.6" +version = "1.0.0" dependencies = [ "assert_cli 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2522,9 +2531,9 @@ dependencies = [ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0", "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2601,7 +2610,7 @@ name = "serde_derive" version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2744,7 +2753,7 @@ name = "strum_macros" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2774,7 +2783,17 @@ name = "syn" version = "0.14.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "0.15.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2792,7 +2811,7 @@ name = "synstructure" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3218,7 +3237,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum curl-sys 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "08459503c415173da1ce6b41036a37b8bfdd86af46d45abb9964d4c61fe670ef" "checksum datafrog 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "16d724bf4ffe77cdceeecd461009b5f8d9e23c5d645d68bedb4586bf43e7e142" "checksum derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ceed73957c449214f8440eec8ad7fa282b67dc9eacbb24a3085b15d60397a17a" -"checksum derive_more 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46c7f14685a20f5dd08e7f754f2ea8cc064d8f4214ae21116c106a2768ba7b9b" +"checksum derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f57d78cf3bd45270dad4e70c21ec77a960b36c7a841ff9db76aaa775a8fb871" "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" @@ -3320,7 +3339,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" "checksum pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6" "checksum proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1b06e2f335f48d24442b35a19df506a835fb3547bc3c06ef27340da9acf5cae7" -"checksum proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "ee5697238f0d893c7f0ecc59c0999f18d2af85e424de441178bcacc9f9e6cf67" +"checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09" "checksum proptest 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)" = "926d0604475349f463fe44130aae73f2294b5309ab2ca0310b998bd334ef191f" "checksum pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdf85cda6cadfae5428a54661d431330b312bc767ddbc57adbedc24da66e32" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" @@ -3328,7 +3347,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8" "checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5" -"checksum racer 2.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "5eeddfffd44c83eb03eedf5eb336e9c75303534fe28728a9f6b39a6e6f07ccff" +"checksum racer 2.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "344a53b68d889ab5f44d0617f2bbe1f696abe6a730bd41fa619cfc6fa83a6078" "checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" "checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" "checksum rand_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edecf0f94da5551fc9b492093e30b041a891657db7940ee221f9d2f66e82eef2" @@ -3341,20 +3360,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7" "checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" -"checksum rls-analysis 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9a625690e3bf1204ce27b50f71e508ee788214b2d51e26e4e5db884a83627673" -"checksum rls-blacklist 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e4a9cc2545ccb7e05b355bfe047b8039a6ec12270d5f3c996b766b340a50f7d2" +"checksum rls-analysis 0.16.8 (registry+https://github.com/rust-lang/crates.io-index)" = "2a1d3a2a8c03e380331aefb8b5e3e06f3065602fbaa6657ba0ac649dc99d8537" +"checksum rls-blacklist 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b8ce1fdac03e138c4617ff87b194e1ff57a39bb985a044ccbd8673d30701e411" "checksum rls-data 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a209ce46bb52813cbe0786a7baadc0c1a3f5543ef93f179eda3b841ed72cf2e" "checksum rls-rustc 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9dba7390427aefa953608429701e3665192ca810ba8ae09301e001b7c7bed0" "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a" -"checksum rls-vfs 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ecbc8541b4c341d6271eae10f869dd9d36db871afe184f5b6f9bffbd6ed0373f" -"checksum rustc-ap-arena 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "866fda692855b38f9d6562f0e952c75c6ebe4032d7dd63c608a88e7c4d3f8087" -"checksum rustc-ap-rustc_cratesio_shim 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6c2343e11a97b4eb3bee29cd5f9314ea409a87baee5d3fec8d1516d1633412e" -"checksum rustc-ap-rustc_data_structures 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b88f905f7ab99bf14220a3a87eff60ec143af8136fd0ca8573641c78be532ec8" -"checksum rustc-ap-rustc_errors 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c86fda6cf42e0355b7ecf40f14888340c20b7b864c9d37f6ffca85fe87200652" -"checksum rustc-ap-rustc_target 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8fa8622299beac8c40270e8536a7b0509ca80f227a2b56550019a325fa5a60c0" -"checksum rustc-ap-serialize 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d16cc3d014af9a524c0bed6ca806c3170e39d5987180f0f8ce8fb7df5113576c" -"checksum rustc-ap-syntax 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2a29f280f04f4f45e1bdd773ab5e667b36e757bfbbd01193c330815b9e76d05a" -"checksum rustc-ap-syntax_pos 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c2ea27b65311571c7614deb393691eb18c5e41fd4fd9d8490304e128e1358646" +"checksum rls-vfs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "72d56425bd5aa86d9d4372b76f0381d3b4bda9c0220e71956c9fcc929f45c1f1" +"checksum rustc-ap-arena 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b69fd4a0e8a3ecd99b497965d05f6f04dd2e4601a6146a841dbe4c8e77c2b30c" +"checksum rustc-ap-graphviz 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8136418dbc491bab74aa0565eaa2086754a7a81a5e74a1d84d6168d18e889e7" +"checksum rustc-ap-rustc_cratesio_shim 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a972feda82332d1d05b1ba5a097e915cd9c9c8f1af2bd7b08af09fb88c753d5f" +"checksum rustc-ap-rustc_data_structures 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "582584c6c48b0ece4b8aef3f9bb59d94d17c5665612bc87a71f509e45a3113b5" +"checksum rustc-ap-rustc_errors 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cd852096944d0ac6af1aefa9639a2ae6dede217606ce97f88ff0dcc8c86d6ff6" +"checksum rustc-ap-rustc_target 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98301a272ecfeec29d2d4e97b07238707c2b89d86fc3a4a5f31a00728f14e288" +"checksum rustc-ap-serialize 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f13510e617e2e322e3297038fd6a7346f2297124af9e10e33a627c5d544e9d" +"checksum rustc-ap-syntax 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0792f5a9ccfc5ec13bb5b0472fa49e145481029c39f6bf5b1a36decc99c3328f" +"checksum rustc-ap-syntax_pos 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0df9f97f41650d23b14f92f7267f8c61089655efb4533d82bf8991f99245198d" "checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395" "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" "checksum rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c6d5a683c6ba4ed37959097e88d71c9e8e26659a3cb5be8b389078e7ad45306" @@ -3390,6 +3410,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" "checksum syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)" = "14f9bf6292f3a61d2c716723fdb789a41bbe104168e6f496dc6497e531ea1b9b" "checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" +"checksum syn 0.15.21 (registry+https://github.com/rust-lang/crates.io-index)" = "816b7af21405b011a23554ea2dc3f6576dc86ca557047c34098c1d741f10f823" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85bb9b7550d063ea184027c9b8c20ac167cd36d3e06b3a40bceb9d746dc1a7b7" "checksum tar 0.4.16 (registry+https://github.com/rust-lang/crates.io-index)" = "e8f41ca4a5689f06998f0247fcb60da6c760f1950cc9df2a10d71575ad0b062a" diff --git a/src/tools/rls b/src/tools/rls index 1c755efed6ee2..daa138ce7f222 160000 --- a/src/tools/rls +++ b/src/tools/rls @@ -1 +1 @@ -Subproject commit 1c755efed6ee265c762f4d3fec73de8a989637a5 +Subproject commit daa138ce7f222559e9a339600b44a715101a3f4d diff --git a/src/tools/rustfmt b/src/tools/rustfmt index 750b25261380b..1cc61cfc2b29a 160000 --- a/src/tools/rustfmt +++ b/src/tools/rustfmt @@ -1 +1 @@ -Subproject commit 750b25261380b776de2518fd6863fe63f98d2722 +Subproject commit 1cc61cfc2b29ae3f29a924b4c8feb1bcb09aa5fc From 8129c413f24aa99b2d2b6744200f8004a292a244 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 20 Nov 2018 14:03:20 -0800 Subject: [PATCH 29/31] Update the `cargo_metadata` dependency Needed by rustfmt! --- src/Cargo.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 7e845e3634b25..8533fde98e4af 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -253,7 +253,7 @@ dependencies = [ [[package]] name = "cargo_metadata" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -323,7 +323,7 @@ dependencies = [ name = "clippy" version = "0.0.212" dependencies = [ - "cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "clippy-mini-macro-test 0.2.0", "clippy_dev 0.0.1", "clippy_lints 0.0.212", @@ -357,7 +357,7 @@ dependencies = [ name = "clippy_lints" version = "0.0.212" dependencies = [ - "cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "if_chain 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1289,7 +1289,7 @@ name = "miri" version = "0.1.0" dependencies = [ "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "compiletest_rs 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1786,7 +1786,7 @@ name = "rls" version = "1.31.6" dependencies = [ "cargo 0.32.0", - "cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "clippy_lints 0.0.212", "crossbeam-channel 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2521,7 +2521,7 @@ dependencies = [ "assert_cli 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "bytecount 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3210,7 +3210,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum bytecount 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f861d9ce359f56dbcb6e0c2a1cb84e52ad732cadb57b806adeb3c7668caccbd8" "checksum byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "74c0b906e9446b0a2e4f760cdb3fa4b2c48cdc6db8766a845c54b6ff063fd2e9" "checksum bytesize 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "716960a18f978640f25101b5cbf1c6f6b0d3192fab36a2d98ca96f0ecbe41010" -"checksum cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d6809b327f87369e6f3651efd2c5a96c49847a3ed2559477ecba79014751ee1" +"checksum cargo_metadata 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d8dfe3adeb30f7938e6c1dd5327f29235d8ada3e898aeb08c343005ec2915a2" "checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16" "checksum cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4e7bb64a8ebb0d856483e1e682ea3422f883c5f5615a90d51a2c82fe87fdd3" "checksum chalk-engine 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9adbe0fe1d6e937c3ee0571739a78f53c1de22f59df616060e868cf13c6c4ce5" From e6c93e7717269c88980224d86349ecb68ad8eae2 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 17 Nov 2018 21:08:00 +0300 Subject: [PATCH 30/31] Stabilize `extern_crate_item_prelude` --- src/librustc_resolve/lib.rs | 12 +-- src/librustc_resolve/macros.rs | 5 +- src/librustc_resolve/resolve_imports.rs | 2 +- src/libsyntax/feature_gate.rs | 5 +- .../extern-prelude-extern-crate-proc-macro.rs | 2 - .../feature-gate-extern_crate_item_prelude.rs | 46 ------------ ...ture-gate-extern_crate_item_prelude.stderr | 75 ------------------- ...-prelude-extern-crate-absolute-expanded.rs | 2 - .../extern-prelude-extern-crate-cfg.rs | 1 - .../extern-prelude-extern-crate-pass.rs | 2 - ...elude-extern-crate-restricted-shadowing.rs | 2 - ...e-extern-crate-restricted-shadowing.stderr | 4 +- 12 files changed, 9 insertions(+), 149 deletions(-) delete mode 100644 src/test/ui/feature-gates/feature-gate-extern_crate_item_prelude.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-extern_crate_item_prelude.stderr diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index abd34ce8e7ee2..4eb8a285aeccb 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -58,7 +58,6 @@ use syntax::ast::{self, Name, NodeId, Ident, FloatTy, IntTy, UintTy}; use syntax::ext::base::SyntaxExtension; use syntax::ext::base::Determinacy::{self, Determined, Undetermined}; use syntax::ext::base::MacroKind; -use syntax::feature_gate::{emit_feature_err, GateIssue}; use syntax::symbol::{Symbol, keywords}; use syntax::util::lev_distance::find_best_match_for_name; @@ -2120,7 +2119,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { if !module.no_implicit_prelude { if ns == TypeNS { - if let Some(binding) = self.extern_prelude_get(ident, !record_used, false) { + if let Some(binding) = self.extern_prelude_get(ident, !record_used) { return Some(LexicalScopeBinding::Item(binding)); } } @@ -5035,7 +5034,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { self.name_already_seen.insert(name, span); } - fn extern_prelude_get(&mut self, ident: Ident, speculative: bool, skip_feature_gate: bool) + fn extern_prelude_get(&mut self, ident: Ident, speculative: bool) -> Option<&'a NameBinding<'a>> { if ident.is_path_segment_keyword() { // Make sure `self`, `super` etc produce an error when passed to here. @@ -5043,13 +5042,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { } self.extern_prelude.get(&ident.modern()).cloned().and_then(|entry| { if let Some(binding) = entry.extern_crate_item { - if !speculative && !skip_feature_gate && entry.introduced_by_item && - !self.session.features_untracked().extern_crate_item_prelude { - emit_feature_err(&self.session.parse_sess, "extern_crate_item_prelude", - ident.span, GateIssue::Language, - "use of extern prelude names introduced \ - with `extern crate` items is unstable"); - } Some(binding) } else { let crate_id = if !speculative { diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 352b50768e654..df73befa324f0 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -738,8 +738,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { } WhereToResolve::ExternPrelude => { if use_prelude { - match self.extern_prelude_get(ident, !record_used, - innermost_result.is_some()) { + match self.extern_prelude_get(ident, !record_used) { Some(binding) => Ok((binding, Flags::PRELUDE)), None => Err(Determinacy::determined( self.graph_root.unresolved_invocations.borrow().is_empty() @@ -906,7 +905,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { // but its `Def` should coincide with a crate passed with `--extern` // (otherwise there would be ambiguity) and we can skip feature error in this case. if ns != TypeNS || !use_prelude || - self.extern_prelude_get(ident, true, false).is_none() { + self.extern_prelude_get(ident, true).is_none() { let msg = "imports can only refer to extern crate names \ passed with `--extern` on stable channel"; let mut err = feature_err(&self.session.parse_sess, "uniform_paths", diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 87a9b97344ad5..b4490ea05f5a4 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -167,7 +167,7 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> { match uniform_root_kind { UniformRootKind::ExternPrelude => { return if let Some(binding) = - self.extern_prelude_get(ident, !record_used, false) { + self.extern_prelude_get(ident, !record_used) { Ok(binding) } else if !self.graph_root.unresolved_invocations.borrow().is_empty() { // Macro-expanded `extern crate` items can add names to extern prelude. diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index c1b2e796d8234..55e9c3c298c5d 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -501,9 +501,6 @@ declare_features! ( // Allows `const _: TYPE = VALUE` (active, underscore_const_names, "1.31.0", Some(54912), None), - - // `extern crate foo as bar;` puts `bar` into extern prelude. - (active, extern_crate_item_prelude, "1.31.0", Some(54658), None), ); declare_features! ( @@ -689,6 +686,8 @@ declare_features! ( // impl Iterator for &mut Iterator // impl Debug for Foo<'_> (accepted, impl_header_lifetime_elision, "1.31.0", Some(15872), None), + // `extern crate foo as bar;` puts `bar` into extern prelude. + (accepted, extern_crate_item_prelude, "1.31.0", Some(55599), None), ); // If you change this, please modify src/doc/unstable-book as well. You must diff --git a/src/test/ui-fulldeps/proc-macro/extern-prelude-extern-crate-proc-macro.rs b/src/test/ui-fulldeps/proc-macro/extern-prelude-extern-crate-proc-macro.rs index e320ad9713542..25a2a37614778 100644 --- a/src/test/ui-fulldeps/proc-macro/extern-prelude-extern-crate-proc-macro.rs +++ b/src/test/ui-fulldeps/proc-macro/extern-prelude-extern-crate-proc-macro.rs @@ -1,8 +1,6 @@ // compile-pass // edition:2018 -#![feature(extern_crate_item_prelude)] - extern crate proc_macro; use proc_macro::TokenStream; // OK diff --git a/src/test/ui/feature-gates/feature-gate-extern_crate_item_prelude.rs b/src/test/ui/feature-gates/feature-gate-extern_crate_item_prelude.rs deleted file mode 100644 index 27b9a34ff4eb7..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-extern_crate_item_prelude.rs +++ /dev/null @@ -1,46 +0,0 @@ -// edition:2018 - -#![feature(alloc, underscore_imports)] - -extern crate alloc; - -mod in_scope { - fn check() { - let v = alloc::vec![0]; - //~^ ERROR use of extern prelude names introduced with `extern crate` items is unstable - type A = alloc::boxed::Box; - //~^ ERROR use of extern prelude names introduced with `extern crate` items is unstable - } -} - -mod absolute { - fn check() { - let v = ::alloc::vec![0]; - //~^ ERROR use of extern prelude names introduced with `extern crate` items is unstable - type A = ::alloc::boxed::Box; - //~^ ERROR use of extern prelude names introduced with `extern crate` items is unstable - } -} - -mod import_in_scope { - use alloc as _; - //~^ ERROR use of extern prelude names introduced with `extern crate` items is unstable - use alloc::boxed; - //~^ ERROR use of extern prelude names introduced with `extern crate` items is unstable -} - -mod import_absolute { - use ::alloc; - //~^ ERROR use of extern prelude names introduced with `extern crate` items is unstable - use ::alloc::boxed; - //~^ ERROR use of extern prelude names introduced with `extern crate` items is unstable -} - -extern crate alloc as core; - -mod unrelated_crate_renamed { - type A = core::boxed::Box; - //~^ ERROR use of extern prelude names introduced with `extern crate` items is unstable -} - -fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-extern_crate_item_prelude.stderr b/src/test/ui/feature-gates/feature-gate-extern_crate_item_prelude.stderr deleted file mode 100644 index ac65dcb4d54fc..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-extern_crate_item_prelude.stderr +++ /dev/null @@ -1,75 +0,0 @@ -error[E0658]: use of extern prelude names introduced with `extern crate` items is unstable (see issue #54658) - --> $DIR/feature-gate-extern_crate_item_prelude.rs:26:9 - | -LL | use alloc as _; - | ^^^^^ - | - = help: add #![feature(extern_crate_item_prelude)] to the crate attributes to enable - -error[E0658]: use of extern prelude names introduced with `extern crate` items is unstable (see issue #54658) - --> $DIR/feature-gate-extern_crate_item_prelude.rs:28:9 - | -LL | use alloc::boxed; - | ^^^^^ - | - = help: add #![feature(extern_crate_item_prelude)] to the crate attributes to enable - -error[E0658]: use of extern prelude names introduced with `extern crate` items is unstable (see issue #54658) - --> $DIR/feature-gate-extern_crate_item_prelude.rs:33:11 - | -LL | use ::alloc; - | ^^^^^ - | - = help: add #![feature(extern_crate_item_prelude)] to the crate attributes to enable - -error[E0658]: use of extern prelude names introduced with `extern crate` items is unstable (see issue #54658) - --> $DIR/feature-gate-extern_crate_item_prelude.rs:35:11 - | -LL | use ::alloc::boxed; - | ^^^^^ - | - = help: add #![feature(extern_crate_item_prelude)] to the crate attributes to enable - -error[E0658]: use of extern prelude names introduced with `extern crate` items is unstable (see issue #54658) - --> $DIR/feature-gate-extern_crate_item_prelude.rs:9:17 - | -LL | let v = alloc::vec![0]; - | ^^^^^ - | - = help: add #![feature(extern_crate_item_prelude)] to the crate attributes to enable - -error[E0658]: use of extern prelude names introduced with `extern crate` items is unstable (see issue #54658) - --> $DIR/feature-gate-extern_crate_item_prelude.rs:11:18 - | -LL | type A = alloc::boxed::Box; - | ^^^^^ - | - = help: add #![feature(extern_crate_item_prelude)] to the crate attributes to enable - -error[E0658]: use of extern prelude names introduced with `extern crate` items is unstable (see issue #54658) - --> $DIR/feature-gate-extern_crate_item_prelude.rs:18:19 - | -LL | let v = ::alloc::vec![0]; - | ^^^^^ - | - = help: add #![feature(extern_crate_item_prelude)] to the crate attributes to enable - -error[E0658]: use of extern prelude names introduced with `extern crate` items is unstable (see issue #54658) - --> $DIR/feature-gate-extern_crate_item_prelude.rs:20:20 - | -LL | type A = ::alloc::boxed::Box; - | ^^^^^ - | - = help: add #![feature(extern_crate_item_prelude)] to the crate attributes to enable - -error[E0658]: use of extern prelude names introduced with `extern crate` items is unstable (see issue #54658) - --> $DIR/feature-gate-extern_crate_item_prelude.rs:42:14 - | -LL | type A = core::boxed::Box; - | ^^^^ - | - = help: add #![feature(extern_crate_item_prelude)] to the crate attributes to enable - -error: aborting due to 9 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/imports/extern-prelude-extern-crate-absolute-expanded.rs b/src/test/ui/imports/extern-prelude-extern-crate-absolute-expanded.rs index b1154f2076b80..cf91a9714ade0 100644 --- a/src/test/ui/imports/extern-prelude-extern-crate-absolute-expanded.rs +++ b/src/test/ui/imports/extern-prelude-extern-crate-absolute-expanded.rs @@ -1,8 +1,6 @@ // compile-pass // edition:2018 -#![feature(extern_crate_item_prelude)] - macro_rules! define_iso { () => { extern crate std as iso; }} diff --git a/src/test/ui/imports/extern-prelude-extern-crate-cfg.rs b/src/test/ui/imports/extern-prelude-extern-crate-cfg.rs index c48a65798b6c1..6117e5f6f3cd7 100644 --- a/src/test/ui/imports/extern-prelude-extern-crate-cfg.rs +++ b/src/test/ui/imports/extern-prelude-extern-crate-cfg.rs @@ -1,7 +1,6 @@ // compile-pass // compile-flags:--cfg my_feature -#![feature(extern_crate_item_prelude)] #![no_std] #[cfg(my_feature)] diff --git a/src/test/ui/imports/extern-prelude-extern-crate-pass.rs b/src/test/ui/imports/extern-prelude-extern-crate-pass.rs index 8c147dfd04a3c..bb4cf6ca99c75 100644 --- a/src/test/ui/imports/extern-prelude-extern-crate-pass.rs +++ b/src/test/ui/imports/extern-prelude-extern-crate-pass.rs @@ -1,8 +1,6 @@ // compile-pass // aux-build:two_macros.rs -#![feature(extern_crate_item_prelude)] - extern crate two_macros; mod m { diff --git a/src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.rs b/src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.rs index 732f1c4de2fb3..3eefaf1267e88 100644 --- a/src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.rs +++ b/src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.rs @@ -1,7 +1,5 @@ // aux-build:two_macros.rs -#![feature(extern_crate_item_prelude)] - macro_rules! define_vec { () => { extern crate std as Vec; diff --git a/src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.stderr b/src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.stderr index 218dfb796f77a..325a47b19e8fb 100644 --- a/src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.stderr +++ b/src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.stderr @@ -1,12 +1,12 @@ error[E0659]: `Vec` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) - --> $DIR/extern-prelude-extern-crate-restricted-shadowing.rs:15:9 + --> $DIR/extern-prelude-extern-crate-restricted-shadowing.rs:13:9 | LL | Vec::panic!(); //~ ERROR `Vec` is ambiguous | ^^^ ambiguous name | = note: `Vec` could refer to a struct from prelude note: `Vec` could also refer to the extern crate imported here - --> $DIR/extern-prelude-extern-crate-restricted-shadowing.rs:7:9 + --> $DIR/extern-prelude-extern-crate-restricted-shadowing.rs:5:9 | LL | extern crate std as Vec; | ^^^^^^^^^^^^^^^^^^^^^^^^ From 93704f2f975efed3a764a5dbab8c4afc66049ece Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 18 Nov 2018 01:52:07 +0300 Subject: [PATCH 31/31] Add a couple more tests --- ...tern-prelude-extern-crate-restricted-shadowing.rs | 9 +++++++++ ...-prelude-extern-crate-restricted-shadowing.stderr | 11 ++++++++++- .../imports/extern-prelude-extern-crate-shadowing.rs | 12 ++++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/imports/extern-prelude-extern-crate-shadowing.rs diff --git a/src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.rs b/src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.rs index 3eefaf1267e88..6ff3ab73639c0 100644 --- a/src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.rs +++ b/src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.rs @@ -14,4 +14,13 @@ mod m { } } +macro_rules! define_other_core { + () => { + extern crate std as core; + //~^ ERROR macro-expanded `extern crate` items cannot shadow names passed with `--extern` + } +} + +define_other_core!(); + fn main() {} diff --git a/src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.stderr b/src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.stderr index 325a47b19e8fb..795e1761ccdb3 100644 --- a/src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.stderr +++ b/src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.stderr @@ -1,3 +1,12 @@ +error: macro-expanded `extern crate` items cannot shadow names passed with `--extern` + --> $DIR/extern-prelude-extern-crate-restricted-shadowing.rs:19:9 + | +LL | extern crate std as core; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | define_other_core!(); + | --------------------- in this macro invocation + error[E0659]: `Vec` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) --> $DIR/extern-prelude-extern-crate-restricted-shadowing.rs:13:9 | @@ -14,6 +23,6 @@ LL | extern crate std as Vec; LL | define_vec!(); | -------------- in this macro invocation -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/imports/extern-prelude-extern-crate-shadowing.rs b/src/test/ui/imports/extern-prelude-extern-crate-shadowing.rs new file mode 100644 index 0000000000000..c5adeaf17fa92 --- /dev/null +++ b/src/test/ui/imports/extern-prelude-extern-crate-shadowing.rs @@ -0,0 +1,12 @@ +// compile-pass +// aux-build:two_macros.rs + +extern crate two_macros as core; + +mod m { + fn check() { + core::m!(); // OK + } +} + +fn main() {}