From 600607f45a400e5930126b5ef1dc05f5644e95c3 Mon Sep 17 00:00:00 2001 From: varkor Date: Sun, 20 Oct 2019 17:16:58 +0100 Subject: [PATCH 01/23] Move `search_for_adt_without_structural_match` to `ty/mod` --- src/librustc/ty/mod.rs | 117 ++++++++++++++++++++++++- src/librustc_mir/hair/pattern/mod.rs | 122 +-------------------------- 2 files changed, 116 insertions(+), 123 deletions(-) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index d377b7328e80b..77d8141c9688c 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -4,7 +4,7 @@ pub use self::Variance::*; pub use self::AssocItemContainer::*; pub use self::BorrowKind::*; pub use self::IntVarValue::*; -pub use self::fold::TypeFoldable; +pub use self::fold::{TypeFoldable, TypeVisitor}; use crate::hir::{map as hir_map, GlobMap, TraitMap}; use crate::hir::Node; @@ -50,7 +50,7 @@ use syntax::symbol::{kw, sym, Symbol, InternedString}; use syntax_pos::Span; use smallvec; -use rustc_data_structures::fx::FxIndexMap; +use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::stable_hasher::{StableHasher, HashStable}; use rustc_index::vec::{Idx, IndexVec}; @@ -3393,6 +3393,119 @@ fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync { fn_like.asyncness() } +/// This method traverses the structure of `ty`, trying to find an +/// instance of an ADT (i.e. struct or enum) that was declared without +/// the `#[structural_match]` attribute. +/// +/// The "structure of a type" includes all components that would be +/// considered when doing a pattern match on a constant of that +/// type. +/// +/// * This means this method descends into fields of structs/enums, +/// and also descends into the inner type `T` of `&T` and `&mut T` +/// +/// * The traversal doesn't dereference unsafe pointers (`*const T`, +/// `*mut T`), and it does not visit the type arguments of an +/// instantiated generic like `PhantomData`. +/// +/// The reason we do this search is Rust currently require all ADTs +/// reachable from a constant's type to be annotated with +/// `#[structural_match]`, an attribute which essentially says that +/// the implementation of `PartialEq::eq` behaves *equivalently* to a +/// comparison against the unfolded structure. +/// +/// For more background on why Rust has this requirement, and issues +/// that arose when the requirement was not enforced completely, see +/// Rust RFC 1445, rust-lang/rust#61188, and rust-lang/rust#62307. +pub fn search_for_adt_without_structural_match<'tcx>(tcx: TyCtxt<'tcx>, + ty: Ty<'tcx>) + -> Option<&'tcx AdtDef> +{ + let mut search = Search { tcx, found: None, seen: FxHashSet::default() }; + ty.visit_with(&mut search); + return search.found; + + struct Search<'tcx> { + tcx: TyCtxt<'tcx>, + + // records the first ADT we find without `#[structural_match` + found: Option<&'tcx AdtDef>, + + // tracks ADT's previously encountered during search, so that + // we will not recur on them again. + seen: FxHashSet, + } + + impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { + debug!("Search visiting ty: {:?}", ty); + + let (adt_def, substs) = match ty.kind { + ty::Adt(adt_def, substs) => (adt_def, substs), + ty::RawPtr(..) => { + // `#[structural_match]` ignores substructure of + // `*const _`/`*mut _`, so skip super_visit_with + // + // (But still tell caller to continue search.) + return false; + } + ty::FnDef(..) | ty::FnPtr(..) => { + // types of formals and return in `fn(_) -> _` are also irrelevant + // + // (But still tell caller to continue search.) + return false; + } + ty::Array(_, n) if n.try_eval_usize(self.tcx, ty::ParamEnv::reveal_all()) == Some(0) + => { + // rust-lang/rust#62336: ignore type of contents + // for empty array. + return false; + } + _ => { + ty.super_visit_with(self); + return false; + } + }; + + if !self.tcx.has_attr(adt_def.did, sym::structural_match) { + self.found = Some(&adt_def); + debug!("Search found adt_def: {:?}", adt_def); + return true // Halt visiting! + } + + if !self.seen.insert(adt_def.did) { + debug!("Search already seen adt_def: {:?}", adt_def); + // let caller continue its search + return false; + } + + // `#[structural_match]` does not care about the + // instantiation of the generics in an ADT (it + // instead looks directly at its fields outside + // this match), so we skip super_visit_with. + // + // (Must not recur on substs for `PhantomData` cf + // rust-lang/rust#55028 and rust-lang/rust#55837; but also + // want to skip substs when only uses of generic are + // behind unsafe pointers `*const T`/`*mut T`.) + + // even though we skip super_visit_with, we must recur on + // fields of ADT. + let tcx = self.tcx; + for field_ty in adt_def.all_fields().map(|field| field.ty(tcx, substs)) { + if field_ty.visit_with(self) { + // found an ADT without `#[structural_match]`; halt visiting! + assert!(self.found.is_some()); + return true; + } + } + + // Even though we do not want to recur on substs, we do + // want our caller to continue its own search. + false + } + } +} pub fn provide(providers: &mut ty::query::Providers<'_>) { context::provide(providers); diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 58480912929b3..d996881221857 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -25,7 +25,6 @@ use rustc::hir::pat_util::EnumerateAndAdjustIterator; use rustc::hir::ptr::P; use rustc_index::vec::Idx; -use rustc_data_structures::fx::FxHashSet; use std::cmp::Ordering; use std::fmt; @@ -1000,7 +999,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { if self.include_lint_checks && !saw_error { // If we were able to successfully convert the const to some pat, double-check // that the type of the const obeys `#[structural_match]` constraint. - if let Some(adt_def) = search_for_adt_without_structural_match(self.tcx, cv.ty) { + if let Some(adt_def) = ty::search_for_adt_without_structural_match(self.tcx, cv.ty) { let path = self.tcx.def_path_str(adt_def.did); let msg = format!( @@ -1169,125 +1168,6 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { } } -/// This method traverses the structure of `ty`, trying to find an -/// instance of an ADT (i.e. struct or enum) that was declared without -/// the `#[structural_match]` attribute. -/// -/// The "structure of a type" includes all components that would be -/// considered when doing a pattern match on a constant of that -/// type. -/// -/// * This means this method descends into fields of structs/enums, -/// and also descends into the inner type `T` of `&T` and `&mut T` -/// -/// * The traversal doesn't dereference unsafe pointers (`*const T`, -/// `*mut T`), and it does not visit the type arguments of an -/// instantiated generic like `PhantomData`. -/// -/// The reason we do this search is Rust currently require all ADT's -/// reachable from a constant's type to be annotated with -/// `#[structural_match]`, an attribute which essentially says that -/// the implementation of `PartialEq::eq` behaves *equivalently* to a -/// comparison against the unfolded structure. -/// -/// For more background on why Rust has this requirement, and issues -/// that arose when the requirement was not enforced completely, see -/// Rust RFC 1445, rust-lang/rust#61188, and rust-lang/rust#62307. -fn search_for_adt_without_structural_match<'tcx>(tcx: TyCtxt<'tcx>, - ty: Ty<'tcx>) - -> Option<&'tcx AdtDef> -{ - // Import here (not mod level), because `TypeFoldable::fold_with` - // conflicts with `PatternFoldable::fold_with` - use crate::rustc::ty::fold::TypeVisitor; - use crate::rustc::ty::TypeFoldable; - - let mut search = Search { tcx, found: None, seen: FxHashSet::default() }; - ty.visit_with(&mut search); - return search.found; - - struct Search<'tcx> { - tcx: TyCtxt<'tcx>, - - // records the first ADT we find without `#[structural_match` - found: Option<&'tcx AdtDef>, - - // tracks ADT's previously encountered during search, so that - // we will not recur on them again. - seen: FxHashSet, - } - - impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> { - fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { - debug!("Search visiting ty: {:?}", ty); - - let (adt_def, substs) = match ty.kind { - ty::Adt(adt_def, substs) => (adt_def, substs), - ty::RawPtr(..) => { - // `#[structural_match]` ignores substructure of - // `*const _`/`*mut _`, so skip super_visit_with - // - // (But still tell caller to continue search.) - return false; - } - ty::FnDef(..) | ty::FnPtr(..) => { - // types of formals and return in `fn(_) -> _` are also irrelevant - // - // (But still tell caller to continue search.) - return false; - } - ty::Array(_, n) if n.try_eval_usize(self.tcx, ty::ParamEnv::reveal_all()) == Some(0) - => { - // rust-lang/rust#62336: ignore type of contents - // for empty array. - return false; - } - _ => { - ty.super_visit_with(self); - return false; - } - }; - - if !self.tcx.has_attr(adt_def.did, sym::structural_match) { - self.found = Some(&adt_def); - debug!("Search found adt_def: {:?}", adt_def); - return true // Halt visiting! - } - - if !self.seen.insert(adt_def.did) { - debug!("Search already seen adt_def: {:?}", adt_def); - // let caller continue its search - return false; - } - - // `#[structural_match]` does not care about the - // instantiation of the generics in an ADT (it - // instead looks directly at its fields outside - // this match), so we skip super_visit_with. - // - // (Must not recur on substs for `PhantomData` cf - // rust-lang/rust#55028 and rust-lang/rust#55837; but also - // want to skip substs when only uses of generic are - // behind unsafe pointers `*const T`/`*mut T`.) - - // even though we skip super_visit_with, we must recur on - // fields of ADT. - let tcx = self.tcx; - for field_ty in adt_def.all_fields().map(|field| field.ty(tcx, substs)) { - if field_ty.visit_with(self) { - // found an ADT without `#[structural_match]`; halt visiting! - assert!(self.found.is_some()); - return true; - } - } - - // Even though we do not want to recur on substs, we do - // want our caller to continue its own search. - false - } - } -} - impl UserAnnotatedTyHelpers<'tcx> for PatCtxt<'_, 'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx From bbd53deaeb79e78162524e18ca29211745e2d18e Mon Sep 17 00:00:00 2001 From: varkor Date: Sun, 20 Oct 2019 17:17:12 +0100 Subject: [PATCH 02/23] Forbid non-`structural_match` types in const generics --- src/librustc_typeck/collect.rs | 11 +++++++++ src/librustc_typeck/error_codes.rs | 24 +++++++++++++++++++ .../forbid-non-structural_match-types.rs | 13 ++++++++++ .../forbid-non-structural_match-types.stderr | 17 +++++++++++++ 4 files changed, 65 insertions(+) create mode 100644 src/test/ui/const-generics/forbid-non-structural_match-types.rs create mode 100644 src/test/ui/const-generics/forbid-non-structural_match-types.stderr diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 1749fd1075e05..d6162c0bc0e9f 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1532,6 +1532,17 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option { diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index 3ecbf620cbc7b..5d1afcaef9140 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -4978,6 +4978,30 @@ the future, [RFC 2091] prohibits their implementation without a follow-up RFC. [RFC 2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md "##, +E0739: r##" +Only `structural_match` types (that is, types that derive `PartialEq` and `Eq`) +may be used as the types of const generic parameters. + +```compile_fail,E0739 +#![feature(const_generics)] + +struct A; + +struct B; // error! +``` + +To fix this example, we derive `PartialEq` and `Eq`. + +``` +#![feature(const_generics)] + +#[derive(PartialEq, Eq)] +struct A; + +struct B; // ok! +``` +"##, + ; // E0035, merged into E0087/E0089 // E0036, merged into E0087/E0089 diff --git a/src/test/ui/const-generics/forbid-non-structural_match-types.rs b/src/test/ui/const-generics/forbid-non-structural_match-types.rs new file mode 100644 index 0000000000000..7bc4f3986eb75 --- /dev/null +++ b/src/test/ui/const-generics/forbid-non-structural_match-types.rs @@ -0,0 +1,13 @@ +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +#[derive(PartialEq, Eq)] +struct A; + +struct B; // ok + +struct C; + +struct D; //~ ERROR the types of const generic parameters must derive + +fn main() {} diff --git a/src/test/ui/const-generics/forbid-non-structural_match-types.stderr b/src/test/ui/const-generics/forbid-non-structural_match-types.stderr new file mode 100644 index 0000000000000..9ab6c69521be0 --- /dev/null +++ b/src/test/ui/const-generics/forbid-non-structural_match-types.stderr @@ -0,0 +1,17 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/forbid-non-structural_match-types.rs:1:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error[E0739]: the types of const generic parameters must derive `PartialEq` and `Eq` + --> $DIR/forbid-non-structural_match-types.rs:11:19 + | +LL | struct D; + | ^ `C` doesn't derive both `PartialEq` and `Eq` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0739`. From 133cd2cfaf244c130e2e0d681090ca117bcba94e Mon Sep 17 00:00:00 2001 From: varkor Date: Sun, 20 Oct 2019 18:17:42 +0100 Subject: [PATCH 03/23] Search for generic parameters when finding non-`structural_match` types --- src/librustc/ty/mod.rs | 32 ++++++++++++------- src/librustc_mir/hair/pattern/mod.rs | 24 ++++++++------ src/librustc_typeck/collect.rs | 4 +-- src/librustc_typeck/error_codes.rs | 4 +-- .../forbid-non-structural_match-types.stderr | 4 +-- 5 files changed, 42 insertions(+), 26 deletions(-) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 77d8141c9688c..6c512a0238eed 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -3393,9 +3393,15 @@ fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync { fn_like.asyncness() } +pub enum NonStructuralMatchTy<'tcx> { + Adt(&'tcx AdtDef), + Param, +} + /// This method traverses the structure of `ty`, trying to find an /// instance of an ADT (i.e. struct or enum) that was declared without -/// the `#[structural_match]` attribute. +/// the `#[structural_match]` attribute, or a generic type parameter +/// (which cannot be determined to be `structural_match`). /// /// The "structure of a type" includes all components that would be /// considered when doing a pattern match on a constant of that @@ -3417,10 +3423,10 @@ fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync { /// For more background on why Rust has this requirement, and issues /// that arose when the requirement was not enforced completely, see /// Rust RFC 1445, rust-lang/rust#61188, and rust-lang/rust#62307. -pub fn search_for_adt_without_structural_match<'tcx>(tcx: TyCtxt<'tcx>, - ty: Ty<'tcx>) - -> Option<&'tcx AdtDef> -{ +pub fn search_for_structural_match_violation<'tcx>( + tcx: TyCtxt<'tcx>, + ty: Ty<'tcx>, +) -> Option> { let mut search = Search { tcx, found: None, seen: FxHashSet::default() }; ty.visit_with(&mut search); return search.found; @@ -3428,11 +3434,11 @@ pub fn search_for_adt_without_structural_match<'tcx>(tcx: TyCtxt<'tcx>, struct Search<'tcx> { tcx: TyCtxt<'tcx>, - // records the first ADT we find without `#[structural_match` - found: Option<&'tcx AdtDef>, + // Records the first ADT or type parameter we find without `#[structural_match`. + found: Option>, - // tracks ADT's previously encountered during search, so that - // we will not recur on them again. + // Tracks ADTs previously encountered during search, so that + // we will not recurse on them again. seen: FxHashSet, } @@ -3442,6 +3448,10 @@ pub fn search_for_adt_without_structural_match<'tcx>(tcx: TyCtxt<'tcx>, let (adt_def, substs) = match ty.kind { ty::Adt(adt_def, substs) => (adt_def, substs), + ty::Param(_) => { + self.found = Some(NonStructuralMatchTy::Param); + return true; // Stop visiting. + } ty::RawPtr(..) => { // `#[structural_match]` ignores substructure of // `*const _`/`*mut _`, so skip super_visit_with @@ -3468,9 +3478,9 @@ pub fn search_for_adt_without_structural_match<'tcx>(tcx: TyCtxt<'tcx>, }; if !self.tcx.has_attr(adt_def.did, sym::structural_match) { - self.found = Some(&adt_def); + self.found = Some(NonStructuralMatchTy::Adt(&adt_def)); debug!("Search found adt_def: {:?}", adt_def); - return true // Halt visiting! + return true; // Stop visiting. } if !self.seen.insert(adt_def.did) { diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index d996881221857..98e286e61e942 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -999,15 +999,21 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { if self.include_lint_checks && !saw_error { // If we were able to successfully convert the const to some pat, double-check // that the type of the const obeys `#[structural_match]` constraint. - if let Some(adt_def) = ty::search_for_adt_without_structural_match(self.tcx, cv.ty) { - - let path = self.tcx.def_path_str(adt_def.did); - let msg = format!( - "to use a constant of type `{}` in a pattern, \ - `{}` must be annotated with `#[derive(PartialEq, Eq)]`", - path, - path, - ); + if let Some(non_sm_ty) = ty::search_for_structural_match_violation(self.tcx, cv.ty) { + let msg = match non_sm_ty { + ty::NonStructuralMatchTy::Adt(adt_def) => { + let path = self.tcx.def_path_str(adt_def.did); + format!( + "to use a constant of type `{}` in a pattern, \ + `{}` must be annotated with `#[derive(PartialEq, Eq)]`", + path, + path, + ) + } + ty::NonStructuralMatchTy::Param => { + bug!("use of constant whose type is a parameter inside a pattern"); + } + }; // before issuing lint, double-check there even *is* a // semantic PartialEq for us to dispatch to. diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index d6162c0bc0e9f..08fb5ae1676e7 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1532,11 +1532,11 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option $DIR/forbid-non-structural_match-types.rs:11:19 | LL | struct D; @@ -14,4 +14,4 @@ LL | struct D; error: aborting due to previous error -For more information about this error, try `rustc --explain E0739`. +For more information about this error, try `rustc --explain E0740`. From f0e6cd9f89d3cdb11f417707690679fc334dfe0a Mon Sep 17 00:00:00 2001 From: varkor Date: Sun, 20 Oct 2019 18:18:24 +0100 Subject: [PATCH 04/23] Remove "type parameter depends on const parameter" error from resolution --- src/librustc_resolve/diagnostics.rs | 10 -------- src/librustc_resolve/error_codes.rs | 7 +++--- src/librustc_resolve/late.rs | 23 +------------------ src/librustc_resolve/lib.rs | 15 ++---------- ...aram-type-depends-on-type-param-ungated.rs | 2 +- ...-type-depends-on-type-param-ungated.stderr | 14 +++++------ .../const-param-type-depends-on-type-param.rs | 3 +-- ...st-param-type-depends-on-type-param.stderr | 19 ++++----------- 8 files changed, 21 insertions(+), 72 deletions(-) diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 5647d5b2794af..7634093fbefba 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -367,16 +367,6 @@ impl<'a> Resolver<'a> { span, "`Self` in type parameter default".to_string()); err } - ResolutionError::ConstParamDependentOnTypeParam => { - let mut err = struct_span_err!( - self.session, - span, - E0671, - "const parameters cannot depend on type parameters" - ); - err.span_label(span, format!("const parameter depends on type parameter")); - err - } } } diff --git a/src/librustc_resolve/error_codes.rs b/src/librustc_resolve/error_codes.rs index b82cba8c83dc4..49f8e82a2d1b5 100644 --- a/src/librustc_resolve/error_codes.rs +++ b/src/librustc_resolve/error_codes.rs @@ -1880,13 +1880,14 @@ fn main() { "##, E0671: r##" +#### Note: this error code is no longer emitted by the compiler. + Const parameters cannot depend on type parameters. The following is therefore invalid: -```compile_fail,E0671 +```compile_fail,E0740 #![feature(const_generics)] -fn const_id() -> T { // error: const parameter - // depends on type parameter +fn const_id() -> T { // error N } ``` diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 73a282b1a0ec1..136ab1f0444fa 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -111,9 +111,6 @@ crate enum RibKind<'a> { /// from the default of a type parameter because they're not declared /// before said type parameter. Also see the `visit_generics` override. ForwardTyParamBanRibKind, - - /// We forbid the use of type parameters as the types of const parameters. - TyParamAsConstParamTy, } impl RibKind<'_> { @@ -128,8 +125,7 @@ impl RibKind<'_> { | MacroDefinition(_) => false, AssocItemRibKind | ItemRibKind(_) - | ForwardTyParamBanRibKind - | TyParamAsConstParamTy => true, + | ForwardTyParamBanRibKind => true, } } } @@ -483,18 +479,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> { default_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err); } - // We also ban access to type parameters for use as the types of const parameters. - let mut const_ty_param_ban_rib = Rib::new(TyParamAsConstParamTy); - const_ty_param_ban_rib.bindings.extend(generics.params.iter() - .filter(|param| { - if let GenericParamKind::Type { .. } = param.kind { - true - } else { - false - } - }) - .map(|param| (Ident::with_dummy_span(param.ident.name), Res::Err))); - for param in &generics.params { match param.kind { GenericParamKind::Lifetime { .. } => self.visit_generic_param(param), @@ -513,15 +497,10 @@ impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> { default_ban_rib.bindings.remove(&Ident::with_dummy_span(param.ident.name)); } GenericParamKind::Const { ref ty } => { - self.ribs[TypeNS].push(const_ty_param_ban_rib); - for bound in ¶m.bounds { self.visit_param_bound(bound); } - self.visit_ty(ty); - - const_ty_param_ban_rib = self.ribs[TypeNS].pop().unwrap(); } } } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 17d8f0f211a92..1cc21a54e3cff 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -215,8 +215,6 @@ enum ResolutionError<'a> { ForwardDeclaredTyParam, // FIXME(const_generics:defaults) /// Error E0735: type parameters with a default cannot use `Self` SelfInTyParamDefault, - /// Error E0671: const parameter cannot depend on type parameter. - ConstParamDependentOnTypeParam, } // A minimal representation of a path segment. We use this in resolve because @@ -2169,15 +2167,6 @@ impl<'a> Resolver<'a> { return Res::Err; } - // An invalid use of a type parameter as the type of a const parameter. - if let TyParamAsConstParamTy = all_ribs[rib_index].kind { - if record_used { - self.report_error(span, ResolutionError::ConstParamDependentOnTypeParam); - } - assert_eq!(res, Res::Err); - return Res::Err; - } - match res { Res::Local(_) => { use ResolutionError::*; @@ -2186,7 +2175,7 @@ impl<'a> Resolver<'a> { for rib in ribs { match rib.kind { NormalRibKind | ModuleRibKind(..) | MacroDefinition(..) | - ForwardTyParamBanRibKind | TyParamAsConstParamTy => { + ForwardTyParamBanRibKind => { // Nothing to do. Continue. } ItemRibKind(_) | FnItemRibKind | AssocItemRibKind => { @@ -2220,7 +2209,7 @@ impl<'a> Resolver<'a> { let has_generic_params = match rib.kind { NormalRibKind | AssocItemRibKind | ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind | - ConstantItemRibKind | TyParamAsConstParamTy => { + ConstantItemRibKind => { // Nothing to do. Continue. continue; } diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs index af5e8f49754e8..78bd549ba791a 100644 --- a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs +++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs @@ -1,6 +1,6 @@ use std::marker::PhantomData; struct B(PhantomData<[T; N]>); //~ ERROR const generics are unstable -//~^ ERROR const parameters cannot depend on type parameters +//~^ ERROR the types of const generic parameters must derive `PartialEq` and `Eq` fn main() {} diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr index c659074a091c8..ba6f53e56840e 100644 --- a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr +++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr @@ -1,9 +1,3 @@ -error[E0671]: const parameters cannot depend on type parameters - --> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:22 - | -LL | struct B(PhantomData<[T; N]>); - | ^ const parameter depends on type parameter - error[E0658]: const generics are unstable --> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:19 | @@ -13,7 +7,13 @@ LL | struct B(PhantomData<[T; N]>); = note: for more information, see https://github.com/rust-lang/rust/issues/44580 = help: add `#![feature(const_generics)]` to the crate attributes to enable +error[E0740]: the types of const generic parameters must derive `PartialEq` and `Eq` + --> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:22 + | +LL | struct B(PhantomData<[T; N]>); + | ^ `T` doesn't derive both `PartialEq` and `Eq` + error: aborting due to 2 previous errors -Some errors have detailed explanations: E0658, E0671. +Some errors have detailed explanations: E0658, E0740. For more information about an error, try `rustc --explain E0658`. diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs b/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs index 28e0d6c2bb7e7..b76209571b05c 100644 --- a/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs +++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs @@ -7,7 +7,6 @@ // details. pub struct Dependent([(); X]); -//~^ ERROR const parameters cannot depend on type parameters -//~^^ ERROR parameter `T` is never used +//~^ ERROR the types of const generic parameters must derive `PartialEq` and `Eq` fn main() {} diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr b/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr index db14f9c9bf695..c86a09bef0b8d 100644 --- a/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr +++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr @@ -1,9 +1,3 @@ -error[E0671]: const parameters cannot depend on type parameters - --> $DIR/const-param-type-depends-on-type-param.rs:9:34 - | -LL | pub struct Dependent([(); X]); - | ^ const parameter depends on type parameter - warning: the feature `const_generics` is incomplete and may cause the compiler to crash --> $DIR/const-param-type-depends-on-type-param.rs:1:12 | @@ -12,15 +6,12 @@ LL | #![feature(const_generics)] | = note: `#[warn(incomplete_features)]` on by default -error[E0392]: parameter `T` is never used - --> $DIR/const-param-type-depends-on-type-param.rs:9:22 +error[E0740]: the types of const generic parameters must derive `PartialEq` and `Eq` + --> $DIR/const-param-type-depends-on-type-param.rs:9:34 | LL | pub struct Dependent([(); X]); - | ^ unused parameter - | - = help: consider removing `T`, referring to it in a field, or using a marker such as `std::marker::PhantomData` + | ^ `T` doesn't derive both `PartialEq` and `Eq` -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0392, E0671. -For more information about an error, try `rustc --explain E0392`. +For more information about this error, try `rustc --explain E0740`. From 9f788f3a2b7626318d0bdedca38986fc283f481f Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 21 Oct 2019 16:54:33 +0100 Subject: [PATCH 05/23] Fix rustdoc const generics test --- src/test/rustdoc/const-generics/const-impl.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/rustdoc/const-generics/const-impl.rs b/src/test/rustdoc/const-generics/const-impl.rs index 85ee6d3376b27..2d506787b3b80 100644 --- a/src/test/rustdoc/const-generics/const-impl.rs +++ b/src/test/rustdoc/const-generics/const-impl.rs @@ -4,6 +4,7 @@ #![crate_name = "foo"] +#[derive(PartialEq, Eq)] pub enum Order { Sorted, Unsorted, From 7f13a4a80a67ecc4fd0521e867eeb91b657f2fa0 Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 22 Oct 2019 12:00:54 +0100 Subject: [PATCH 06/23] Remove FIXME --- src/librustc/ty/relate.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 41f34703622e7..1da65f4b51d36 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -557,10 +557,9 @@ pub fn super_relate_consts>( x.val }; - // Currently, the values that can be unified are those that - // implement both `PartialEq` and `Eq`, corresponding to - // `structural_match` types. - // FIXME(const_generics): check for `structural_match` synthetic attribute. + // Currently, the values that can be unified are primitive types, + // and those that derive both `PartialEq` and `Eq`, corresponding + // to `structural_match` types. let new_const_val = match (eagerly_eval(a), eagerly_eval(b)) { (ConstValue::Infer(_), _) | (_, ConstValue::Infer(_)) => { // The caller should handle these cases! From 2dda8ad98a8d5089335b2d09307f1bfd085499f9 Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 22 Oct 2019 12:28:23 +0100 Subject: [PATCH 07/23] Use E0741 for structural match error --- src/librustc_resolve/error_codes.rs | 2 +- src/librustc_typeck/collect.rs | 2 +- src/librustc_typeck/error_codes.rs | 4 ++-- .../const-param-type-depends-on-type-param-ungated.stderr | 4 ++-- .../const-param-type-depends-on-type-param.stderr | 4 ++-- .../const-generics/forbid-non-structural_match-types.stderr | 4 ++-- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/librustc_resolve/error_codes.rs b/src/librustc_resolve/error_codes.rs index 49f8e82a2d1b5..df22085c38c74 100644 --- a/src/librustc_resolve/error_codes.rs +++ b/src/librustc_resolve/error_codes.rs @@ -1884,7 +1884,7 @@ E0671: r##" Const parameters cannot depend on type parameters. The following is therefore invalid: -```compile_fail,E0740 +```compile_fail,E0741 #![feature(const_generics)] fn const_id() -> T { // error diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 08fb5ae1676e7..f40667652cac0 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1536,7 +1536,7 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option(PhantomData<[T; N]>); = note: for more information, see https://github.com/rust-lang/rust/issues/44580 = help: add `#![feature(const_generics)]` to the crate attributes to enable -error[E0740]: the types of const generic parameters must derive `PartialEq` and `Eq` +error[E0741]: the types of const generic parameters must derive `PartialEq` and `Eq` --> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:22 | LL | struct B(PhantomData<[T; N]>); @@ -15,5 +15,5 @@ LL | struct B(PhantomData<[T; N]>); error: aborting due to 2 previous errors -Some errors have detailed explanations: E0658, E0740. +Some errors have detailed explanations: E0658, E0741. For more information about an error, try `rustc --explain E0658`. diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr b/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr index c86a09bef0b8d..c9d6db7e2c220 100644 --- a/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr +++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr @@ -6,7 +6,7 @@ LL | #![feature(const_generics)] | = note: `#[warn(incomplete_features)]` on by default -error[E0740]: the types of const generic parameters must derive `PartialEq` and `Eq` +error[E0741]: the types of const generic parameters must derive `PartialEq` and `Eq` --> $DIR/const-param-type-depends-on-type-param.rs:9:34 | LL | pub struct Dependent([(); X]); @@ -14,4 +14,4 @@ LL | pub struct Dependent([(); X]); error: aborting due to previous error -For more information about this error, try `rustc --explain E0740`. +For more information about this error, try `rustc --explain E0741`. diff --git a/src/test/ui/const-generics/forbid-non-structural_match-types.stderr b/src/test/ui/const-generics/forbid-non-structural_match-types.stderr index c870d9b1db486..0fd9e0599e80e 100644 --- a/src/test/ui/const-generics/forbid-non-structural_match-types.stderr +++ b/src/test/ui/const-generics/forbid-non-structural_match-types.stderr @@ -6,7 +6,7 @@ LL | #![feature(const_generics)] | = note: `#[warn(incomplete_features)]` on by default -error[E0740]: the types of const generic parameters must derive `PartialEq` and `Eq` +error[E0741]: the types of const generic parameters must derive `PartialEq` and `Eq` --> $DIR/forbid-non-structural_match-types.rs:11:19 | LL | struct D; @@ -14,4 +14,4 @@ LL | struct D; error: aborting due to previous error -For more information about this error, try `rustc --explain E0740`. +For more information about this error, try `rustc --explain E0741`. From fe3dc3171066e26085ca11be77ade8c9f8adee2d Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 22 Oct 2019 15:22:57 -0700 Subject: [PATCH 08/23] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 3a9abe3f06555..3ba5f27170db1 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 3a9abe3f065554a7fbc59f440df2baba4a6e47ee +Subproject commit 3ba5f27170db10af7a92f2b682e049397197b8fa From eb6d757cb0bb2e4bd81158299a118230b099ac41 Mon Sep 17 00:00:00 2001 From: Umesh Kalappa Date: Sun, 20 Oct 2019 23:48:05 -0700 Subject: [PATCH 09/23] UI failures fix --- src/test/ui/intrinsics/intrinsic-alignment.rs | 3 ++- src/test/ui/signal-alternate-stack-cleanup.rs | 1 + src/test/ui/structs-enums/rec-align-u64.rs | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/test/ui/intrinsics/intrinsic-alignment.rs b/src/test/ui/intrinsics/intrinsic-alignment.rs index 6a67d04a54cf4..02e3139d29444 100644 --- a/src/test/ui/intrinsics/intrinsic-alignment.rs +++ b/src/test/ui/intrinsics/intrinsic-alignment.rs @@ -19,7 +19,8 @@ mod rusti { target_os = "macos", target_os = "netbsd", target_os = "openbsd", - target_os = "solaris"))] + target_os = "solaris", + target_os = "vxworks"))] mod m { #[main] #[cfg(target_arch = "x86")] diff --git a/src/test/ui/signal-alternate-stack-cleanup.rs b/src/test/ui/signal-alternate-stack-cleanup.rs index 787ff51799a8a..8fef66eac8de2 100644 --- a/src/test/ui/signal-alternate-stack-cleanup.rs +++ b/src/test/ui/signal-alternate-stack-cleanup.rs @@ -7,6 +7,7 @@ // ignore-wasm32-bare no libc // ignore-windows // ignore-sgx no libc +// ignore-vxworks no SIGWINCH in user space #![feature(rustc_private)] extern crate libc; diff --git a/src/test/ui/structs-enums/rec-align-u64.rs b/src/test/ui/structs-enums/rec-align-u64.rs index c4e9e9ea5ee1a..680a690ba34e3 100644 --- a/src/test/ui/structs-enums/rec-align-u64.rs +++ b/src/test/ui/structs-enums/rec-align-u64.rs @@ -40,7 +40,8 @@ struct Outer { target_os = "macos", target_os = "netbsd", target_os = "openbsd", - target_os = "solaris"))] + target_os = "solaris", + target_os = "vxworks"))] mod m { #[cfg(target_arch = "x86")] pub mod m { From 8467ceff22477fe567883e6fbd810e0f9e220686 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 23 Oct 2019 17:32:33 -0700 Subject: [PATCH 10/23] Tweak format string error to point at arguments always Add secondary span labels with no text to make it clear when there's a mismatch bewteen the positional arguments in a format string and the arguments to the macro. This shouldn't affect experienced users, but it should make it easier for newcomers to more clearly understand how `format!()` and `println!()` are supposed to be used. ``` error: 2 positional arguments in format string, but there is 1 argument --> file8.rs:2:14 | 2 | format!("{} {}", 1); | ^^ ^^ - ``` instead of ``` error: 2 positional arguments in format string, but there is 1 argument --> file8.rs:2:14 | 2 | format!("{} {}", 1); | ^^ ^^ ``` --- src/libsyntax_ext/format.rs | 5 ++++- src/test/ui/fmt/format-string-error.rs | 2 ++ src/test/ui/fmt/format-string-error.stderr | 8 +++++++- src/test/ui/if/ifmt-bad-arg.stderr | 10 ++++++---- 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 45d9f79c28fc3..37310f46f7eed 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -278,7 +278,7 @@ impl<'a, 'b> Context<'a, 'b> { /// format string. fn report_invalid_references(&self, numbered_position_args: bool) { let mut e; - let sp = if self.is_literal { + let sp = if self.is_literal { // Point at the formatting arguments. MultiSpan::from_spans(self.arg_spans.clone()) } else { MultiSpan::from_span(self.fmtsp) @@ -304,6 +304,9 @@ impl<'a, 'b> Context<'a, 'b> { self.describe_num_args(), ), ); + for arg in &self.args { // Point at the arguments that will be formatted. + e.span_label(arg.span, ""); + } } else { let (mut refs, spans): (Vec<_>, Vec<_>) = refs.unzip(); // Avoid `invalid reference to positional arguments 7 and 7 (there is 1 argument)` diff --git a/src/test/ui/fmt/format-string-error.rs b/src/test/ui/fmt/format-string-error.rs index cca949aab6364..691c06a2402c5 100644 --- a/src/test/ui/fmt/format-string-error.rs +++ b/src/test/ui/fmt/format-string-error.rs @@ -48,4 +48,6 @@ fn main() { "###); //~^^^ ERROR invalid format string: unmatched `}` found + println!("{} {} {}", 1, 2); + //~^ ERROR 3 positional arguments in format string, but there are 2 arguments } diff --git a/src/test/ui/fmt/format-string-error.stderr b/src/test/ui/fmt/format-string-error.stderr index 3dc122a7399dd..32119b18774b2 100644 --- a/src/test/ui/fmt/format-string-error.stderr +++ b/src/test/ui/fmt/format-string-error.stderr @@ -107,5 +107,11 @@ LL | } | = note: if you intended to print `}`, you can escape it using `}}` -error: aborting due to 12 previous errors +error: 3 positional arguments in format string, but there are 2 arguments + --> $DIR/format-string-error.rs:51:15 + | +LL | println!("{} {} {}", 1, 2); + | ^^ ^^ ^^ - - + +error: aborting due to 13 previous errors diff --git a/src/test/ui/if/ifmt-bad-arg.stderr b/src/test/ui/if/ifmt-bad-arg.stderr index 336ea2254bf5a..c58cbc312335a 100644 --- a/src/test/ui/if/ifmt-bad-arg.stderr +++ b/src/test/ui/if/ifmt-bad-arg.stderr @@ -224,8 +224,9 @@ error: 4 positional arguments in format string, but there are 3 arguments --> $DIR/ifmt-bad-arg.rs:78:15 | LL | println!("{} {:.*} {}", 1, 3.2, 4); - | ^^ ^^--^ ^^ --- this parameter corresponds to the precision flag - | | + | ^^ ^^--^ ^^ - --- - + | | | + | | this parameter corresponds to the precision flag | this precision flag adds an extra required argument at position 1, which is why there are 4 arguments expected | = note: positional arguments are zero-based @@ -235,8 +236,9 @@ error: 4 positional arguments in format string, but there are 3 arguments --> $DIR/ifmt-bad-arg.rs:81:15 | LL | println!("{} {:07$.*} {}", 1, 3.2, 4); - | ^^ ^^^----^ ^^ --- this parameter corresponds to the precision flag - | | | + | ^^ ^^^----^ ^^ - --- - + | | | | + | | | this parameter corresponds to the precision flag | | this precision flag adds an extra required argument at position 1, which is why there are 4 arguments expected | this width flag expects an `usize` argument at position 7, but there are 3 arguments | From 18d873e8f0d10ad61a6110af28e2d1008e6acd16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 24 Oct 2019 00:37:32 -0700 Subject: [PATCH 11/23] Avoid ICE when adjusting bad self ty --- src/librustc_typeck/check/method/confirm.rs | 20 +++++-- src/test/ui/issues/issue-65611.rs | 63 +++++++++++++++++++++ src/test/ui/issues/issue-65611.stderr | 18 ++++++ 3 files changed, 96 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/issues/issue-65611.rs create mode 100644 src/test/ui/issues/issue-65611.stderr diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 9baf06be3f6b5..59636d32bc037 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -141,14 +141,24 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { /////////////////////////////////////////////////////////////////////////// // ADJUSTMENTS - fn adjust_self_ty(&mut self, - unadjusted_self_ty: Ty<'tcx>, - pick: &probe::Pick<'tcx>) - -> Ty<'tcx> { + fn adjust_self_ty( + &mut self, + unadjusted_self_ty: Ty<'tcx>, + pick: &probe::Pick<'tcx>, + ) -> Ty<'tcx> { // Commit the autoderefs by calling `autoderef` again, but this // time writing the results into the various tables. let mut autoderef = self.autoderef(self.span, unadjusted_self_ty); - let (_, n) = autoderef.nth(pick.autoderefs).unwrap(); + let (_, n) = match autoderef.nth(pick.autoderefs) { + Some(n) => n, + None => { + self.tcx.sess.delay_span_bug( + syntax_pos::DUMMY_SP, + &format!("failed autoderef {}", pick.autoderefs), + ); + return self.tcx.types.err; + } + }; assert_eq!(n, pick.autoderefs); let mut adjustments = autoderef.adjust_steps(self, Needs::None); diff --git a/src/test/ui/issues/issue-65611.rs b/src/test/ui/issues/issue-65611.rs new file mode 100644 index 0000000000000..b74ee1b0c6e54 --- /dev/null +++ b/src/test/ui/issues/issue-65611.rs @@ -0,0 +1,63 @@ +use std::mem::MaybeUninit; +use std::ops::Deref; + +pub unsafe trait Array { + /// The array’s element type + type Item; + #[doc(hidden)] + /// The smallest index type that indexes the array. + type Index: Index; + #[doc(hidden)] + fn as_ptr(&self) -> *const Self::Item; + #[doc(hidden)] + fn as_mut_ptr(&mut self) -> *mut Self::Item; + #[doc(hidden)] + fn capacity() -> usize; +} + +pub trait Index : PartialEq + Copy { + fn to_usize(self) -> usize; + fn from(usize) -> Self; +} + +impl Index for usize { + fn to_usize(self) -> usize { self } + fn from(val: usize) -> Self { + val + } +} + +unsafe impl Array for [T; 1] { + type Item = T; + type Index = usize; + fn as_ptr(&self) -> *const T { self as *const _ as *const _ } + fn as_mut_ptr(&mut self) -> *mut T { self as *mut _ as *mut _} + fn capacity() -> usize { 1 } +} + +impl Deref for ArrayVec { + type Target = [A::Item]; + #[inline] + fn deref(&self) -> &[A::Item] { + panic!() + } +} + +pub struct ArrayVec { + xs: MaybeUninit, + len: usize, +} + +impl ArrayVec { + pub fn new() -> ArrayVec { + panic!() + } +} + +fn main() { + let mut buffer = ArrayVec::new(); + let x = buffer.last().unwrap().0.clone(); + //~^ ERROR type annotations needed + //~| ERROR no field `0` on type `&_` + buffer.reverse(); +} diff --git a/src/test/ui/issues/issue-65611.stderr b/src/test/ui/issues/issue-65611.stderr new file mode 100644 index 0000000000000..cb441c13c6b9e --- /dev/null +++ b/src/test/ui/issues/issue-65611.stderr @@ -0,0 +1,18 @@ +error[E0282]: type annotations needed + --> $DIR/issue-65611.rs:59:20 + | +LL | let x = buffer.last().unwrap().0.clone(); + | ^^^^ cannot infer type for `T` + | + = note: type must be known at this point + +error[E0609]: no field `0` on type `&_` + --> $DIR/issue-65611.rs:59:36 + | +LL | let x = buffer.last().unwrap().0.clone(); + | ^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0282, E0609. +For more information about an error, try `rustc --explain E0282`. From 060b6cbe74f65b8d517c4d4936f4a361f3e4287d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 24 Oct 2019 08:07:03 -0700 Subject: [PATCH 12/23] Update hashbrown to 0.6.2 Pulls in rust-lang/hashbrown#119 which should be a good improvement for compile times of hashmap-heavy crates. --- Cargo.lock | 6 +++--- src/libstd/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index efcbd7b6794f0..fb81c0637cca9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1297,9 +1297,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6587d09be37fb98a11cb08b9000a3f592451c1b1b613ca69d949160e313a430a" +checksum = "3cd9867f119b19fecb08cd5c326ad4488d7a1da4bf75b4d95d71db742525aaab" dependencies = [ "autocfg", "compiler_builtins", @@ -4146,7 +4146,7 @@ dependencies = [ "core", "dlmalloc", "fortanix-sgx-abi", - "hashbrown 0.6.1", + "hashbrown 0.6.2", "libc", "panic_abort", "panic_unwind", diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index 5309af6f4c342..efe5c9d28f0d2 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -23,7 +23,7 @@ libc = { version = "0.2.51", default-features = false, features = ['rustc-dep-of compiler_builtins = { version = "0.1.16" } profiler_builtins = { path = "../libprofiler_builtins", optional = true } unwind = { path = "../libunwind" } -hashbrown = { version = "0.6.1", default-features = false, features = ['rustc-dep-of-std'] } +hashbrown = { version = "0.6.2", default-features = false, features = ['rustc-dep-of-std'] } [dependencies.backtrace_rs] package = "backtrace" From 184a61f0bfa4cf6c913d03be3da019ef3e7402cd Mon Sep 17 00:00:00 2001 From: csmoe Date: Thu, 24 Oct 2019 14:25:23 +0800 Subject: [PATCH 13/23] Don't assert for different instance on impl trait alias --- src/librustc_typeck/check/mod.rs | 3 +-- ...issue-65679-inst-opaque-ty-from-val-twice.rs | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 73a025182a7e3..790407aae9ff1 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2761,8 +2761,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut opaque_types = self.opaque_types.borrow_mut(); for (ty, decl) in opaque_type_map { - let old_value = opaque_types.insert(ty, decl); - assert!(old_value.is_none(), "instantiated twice: {:?}/{:?}", ty, decl); + let _ = opaque_types.insert(ty, decl); } value diff --git a/src/test/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs b/src/test/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs new file mode 100644 index 0000000000000..12eb75ae4c019 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs @@ -0,0 +1,17 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +type T = impl Sized; +// The concrete type referred by impl-trait-type-alias(`T`) is guaranteed +// to be the same as where it occurs, whereas `impl Trait`'s instance is location sensitive; +// so difference assertion should not be declared on impl-trait-type-alias's instances. +// for details, check RFC-2515: +// https://github.com/rust-lang/rfcs/blob/master/text/2515-type_alias_impl_trait.md + +fn take(_: fn() -> T) {} + +fn main() { + take(|| {}); + take(|| {}); +} From 2c16f8449090349c3907b15402d36ff190135c99 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 16 Oct 2019 19:03:21 +0300 Subject: [PATCH 14/23] rustc_driver: Remove unnecessary use of crate store --- src/librustc_driver/lib.rs | 8 ++++---- src/librustc_metadata/locator.rs | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 5d9dec14c6c8e..15adf7e4add73 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -36,11 +36,11 @@ use rustc::session::config::nightly_options; use rustc::session::{early_error, early_warn}; use rustc::lint::Lint; use rustc::lint; +use rustc::middle::cstore::MetadataLoader; use rustc::hir::def_id::LOCAL_CRATE; use rustc::ty::TyCtxt; use rustc::util::common::{set_time_depth, time, print_time_passes_entry, ErrorReported}; use rustc_metadata::locator; -use rustc_metadata::cstore::CStore; use rustc_codegen_utils::codegen_backend::CodegenBackend; use rustc_interface::interface; use rustc_interface::util::get_codegen_sysroot; @@ -277,7 +277,7 @@ pub fn run_compiler( compiler.output_file(), ).and_then(|| RustcDefaultCalls::list_metadata( sess, - compiler.cstore(), + &*compiler.codegen_backend().metadata_loader(), &matches, compiler.input() )); @@ -614,7 +614,7 @@ fn show_content_with_pager(content: &String) { impl RustcDefaultCalls { pub fn list_metadata(sess: &Session, - cstore: &CStore, + metadata_loader: &dyn MetadataLoader, matches: &getopts::Matches, input: &Input) -> Compilation { @@ -626,7 +626,7 @@ impl RustcDefaultCalls { let mut v = Vec::new(); locator::list_file_metadata(&sess.target.target, path, - cstore, + metadata_loader, &mut v) .unwrap(); println!("{}", String::from_utf8(v).unwrap()); diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index 05676dad3340c..b9f7879203815 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -212,7 +212,7 @@ //! no means all of the necessary details. Take a look at the rest of //! metadata::locator or metadata::creader for all the juicy details! -use crate::cstore::{MetadataBlob, CStore}; +use crate::cstore::MetadataBlob; use crate::creader::Library; use crate::schema::{METADATA_HEADER, rustc_version}; @@ -914,7 +914,7 @@ fn get_metadata_section_imp(target: &Target, /// A diagnostic function for dumping crate metadata to an output stream. pub fn list_file_metadata(target: &Target, path: &Path, - cstore: &CStore, + metadata_loader: &dyn MetadataLoader, out: &mut dyn io::Write) -> io::Result<()> { let filename = path.file_name().unwrap().to_str().unwrap(); @@ -925,7 +925,7 @@ pub fn list_file_metadata(target: &Target, } else { CrateFlavor::Dylib }; - match get_metadata_section(target, flavor, path, &*cstore.metadata_loader) { + match get_metadata_section(target, flavor, path, metadata_loader) { Ok(metadata) => metadata.list_crate_metadata(out), Err(msg) => write!(out, "{}\n", msg), } From 2cda75c48f48022690f142b63969660b12536cee Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 16 Oct 2019 19:57:10 +0300 Subject: [PATCH 15/23] rustc_metadata: Remove unnecessary use of crate store in plugin loader --- src/librustc_interface/passes.rs | 7 +-- src/librustc_interface/queries.rs | 2 +- src/librustc_metadata/creader.rs | 94 ++++++++++--------------------- src/librustc_plugin/load.rs | 21 ++----- 4 files changed, 41 insertions(+), 83 deletions(-) diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 2044b73db8aa9..77570bc046303 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -9,7 +9,7 @@ use rustc::hir::lowering::lower_crate; use rustc::hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc::lint; use rustc::middle::{self, reachable, resolve_lifetime, stability}; -use rustc::middle::cstore::CrateStore; +use rustc::middle::cstore::{CrateStore, MetadataLoader}; use rustc::ty::{self, AllArenas, Resolutions, TyCtxt, GlobalCtxt}; use rustc::ty::steal::Steal; use rustc::traits; @@ -226,7 +226,7 @@ pub struct PluginInfo { pub fn register_plugins<'a>( sess: &'a Session, - cstore: &'a CStore, + metadata_loader: &'a dyn MetadataLoader, register_lints: impl Fn(&Session, &mut lint::LintStore), mut krate: ast::Crate, crate_name: &str, @@ -274,9 +274,8 @@ pub fn register_plugins<'a>( let registrars = time(sess, "plugin loading", || { plugin::load::load_plugins( sess, - &cstore, + metadata_loader, &krate, - crate_name, Some(sess.opts.debugging_opts.extra_plugins.clone()), ) }); diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs index 84648ca8326fb..847d21b051251 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -118,7 +118,7 @@ impl Compiler { let empty: &(dyn Fn(&Session, &mut lint::LintStore) + Sync + Send) = &|_, _| {}; let result = passes::register_plugins( self.session(), - self.cstore(), + &*self.codegen_backend().metadata_loader(), self.register_lints .as_ref() .map(|p| &**p) diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 7412e8a2cb9bd..fbd1877dc88ac 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -14,13 +14,12 @@ use rustc::session::{Session, CrateDisambiguator}; use rustc::session::config::{Sanitizer, self}; use rustc_target::spec::{PanicStrategy, TargetTriple}; use rustc::session::search_paths::PathKind; -use rustc::middle::cstore::{CrateSource, ExternCrate, ExternCrateSource}; +use rustc::middle::cstore::{CrateSource, ExternCrate, ExternCrateSource, MetadataLoader}; use rustc::util::common::record_time; use rustc::util::nodemap::FxHashSet; use rustc::hir::map::Definitions; use rustc::hir::def_id::LOCAL_CRATE; -use std::ops::Deref; use std::path::{Path, PathBuf}; use std::{cmp, fs}; @@ -58,29 +57,6 @@ fn dump_crates(cstore: &CStore) { }); } -// Extra info about a crate loaded for plugins or exported macros. -struct ExtensionCrate { - metadata: PMDSource, - dylib: Option, - target_only: bool, -} - -enum PMDSource { - Registered(Lrc), - Owned(Library), -} - -impl Deref for PMDSource { - type Target = MetadataBlob; - - fn deref(&self) -> &MetadataBlob { - match *self { - PMDSource::Registered(ref cmd) => &cmd.blob, - PMDSource::Owned(ref lib) => &lib.metadata - } - } -} - enum LoadResult { Previous(CrateNum), Loaded(Library), @@ -495,21 +471,27 @@ impl<'a> CrateLoader<'a> { self.resolve_crate(dep.name, span, dep_kind, Some((root, &dep))).0 })).collect() } +} - fn read_extension_crate(&self, name: Symbol, span: Span) -> ExtensionCrate { + fn read_extension_crate( + sess: &Session, + metadata_loader: &dyn MetadataLoader, + name: Symbol, + span: Span, + ) -> (Library, bool) { info!("read extension crate `{}`", name); - let target_triple = self.sess.opts.target_triple.clone(); + let target_triple = sess.opts.target_triple.clone(); let host_triple = TargetTriple::from_triple(config::host_triple()); let is_cross = target_triple != host_triple; let mut target_only = false; let mut locate_ctxt = locator::Context { - sess: self.sess, + sess, span, crate_name: name, hash: None, extra_filename: None, - filesearch: self.sess.host_filesearch(PathKind::Crate), - target: &self.sess.host, + filesearch: sess.host_filesearch(PathKind::Crate), + target: &sess.host, triple: host_triple, root: None, rejected_via_hash: vec![], @@ -519,9 +501,10 @@ impl<'a> CrateLoader<'a> { rejected_via_filename: vec![], should_match_name: true, is_proc_macro: None, - metadata_loader: &*self.cstore.metadata_loader, + metadata_loader, }; - let library = self.load(&mut locate_ctxt).or_else(|| { + + let library = locate_ctxt.maybe_load_library_crate().or_else(|| { if !is_cross { return None } @@ -529,36 +512,21 @@ impl<'a> CrateLoader<'a> { // try to load a plugin registrar function, target_only = true; - locate_ctxt.target = &self.sess.target.target; + locate_ctxt.target = &sess.target.target; locate_ctxt.triple = target_triple; - locate_ctxt.filesearch = self.sess.target_filesearch(PathKind::Crate); + locate_ctxt.filesearch = sess.target_filesearch(PathKind::Crate); - self.load(&mut locate_ctxt) + locate_ctxt.maybe_load_library_crate() }); let library = match library { Some(l) => l, None => locate_ctxt.report_errs(), }; - let (dylib, metadata) = match library { - LoadResult::Previous(cnum) => { - let data = self.cstore.get_crate_data(cnum); - (data.source.dylib.clone(), PMDSource::Registered(data)) - } - LoadResult::Loaded(library) => { - let dylib = library.source.dylib.clone(); - let metadata = PMDSource::Owned(library); - (dylib, metadata) - } - }; - - ExtensionCrate { - metadata, - dylib: dylib.map(|p| p.0), - target_only, - } + (library, target_only) } +impl<'a> CrateLoader<'a> { fn dlsym_proc_macros(&self, path: &Path, disambiguator: CrateDisambiguator, @@ -589,32 +557,33 @@ impl<'a> CrateLoader<'a> { decls } +} /// Look for a plugin registrar. Returns library path, crate /// SVH and DefIndex of the registrar function. - pub fn find_plugin_registrar(&self, + pub fn find_plugin_registrar(sess: &Session, + metadata_loader: &dyn MetadataLoader, span: Span, name: Symbol) -> Option<(PathBuf, CrateDisambiguator)> { - let ekrate = self.read_extension_crate(name, span); + let (library, target_only) = read_extension_crate(sess, metadata_loader, name, span); - if ekrate.target_only { + if target_only { // Need to abort before syntax expansion. let message = format!("plugin `{}` is not available for triple `{}` \ (only found {})", name, config::host_triple(), - self.sess.opts.target_triple); - span_fatal!(self.sess, span, E0456, "{}", &message); + sess.opts.target_triple); + span_fatal!(sess, span, E0456, "{}", &message); } - let root = ekrate.metadata.get_root(); - match ekrate.dylib.as_ref() { + match library.source.dylib { Some(dylib) => { - Some((dylib.to_path_buf(), root.disambiguator)) + Some((dylib.0, library.metadata.get_root().disambiguator)) } None => { - span_err!(self.sess, span, E0457, + span_err!(sess, span, E0457, "plugin `{}` only found in rlib format, but must be available \ in dylib format", name); @@ -625,6 +594,7 @@ impl<'a> CrateLoader<'a> { } } +impl<'a> CrateLoader<'a> { fn inject_panic_runtime(&self, krate: &ast::Crate) { // If we're only compiling an rlib, then there's no need to select a // panic runtime, so we just skip this section entirely. @@ -957,9 +927,7 @@ impl<'a> CrateLoader<'a> { data.dependencies.borrow_mut().push(krate); }); } -} -impl<'a> CrateLoader<'a> { pub fn postprocess(&self, krate: &ast::Crate) { self.inject_sanitizer_runtime(); self.inject_profiler_runtime(); diff --git a/src/librustc_plugin/load.rs b/src/librustc_plugin/load.rs index 4481892bcf244..dd0dbf62c7361 100644 --- a/src/librustc_plugin/load.rs +++ b/src/librustc_plugin/load.rs @@ -1,8 +1,8 @@ //! Used by `rustc` when loading a plugin. +use rustc::middle::cstore::MetadataLoader; use rustc::session::Session; -use rustc_metadata::creader::CrateLoader; -use rustc_metadata::cstore::CStore; +use rustc_metadata::creader; use crate::registry::Registry; use std::borrow::ToOwned; @@ -25,7 +25,7 @@ pub struct PluginRegistrar { struct PluginLoader<'a> { sess: &'a Session, - reader: CrateLoader<'a>, + metadata_loader: &'a dyn MetadataLoader, plugins: Vec, } @@ -37,11 +37,10 @@ fn call_malformed_plugin_attribute(sess: &Session, span: Span) { /// Read plugin metadata and dynamically load registrar functions. pub fn load_plugins(sess: &Session, - cstore: &CStore, + metadata_loader: &dyn MetadataLoader, krate: &ast::Crate, - crate_name: &str, addl_plugins: Option>) -> Vec { - let mut loader = PluginLoader::new(sess, cstore, crate_name); + let mut loader = PluginLoader { sess, metadata_loader, plugins: Vec::new() }; // do not report any error now. since crate attributes are // not touched by expansion, every use of plugin without @@ -80,16 +79,8 @@ pub fn load_plugins(sess: &Session, } impl<'a> PluginLoader<'a> { - fn new(sess: &'a Session, cstore: &'a CStore, crate_name: &str) -> Self { - PluginLoader { - sess, - reader: CrateLoader::new(sess, cstore, crate_name), - plugins: vec![], - } - } - fn load_plugin(&mut self, span: Span, name: Symbol, args: Vec) { - let registrar = self.reader.find_plugin_registrar(span, name); + let registrar = creader::find_plugin_registrar(self.sess, self.metadata_loader, span, name); if let Some((lib, disambiguator)) = registrar { let symbol = self.sess.generate_plugin_registrar_symbol(disambiguator); From 175d325ccbaccf40907a8bb8184ee65a5f62ca8a Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 17 Oct 2019 19:08:06 +0300 Subject: [PATCH 16/23] rustc_metadata: Move some code around Plugin search doesn't need a crate loader, only crate locator --- src/librustc_metadata/creader.rs | 98 +------------------------------- src/librustc_metadata/locator.rs | 80 +++++++++++++++++++++++++- src/librustc_plugin/load.rs | 4 +- 3 files changed, 84 insertions(+), 98 deletions(-) diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index fbd1877dc88ac..2eaf7536a70ad 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -14,20 +14,20 @@ use rustc::session::{Session, CrateDisambiguator}; use rustc::session::config::{Sanitizer, self}; use rustc_target::spec::{PanicStrategy, TargetTriple}; use rustc::session::search_paths::PathKind; -use rustc::middle::cstore::{CrateSource, ExternCrate, ExternCrateSource, MetadataLoader}; +use rustc::middle::cstore::{CrateSource, ExternCrate, ExternCrateSource}; use rustc::util::common::record_time; use rustc::util::nodemap::FxHashSet; use rustc::hir::map::Definitions; use rustc::hir::def_id::LOCAL_CRATE; -use std::path::{Path, PathBuf}; +use std::path::Path; use std::{cmp, fs}; use syntax::ast; use syntax::attr; use syntax_expand::allocator::{global_allocator_spans, AllocatorKind}; use syntax::symbol::{Symbol, sym}; -use syntax::{span_err, span_fatal}; +use syntax::span_fatal; use syntax_pos::{Span, DUMMY_SP}; use log::{debug, info, log_enabled}; use proc_macro::bridge::client::ProcMacro; @@ -471,62 +471,7 @@ impl<'a> CrateLoader<'a> { self.resolve_crate(dep.name, span, dep_kind, Some((root, &dep))).0 })).collect() } -} - - fn read_extension_crate( - sess: &Session, - metadata_loader: &dyn MetadataLoader, - name: Symbol, - span: Span, - ) -> (Library, bool) { - info!("read extension crate `{}`", name); - let target_triple = sess.opts.target_triple.clone(); - let host_triple = TargetTriple::from_triple(config::host_triple()); - let is_cross = target_triple != host_triple; - let mut target_only = false; - let mut locate_ctxt = locator::Context { - sess, - span, - crate_name: name, - hash: None, - extra_filename: None, - filesearch: sess.host_filesearch(PathKind::Crate), - target: &sess.host, - triple: host_triple, - root: None, - rejected_via_hash: vec![], - rejected_via_triple: vec![], - rejected_via_kind: vec![], - rejected_via_version: vec![], - rejected_via_filename: vec![], - should_match_name: true, - is_proc_macro: None, - metadata_loader, - }; - - let library = locate_ctxt.maybe_load_library_crate().or_else(|| { - if !is_cross { - return None - } - // Try loading from target crates. This will abort later if we - // try to load a plugin registrar function, - target_only = true; - - locate_ctxt.target = &sess.target.target; - locate_ctxt.triple = target_triple; - locate_ctxt.filesearch = sess.target_filesearch(PathKind::Crate); - - locate_ctxt.maybe_load_library_crate() - }); - let library = match library { - Some(l) => l, - None => locate_ctxt.report_errs(), - }; - (library, target_only) - } - -impl<'a> CrateLoader<'a> { fn dlsym_proc_macros(&self, path: &Path, disambiguator: CrateDisambiguator, @@ -557,44 +502,7 @@ impl<'a> CrateLoader<'a> { decls } -} - - /// Look for a plugin registrar. Returns library path, crate - /// SVH and DefIndex of the registrar function. - pub fn find_plugin_registrar(sess: &Session, - metadata_loader: &dyn MetadataLoader, - span: Span, - name: Symbol) - -> Option<(PathBuf, CrateDisambiguator)> { - let (library, target_only) = read_extension_crate(sess, metadata_loader, name, span); - - if target_only { - // Need to abort before syntax expansion. - let message = format!("plugin `{}` is not available for triple `{}` \ - (only found {})", - name, - config::host_triple(), - sess.opts.target_triple); - span_fatal!(sess, span, E0456, "{}", &message); - } - - match library.source.dylib { - Some(dylib) => { - Some((dylib.0, library.metadata.get_root().disambiguator)) - } - None => { - span_err!(sess, span, E0457, - "plugin `{}` only found in rlib format, but must be available \ - in dylib format", - name); - // No need to abort because the loading code will just ignore this - // empty dylib. - None - } - } - } -impl<'a> CrateLoader<'a> { fn inject_panic_runtime(&self, krate: &ast::Crate) { // If we're only compiling an rlib, then there's no need to select a // panic runtime, so we just skip this section entirely. diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index b9f7879203815..a5298402dd411 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -220,12 +220,13 @@ use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::MetadataRef; use rustc::middle::cstore::{CrateSource, MetadataLoader}; -use rustc::session::{config, Session}; +use rustc::session::{config, Session, CrateDisambiguator}; use rustc::session::filesearch::{FileSearch, FileMatches, FileDoesntMatch}; use rustc::session::search_paths::PathKind; use rustc::util::nodemap::FxHashMap; use errors::DiagnosticBuilder; +use syntax::{span_err, span_fatal}; use syntax::symbol::{Symbol, sym}; use syntax::struct_span_err; use syntax_pos::Span; @@ -911,6 +912,83 @@ fn get_metadata_section_imp(target: &Target, } } +/// Look for a plugin registrar. Returns its library path and crate disambiguator. +pub fn find_plugin_registrar( + sess: &Session, + metadata_loader: &dyn MetadataLoader, + span: Span, + name: Symbol, +) -> Option<(PathBuf, CrateDisambiguator)> { + info!("find plugin registrar `{}`", name); + let target_triple = sess.opts.target_triple.clone(); + let host_triple = TargetTriple::from_triple(config::host_triple()); + let is_cross = target_triple != host_triple; + let mut target_only = false; + let mut locate_ctxt = Context { + sess, + span, + crate_name: name, + hash: None, + extra_filename: None, + filesearch: sess.host_filesearch(PathKind::Crate), + target: &sess.host, + triple: host_triple, + root: None, + rejected_via_hash: vec![], + rejected_via_triple: vec![], + rejected_via_kind: vec![], + rejected_via_version: vec![], + rejected_via_filename: vec![], + should_match_name: true, + is_proc_macro: None, + metadata_loader, + }; + + let library = locate_ctxt.maybe_load_library_crate().or_else(|| { + if !is_cross { + return None + } + // Try loading from target crates. This will abort later if we + // try to load a plugin registrar function, + target_only = true; + + locate_ctxt.target = &sess.target.target; + locate_ctxt.triple = target_triple; + locate_ctxt.filesearch = sess.target_filesearch(PathKind::Crate); + + locate_ctxt.maybe_load_library_crate() + }); + let library = match library { + Some(l) => l, + None => locate_ctxt.report_errs(), + }; + + if target_only { + // Need to abort before syntax expansion. + let message = format!("plugin `{}` is not available for triple `{}` \ + (only found {})", + name, + config::host_triple(), + sess.opts.target_triple); + span_fatal!(sess, span, E0456, "{}", &message); + } + + match library.source.dylib { + Some(dylib) => { + Some((dylib.0, library.metadata.get_root().disambiguator)) + } + None => { + span_err!(sess, span, E0457, + "plugin `{}` only found in rlib format, but must be available \ + in dylib format", + name); + // No need to abort because the loading code will just ignore this + // empty dylib. + None + } + } +} + /// A diagnostic function for dumping crate metadata to an output stream. pub fn list_file_metadata(target: &Target, path: &Path, diff --git a/src/librustc_plugin/load.rs b/src/librustc_plugin/load.rs index dd0dbf62c7361..8ceb56b0fd2b4 100644 --- a/src/librustc_plugin/load.rs +++ b/src/librustc_plugin/load.rs @@ -2,7 +2,7 @@ use rustc::middle::cstore::MetadataLoader; use rustc::session::Session; -use rustc_metadata::creader; +use rustc_metadata::locator; use crate::registry::Registry; use std::borrow::ToOwned; @@ -80,7 +80,7 @@ pub fn load_plugins(sess: &Session, impl<'a> PluginLoader<'a> { fn load_plugin(&mut self, span: Span, name: Symbol, args: Vec) { - let registrar = creader::find_plugin_registrar(self.sess, self.metadata_loader, span, name); + let registrar = locator::find_plugin_registrar(self.sess, self.metadata_loader, span, name); if let Some((lib, disambiguator)) = registrar { let symbol = self.sess.generate_plugin_registrar_symbol(disambiguator); From 222503a354d263ee13ee160506443036b799a2ea Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 17 Oct 2019 21:26:13 +0300 Subject: [PATCH 17/23] rustc: Add a convenience alias for `dyn MetadataLoader + Sync` --- src/librustc/middle/cstore.rs | 2 ++ src/librustc_codegen_llvm/lib.rs | 4 ++-- src/librustc_codegen_utils/codegen_backend.rs | 4 ++-- src/librustc_metadata/cstore.rs | 6 +++--- .../hotplug_codegen_backend/the_backend.rs | 6 +++--- 5 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index ec1e32988a607..8205383da9892 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -191,6 +191,8 @@ pub trait MetadataLoader { -> Result; } +pub type MetadataLoaderDyn = dyn MetadataLoader + Sync; + /// A store of Rust crates, through which their metadata can be accessed. /// /// Note that this trait should probably not be expanding today. All new diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index 8c1797cfb7de4..e09b600afd4e5 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -56,7 +56,7 @@ use std::sync::Arc; use std::ffi::CStr; use rustc::dep_graph::DepGraph; -use rustc::middle::cstore::{EncodedMetadata, MetadataLoader}; +use rustc::middle::cstore::{EncodedMetadata, MetadataLoaderDyn}; use rustc::session::Session; use rustc::session::config::{OutputFilenames, OutputType, PrintRequest, OptLevel}; use rustc::ty::{self, TyCtxt}; @@ -260,7 +260,7 @@ impl CodegenBackend for LlvmCodegenBackend { target_features(sess) } - fn metadata_loader(&self) -> Box { + fn metadata_loader(&self) -> Box { box metadata::LlvmMetadataLoader } diff --git a/src/librustc_codegen_utils/codegen_backend.rs b/src/librustc_codegen_utils/codegen_backend.rs index 1077c1f42637e..0e2c3731eae6d 100644 --- a/src/librustc_codegen_utils/codegen_backend.rs +++ b/src/librustc_codegen_utils/codegen_backend.rs @@ -14,7 +14,7 @@ use rustc::util::common::ErrorReported; use rustc::session::config::{OutputFilenames, PrintRequest}; use rustc::ty::TyCtxt; use rustc::ty::query::Providers; -use rustc::middle::cstore::{EncodedMetadata, MetadataLoader}; +use rustc::middle::cstore::{EncodedMetadata, MetadataLoaderDyn}; use rustc::dep_graph::DepGraph; pub use rustc_data_structures::sync::MetadataRef; @@ -26,7 +26,7 @@ pub trait CodegenBackend { fn print_passes(&self) {} fn print_version(&self) {} - fn metadata_loader(&self) -> Box; + fn metadata_loader(&self) -> Box; fn provide(&self, _providers: &mut Providers<'_>); fn provide_extern(&self, _providers: &mut Providers<'_>); fn codegen_crate<'tcx>( diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index 9a0b98ffb73a9..a2920884409ca 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -5,7 +5,7 @@ use crate::schema; use rustc::dep_graph::DepNodeIndex; use rustc::hir::def_id::{CrateNum, DefIndex}; use rustc::hir::map::definitions::DefPathTable; -use rustc::middle::cstore::{CrateSource, DepKind, ExternCrate, MetadataLoader}; +use rustc::middle::cstore::{CrateSource, DepKind, ExternCrate, MetadataLoaderDyn}; use rustc::mir::interpret::AllocDecodingState; use rustc_index::vec::IndexVec; use rustc::util::nodemap::FxHashMap; @@ -96,7 +96,7 @@ pub struct CrateMetadata { pub struct CStore { metas: RwLock>>>, - crate metadata_loader: Box, + crate metadata_loader: Box, } pub enum LoadedMacro { @@ -105,7 +105,7 @@ pub enum LoadedMacro { } impl CStore { - pub fn new(metadata_loader: Box) -> CStore { + pub fn new(metadata_loader: Box) -> CStore { CStore { // We add an empty entry for LOCAL_CRATE (which maps to zero) in // order to make array indices in `metas` match with the diff --git a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs index 1566a153ec03c..eb96c61060b39 100644 --- a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs +++ b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs @@ -9,14 +9,14 @@ extern crate rustc_target; extern crate rustc_driver; use std::any::Any; -use std::sync::{Arc, mpsc}; +use std::sync::Arc; use std::path::Path; use syntax::symbol::Symbol; use rustc::session::Session; use rustc::session::config::OutputFilenames; use rustc::ty::TyCtxt; use rustc::ty::query::Providers; -use rustc::middle::cstore::{EncodedMetadata, MetadataLoader}; +use rustc::middle::cstore::{EncodedMetadata, MetadataLoader, MetadataLoaderDyn}; use rustc::dep_graph::DepGraph; use rustc::util::common::ErrorReported; use rustc_codegen_utils::codegen_backend::CodegenBackend; @@ -41,7 +41,7 @@ impl MetadataLoader for NoLlvmMetadataLoader { struct TheBackend; impl CodegenBackend for TheBackend { - fn metadata_loader(&self) -> Box { + fn metadata_loader(&self) -> Box { Box::new(NoLlvmMetadataLoader) } From fb353f050acd1d18bafcf570d7be1459cf454858 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 20 Oct 2019 02:55:39 +0300 Subject: [PATCH 18/23] resolve: Privatize all resolver fields --- src/librustc_interface/passes.rs | 43 ++----------- src/librustc_resolve/lib.rs | 64 ++++++++++++++++--- .../passes/collect_intra_doc_links.rs | 4 +- 3 files changed, 61 insertions(+), 50 deletions(-) diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 77570bc046303..3d6ea5354a9f8 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -6,6 +6,7 @@ use log::{info, warn, log_enabled}; use rustc::dep_graph::DepGraph; use rustc::hir; use rustc::hir::lowering::lower_crate; +use rustc::hir::map::Definitions; use rustc::hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc::lint; use rustc::middle::{self, reachable, resolve_lifetime, stability}; @@ -154,7 +155,7 @@ pub fn configure_and_expand( } }; box_region_allow_access!(for(), (&mut Resolver<'_>), (&mut resolver)); - ExpansionResult::from_owned_resolver(resolver) + ExpansionResult::from_resolver_outputs(resolver.into_outputs()) }); result.map(|k| (k, resolver)) } @@ -165,42 +166,8 @@ pub struct ExpansionResult { } impl ExpansionResult { - fn from_owned_resolver( - resolver: Resolver<'_>, - ) -> Self { - ExpansionResult { - defs: Steal::new(resolver.definitions), - resolutions: Steal::new(Resolutions { - extern_crate_map: resolver.extern_crate_map, - export_map: resolver.export_map, - trait_map: resolver.trait_map, - glob_map: resolver.glob_map, - maybe_unused_trait_imports: resolver.maybe_unused_trait_imports, - maybe_unused_extern_crates: resolver.maybe_unused_extern_crates, - extern_prelude: resolver.extern_prelude.iter().map(|(ident, entry)| { - (ident.name, entry.introduced_by_item) - }).collect(), - }), - } - } - - pub fn from_resolver_ref( - resolver: &Resolver<'_>, - ) -> Self { - ExpansionResult { - defs: Steal::new(resolver.definitions.clone()), - resolutions: Steal::new(Resolutions { - extern_crate_map: resolver.extern_crate_map.clone(), - export_map: resolver.export_map.clone(), - trait_map: resolver.trait_map.clone(), - glob_map: resolver.glob_map.clone(), - maybe_unused_trait_imports: resolver.maybe_unused_trait_imports.clone(), - maybe_unused_extern_crates: resolver.maybe_unused_extern_crates.clone(), - extern_prelude: resolver.extern_prelude.iter().map(|(ident, entry)| { - (ident.name, entry.introduced_by_item) - }).collect(), - }), - } + fn from_resolver_outputs((defs, resolutions): (Definitions, Resolutions)) -> Self { + ExpansionResult { defs: Steal::new(defs), resolutions: Steal::new(resolutions) } } } @@ -213,7 +180,7 @@ impl BoxedResolver { Err(resolver) => { let resolver = &*resolver; resolver.borrow_mut().access(|resolver| { - ExpansionResult::from_resolver_ref(resolver) + ExpansionResult::from_resolver_outputs(resolver.clone_outputs()) }) } } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 17d8f0f211a92..57f1b5186cbab 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -831,12 +831,12 @@ pub struct Resolver<'a> { session: &'a Session, cstore: &'a CStore, - pub definitions: Definitions, + definitions: Definitions, - pub graph_root: Module<'a>, + graph_root: Module<'a>, prelude: Option>, - pub extern_prelude: FxHashMap>, + extern_prelude: FxHashMap>, /// N.B., this is used only for better diagnostics, not name resolution itself. has_self: FxHashSet, @@ -869,9 +869,9 @@ pub struct Resolver<'a> { label_res_map: NodeMap, /// `CrateNum` resolutions of `extern crate` items. - pub extern_crate_map: NodeMap, - pub export_map: ExportMap, - pub trait_map: TraitMap, + extern_crate_map: NodeMap, + export_map: ExportMap, + trait_map: TraitMap, /// A map from nodes to anonymous modules. /// Anonymous modules are pseudo-modules that are implicitly created around items @@ -898,11 +898,11 @@ pub struct Resolver<'a> { underscore_disambiguator: u32, /// Maps glob imports to the names of items actually imported. - pub glob_map: GlobMap, + glob_map: GlobMap, used_imports: FxHashSet<(NodeId, Namespace)>, - pub maybe_unused_trait_imports: NodeSet, - pub maybe_unused_extern_crates: Vec<(NodeId, Span)>, + maybe_unused_trait_imports: NodeSet, + maybe_unused_extern_crates: Vec<(NodeId, Span)>, /// Privacy errors are delayed until the end in order to deduplicate them. privacy_errors: Vec>, @@ -920,7 +920,7 @@ pub struct Resolver<'a> { macro_names: FxHashSet, builtin_macros: FxHashMap, macro_use_prelude: FxHashMap>, - pub all_macros: FxHashMap, + all_macros: FxHashMap, macro_map: FxHashMap>, dummy_ext_bang: Lrc, dummy_ext_derive: Lrc, @@ -1236,6 +1236,40 @@ impl<'a> Resolver<'a> { Default::default() } + pub fn into_outputs(self) -> (Definitions, ty::Resolutions) { + ( + self.definitions, + ty::Resolutions { + extern_crate_map: self.extern_crate_map, + export_map: self.export_map, + trait_map: self.trait_map, + glob_map: self.glob_map, + maybe_unused_trait_imports: self.maybe_unused_trait_imports, + maybe_unused_extern_crates: self.maybe_unused_extern_crates, + extern_prelude: self.extern_prelude.iter().map(|(ident, entry)| { + (ident.name, entry.introduced_by_item) + }).collect(), + }, + ) + } + + pub fn clone_outputs(&self) -> (Definitions, ty::Resolutions) { + ( + self.definitions.clone(), + ty::Resolutions { + extern_crate_map: self.extern_crate_map.clone(), + export_map: self.export_map.clone(), + trait_map: self.trait_map.clone(), + glob_map: self.glob_map.clone(), + maybe_unused_trait_imports: self.maybe_unused_trait_imports.clone(), + maybe_unused_extern_crates: self.maybe_unused_extern_crates.clone(), + extern_prelude: self.extern_prelude.iter().map(|(ident, entry)| { + (ident.name, entry.introduced_by_item) + }).collect(), + }, + ) + } + fn non_macro_attr(&self, mark_used: bool) -> Lrc { self.non_macro_attrs[mark_used as usize].clone() } @@ -2808,6 +2842,16 @@ impl<'a> Resolver<'a> { seg.id = self.session.next_node_id(); seg } + + // For rustdoc. + pub fn graph_root(&self) -> Module<'a> { + self.graph_root + } + + // For rustdoc. + pub fn all_macros(&self) -> &FxHashMap { + &self.all_macros + } } fn names_to_string(names: &[Name]) -> String { diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 4270b162bafa4..caa7f08f68cff 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -432,13 +432,13 @@ fn macro_resolve(cx: &DocContext<'_>, path_str: &str) -> Option { let path = ast::Path::from_ident(Ident::from_str(path_str)); cx.enter_resolver(|resolver| { if let Ok((Some(ext), res)) = resolver.resolve_macro_path( - &path, None, &ParentScope::module(resolver.graph_root), false, false + &path, None, &ParentScope::module(resolver.graph_root()), false, false ) { if let SyntaxExtensionKind::LegacyBang { .. } = ext.kind { return Some(res.map_id(|_| panic!("unexpected id"))); } } - if let Some(res) = resolver.all_macros.get(&Symbol::intern(path_str)) { + if let Some(res) = resolver.all_macros().get(&Symbol::intern(path_str)) { return Some(res.map_id(|_| panic!("unexpected id"))); } None From 5fd796ad067f0c23c05524276279d057c9699c97 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 20 Oct 2019 03:19:12 +0300 Subject: [PATCH 19/23] rustc: Combine resolver outputs into a single struct --- src/librustc/ty/context.rs | 2 +- src/librustc/ty/mod.rs | 4 +- src/librustc_interface/passes.rs | 20 ++++------ src/librustc_interface/queries.rs | 3 +- src/librustc_resolve/lib.rs | 62 +++++++++++++++---------------- 5 files changed, 41 insertions(+), 50 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index d5a93e0290550..599601b352964 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1199,7 +1199,7 @@ impl<'tcx> TyCtxt<'tcx> { local_providers: ty::query::Providers<'tcx>, extern_providers: ty::query::Providers<'tcx>, arenas: &'tcx AllArenas, - resolutions: ty::Resolutions, + resolutions: ty::ResolverOutputs, hir: hir_map::Map<'tcx>, on_disk_query_result_cache: query::OnDiskCache<'tcx>, crate_name: &str, diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index feede00fea1c3..e1e88ffd8ea63 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -119,8 +119,8 @@ mod sty; // Data types -#[derive(Clone)] -pub struct Resolutions { +pub struct ResolverOutputs { + pub definitions: hir_map::Definitions, pub extern_crate_map: NodeMap, pub trait_map: TraitMap, pub maybe_unused_trait_imports: NodeSet, diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 3d6ea5354a9f8..18df4ee51b79b 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -6,12 +6,11 @@ use log::{info, warn, log_enabled}; use rustc::dep_graph::DepGraph; use rustc::hir; use rustc::hir::lowering::lower_crate; -use rustc::hir::map::Definitions; use rustc::hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc::lint; use rustc::middle::{self, reachable, resolve_lifetime, stability}; use rustc::middle::cstore::{CrateStore, MetadataLoader}; -use rustc::ty::{self, AllArenas, Resolutions, TyCtxt, GlobalCtxt}; +use rustc::ty::{self, AllArenas, ResolverOutputs, TyCtxt, GlobalCtxt}; use rustc::ty::steal::Steal; use rustc::traits; use rustc::util::common::{time, ErrorReported}; @@ -47,12 +46,10 @@ use syntax_ext; use rustc_serialize::json; use tempfile::Builder as TempFileBuilder; +use std::{env, fs, iter, mem}; use std::any::Any; -use std::env; use std::ffi::OsString; -use std::fs; use std::io::{self, Write}; -use std::iter; use std::path::PathBuf; use std::cell::RefCell; use std::rc::Rc; @@ -161,13 +158,12 @@ pub fn configure_and_expand( } pub struct ExpansionResult { - pub defs: Steal, - pub resolutions: Steal, + pub resolver_outputs: Steal, } impl ExpansionResult { - fn from_resolver_outputs((defs, resolutions): (Definitions, Resolutions)) -> Self { - ExpansionResult { defs: Steal::new(defs), resolutions: Steal::new(resolutions) } + fn from_resolver_outputs(resolver_outputs: ResolverOutputs) -> Self { + ExpansionResult { resolver_outputs: Steal::new(resolver_outputs) } } } @@ -789,8 +785,7 @@ pub fn create_global_ctxt( compiler: &Compiler, lint_store: Lrc, mut hir_forest: hir::map::Forest, - defs: hir::map::Definitions, - resolutions: Resolutions, + mut resolver_outputs: ResolverOutputs, outputs: OutputFilenames, crate_name: &str, ) -> BoxedGlobalCtxt { @@ -798,6 +793,7 @@ pub fn create_global_ctxt( let cstore = compiler.cstore.clone(); let codegen_backend = compiler.codegen_backend().clone(); let crate_name = crate_name.to_string(); + let defs = mem::take(&mut resolver_outputs.definitions); let ((), result) = BoxedGlobalCtxt::new(static move || { let sess = &*sess; @@ -830,7 +826,7 @@ pub fn create_global_ctxt( local_providers, extern_providers, &arenas, - resolutions, + resolver_outputs, hir_map, query_result_on_disk_cache, &crate_name, diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs index 847d21b051251..2ff5c69b145d8 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -234,8 +234,7 @@ impl Compiler { self, lint_store, hir_forest.steal(), - expansion.defs.steal(), - expansion.resolutions.steal(), + expansion.resolver_outputs.steal(), outputs, &crate_name)) }) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 57f1b5186cbab..5cdf4d2fb6926 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -28,7 +28,7 @@ use rustc::hir::def::{self, DefKind, PartialRes, CtorKind, CtorOf, NonMacroAttrK use rustc::hir::def::Namespace::*; use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefId}; use rustc::hir::{TraitMap, GlobMap}; -use rustc::ty::{self, DefIdTree}; +use rustc::ty::{self, DefIdTree, ResolverOutputs}; use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap}; use rustc::span_bug; @@ -1236,38 +1236,34 @@ impl<'a> Resolver<'a> { Default::default() } - pub fn into_outputs(self) -> (Definitions, ty::Resolutions) { - ( - self.definitions, - ty::Resolutions { - extern_crate_map: self.extern_crate_map, - export_map: self.export_map, - trait_map: self.trait_map, - glob_map: self.glob_map, - maybe_unused_trait_imports: self.maybe_unused_trait_imports, - maybe_unused_extern_crates: self.maybe_unused_extern_crates, - extern_prelude: self.extern_prelude.iter().map(|(ident, entry)| { - (ident.name, entry.introduced_by_item) - }).collect(), - }, - ) - } - - pub fn clone_outputs(&self) -> (Definitions, ty::Resolutions) { - ( - self.definitions.clone(), - ty::Resolutions { - extern_crate_map: self.extern_crate_map.clone(), - export_map: self.export_map.clone(), - trait_map: self.trait_map.clone(), - glob_map: self.glob_map.clone(), - maybe_unused_trait_imports: self.maybe_unused_trait_imports.clone(), - maybe_unused_extern_crates: self.maybe_unused_extern_crates.clone(), - extern_prelude: self.extern_prelude.iter().map(|(ident, entry)| { - (ident.name, entry.introduced_by_item) - }).collect(), - }, - ) + pub fn into_outputs(self) -> ResolverOutputs { + ResolverOutputs { + definitions: self.definitions, + extern_crate_map: self.extern_crate_map, + export_map: self.export_map, + trait_map: self.trait_map, + glob_map: self.glob_map, + maybe_unused_trait_imports: self.maybe_unused_trait_imports, + maybe_unused_extern_crates: self.maybe_unused_extern_crates, + extern_prelude: self.extern_prelude.iter().map(|(ident, entry)| { + (ident.name, entry.introduced_by_item) + }).collect(), + } + } + + pub fn clone_outputs(&self) -> ResolverOutputs { + ResolverOutputs { + definitions: self.definitions.clone(), + extern_crate_map: self.extern_crate_map.clone(), + export_map: self.export_map.clone(), + trait_map: self.trait_map.clone(), + glob_map: self.glob_map.clone(), + maybe_unused_trait_imports: self.maybe_unused_trait_imports.clone(), + maybe_unused_extern_crates: self.maybe_unused_extern_crates.clone(), + extern_prelude: self.extern_prelude.iter().map(|(ident, entry)| { + (ident.name, entry.introduced_by_item) + }).collect(), + } } fn non_macro_attr(&self, mark_used: bool) -> Lrc { From 3534ca8f4985afad9b8dfe93ab570b721b80210e Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 20 Oct 2019 03:28:36 +0300 Subject: [PATCH 20/23] Turn crate store into a resolver output --- src/librustc/hir/lowering.rs | 12 ++--- src/librustc/ty/context.rs | 6 +-- src/librustc/ty/mod.rs | 2 + src/librustc_interface/interface.rs | 8 --- src/librustc_interface/passes.rs | 60 ++++++++++----------- src/librustc_interface/queries.rs | 9 ++-- src/librustc_metadata/creader.rs | 26 +++++++-- src/librustc_metadata/cstore.rs | 16 +++--- src/librustc_metadata/cstore_impl.rs | 7 +-- src/librustc_resolve/build_reduced_graph.rs | 19 ++++--- src/librustc_resolve/lib.rs | 24 +++++---- src/librustc_resolve/resolve_imports.rs | 2 +- src/librustdoc/clean/inline.rs | 4 +- src/librustdoc/core.rs | 7 +-- 14 files changed, 102 insertions(+), 100 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 7971c33426b2e..002e6874466bb 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -83,8 +83,6 @@ pub struct LoweringContext<'a> { /// Used to assign IDs to HIR nodes that do not directly correspond to AST nodes. sess: &'a Session, - cstore: &'a dyn CrateStore, - resolver: &'a mut dyn Resolver, /// HACK(Centril): there is a cyclic dependency between the parser and lowering @@ -160,6 +158,8 @@ pub struct LoweringContext<'a> { } pub trait Resolver { + fn cstore(&self) -> &dyn CrateStore; + /// Obtains resolution for a `NodeId` with a single resolution. fn get_partial_res(&mut self, id: NodeId) -> Option; @@ -240,7 +240,6 @@ impl<'a> ImplTraitContext<'a> { pub fn lower_crate( sess: &Session, - cstore: &dyn CrateStore, dep_graph: &DepGraph, krate: &Crate, resolver: &mut dyn Resolver, @@ -256,7 +255,6 @@ pub fn lower_crate( LoweringContext { crate_root: sess.parse_sess.injected_crate_name.try_get().copied(), sess, - cstore, resolver, nt_to_tokenstream, items: BTreeMap::new(), @@ -980,7 +978,7 @@ impl<'a> LoweringContext<'a> { if id.is_local() { self.resolver.definitions().def_key(id.index) } else { - self.cstore.def_key(id) + self.resolver.cstore().def_key(id) } } @@ -1727,8 +1725,8 @@ impl<'a> LoweringContext<'a> { return n; } assert!(!def_id.is_local()); - let item_generics = - self.cstore.item_generics_cloned_untracked(def_id, self.sess); + let item_generics = self.resolver.cstore() + .item_generics_cloned_untracked(def_id, self.sess); let n = item_generics.own_counts().lifetimes; self.type_def_lifetime_params.insert(def_id, n); n diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 599601b352964..9b2e6df6bea14 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1027,7 +1027,7 @@ pub struct GlobalCtxt<'tcx> { interners: CtxtInterners<'tcx>, - cstore: &'tcx CrateStoreDyn, + cstore: Box, pub sess: &'tcx Session, @@ -1195,7 +1195,6 @@ impl<'tcx> TyCtxt<'tcx> { pub fn create_global_ctxt( s: &'tcx Session, lint_store: Lrc, - cstore: &'tcx CrateStoreDyn, local_providers: ty::query::Providers<'tcx>, extern_providers: ty::query::Providers<'tcx>, arenas: &'tcx AllArenas, @@ -1213,6 +1212,7 @@ impl<'tcx> TyCtxt<'tcx> { let common_lifetimes = CommonLifetimes::new(&interners); let common_consts = CommonConsts::new(&interners, &common_types); let dep_graph = hir.dep_graph.clone(); + let cstore = resolutions.cstore; let max_cnum = cstore.crates_untracked().iter().map(|c| c.as_usize()).max().unwrap_or(0); let mut providers = IndexVec::from_elem_n(extern_providers, max_cnum + 1); providers[LOCAL_CRATE] = local_providers; @@ -1428,7 +1428,7 @@ impl<'tcx> TyCtxt<'tcx> { StableHashingContext::new(self.sess, krate, self.hir().definitions(), - self.cstore) + &*self.cstore) } // This method makes sure that we have a DepNode and a Fingerprint for diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index e1e88ffd8ea63..90450494a1419 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -15,6 +15,7 @@ use rustc_macros::HashStable; use crate::ich::Fingerprint; use crate::ich::StableHashingContext; use crate::infer::canonical::Canonical; +use crate::middle::cstore::CrateStoreDyn; use crate::middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem}; use crate::middle::resolve_lifetime::ObjectLifetimeDefault; use crate::mir::Body; @@ -121,6 +122,7 @@ mod sty; pub struct ResolverOutputs { pub definitions: hir_map::Definitions, + pub cstore: Box, pub extern_crate_map: NodeMap, pub trait_map: TraitMap, pub maybe_unused_trait_imports: NodeSet, diff --git a/src/librustc_interface/interface.rs b/src/librustc_interface/interface.rs index 24ea0fc8bf635..e014e4ed0fdc1 100644 --- a/src/librustc_interface/interface.rs +++ b/src/librustc_interface/interface.rs @@ -11,7 +11,6 @@ use rustc_codegen_utils::codegen_backend::CodegenBackend; use rustc_data_structures::OnDrop; use rustc_data_structures::sync::Lrc; use rustc_data_structures::fx::{FxHashSet, FxHashMap}; -use rustc_metadata::cstore::CStore; use std::path::PathBuf; use std::result; use std::sync::{Arc, Mutex}; @@ -37,7 +36,6 @@ pub struct Compiler { pub(crate) output_dir: Option, pub(crate) output_file: Option, pub(crate) queries: Queries, - pub(crate) cstore: Lrc, pub(crate) crate_name: Option, pub(crate) register_lints: Option>, } @@ -49,9 +47,6 @@ impl Compiler { pub fn codegen_backend(&self) -> &Lrc> { &self.codegen_backend } - pub fn cstore(&self) -> &Lrc { - &self.cstore - } pub fn source_map(&self) -> &Lrc { &self.source_map } @@ -160,13 +155,10 @@ where config.lint_caps, ); - let cstore = Lrc::new(CStore::new(codegen_backend.metadata_loader())); - let compiler = Compiler { sess, codegen_backend, source_map, - cstore, input: config.input, input_path: config.input_path, output_dir: config.output_dir, diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 18df4ee51b79b..80ce203b4fbb6 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -9,7 +9,7 @@ use rustc::hir::lowering::lower_crate; use rustc::hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc::lint; use rustc::middle::{self, reachable, resolve_lifetime, stability}; -use rustc::middle::cstore::{CrateStore, MetadataLoader}; +use rustc::middle::cstore::{CrateStore, MetadataLoader, MetadataLoaderDyn}; use rustc::ty::{self, AllArenas, ResolverOutputs, TyCtxt, GlobalCtxt}; use rustc::ty::steal::Steal; use rustc::traits; @@ -23,8 +23,7 @@ use rustc_codegen_utils::link::filename_for_metadata; use rustc_data_structures::{box_region_allow_access, declare_box_region_type, parallel}; use rustc_data_structures::sync::{Lrc, ParallelIterator, par_iter}; use rustc_incremental; -use rustc_metadata::creader::CrateLoader; -use rustc_metadata::cstore::{self, CStore}; +use rustc_metadata::cstore; use rustc_mir as mir; use rustc_passes::{self, ast_validation, hir_stats, layout_test}; use rustc_plugin as plugin; @@ -116,7 +115,7 @@ declare_box_region_type!( pub fn configure_and_expand( sess: Lrc, lint_store: Lrc, - cstore: Lrc, + metadata_loader: Box, krate: ast::Crate, crate_name: &str, plugin_info: PluginInfo, @@ -129,16 +128,14 @@ pub fn configure_and_expand( let crate_name = crate_name.to_string(); let (result, resolver) = BoxedResolver::new(static move || { let sess = &*sess; - let crate_loader = CrateLoader::new(sess, &*cstore, &crate_name); let resolver_arenas = Resolver::arenas(); let res = configure_and_expand_inner( sess, &lint_store, - &*cstore, krate, &crate_name, &resolver_arenas, - &crate_loader, + &*metadata_loader, plugin_info, ); let mut resolver = match res { @@ -275,11 +272,10 @@ pub fn register_plugins<'a>( fn configure_and_expand_inner<'a>( sess: &'a Session, lint_store: &'a lint::LintStore, - cstore: &'a CStore, mut krate: ast::Crate, crate_name: &str, resolver_arenas: &'a ResolverArenas<'a>, - crate_loader: &'a CrateLoader<'a>, + metadata_loader: &'a MetadataLoaderDyn, plugin_info: PluginInfo, ) -> Result<(ast::Crate, Resolver<'a>)> { time(sess, "pre-AST-expansion lint checks", || { @@ -293,10 +289,9 @@ fn configure_and_expand_inner<'a>( let mut resolver = Resolver::new( sess, - cstore, &krate, crate_name, - crate_loader, + metadata_loader, &resolver_arenas, ); syntax_ext::register_builtin_macros(&mut resolver, sess.edition()); @@ -496,7 +491,6 @@ fn configure_and_expand_inner<'a>( pub fn lower_to_hir( sess: &Session, lint_store: &lint::LintStore, - cstore: &CStore, resolver: &mut Resolver<'_>, dep_graph: &DepGraph, krate: &ast::Crate, @@ -504,7 +498,7 @@ pub fn lower_to_hir( // Lower AST to HIR. let hir_forest = time(sess, "lowering AST -> HIR", || { let nt_to_tokenstream = syntax::parse::nt_to_tokenstream; - let hir_crate = lower_crate(sess, cstore, &dep_graph, &krate, resolver, nt_to_tokenstream); + let hir_crate = lower_crate(sess, &dep_graph, &krate, resolver, nt_to_tokenstream); if sess.opts.debugging_opts.hir_stats { hir_stats::print_hir_stats(&hir_crate); @@ -610,8 +604,12 @@ fn escape_dep_filename(filename: &FileName) -> String { filename.to_string().replace(" ", "\\ ") } -fn write_out_deps(compiler: &Compiler, outputs: &OutputFilenames, out_filenames: &[PathBuf]) { - let sess = &compiler.sess; +fn write_out_deps( + sess: &Session, + boxed_resolver: &Steal>>, + outputs: &OutputFilenames, + out_filenames: &[PathBuf], +) { // Write out dependency rules to the dep-info file if requested if !sess.opts.output_types.contains_key(&OutputType::DepInfo) { return; @@ -630,18 +628,20 @@ fn write_out_deps(compiler: &Compiler, outputs: &OutputFilenames, out_filenames: .collect(); if sess.binary_dep_depinfo() { - for cnum in compiler.cstore.crates_untracked() { - let source = compiler.cstore.crate_source_untracked(cnum); - if let Some((path, _)) = source.dylib { - files.push(escape_dep_filename(&FileName::Real(path))); - } - if let Some((path, _)) = source.rlib { - files.push(escape_dep_filename(&FileName::Real(path))); + boxed_resolver.borrow().borrow_mut().access(|resolver| { + for cnum in resolver.cstore().crates_untracked() { + let source = resolver.cstore().crate_source_untracked(cnum); + if let Some((path, _)) = source.dylib { + files.push(escape_dep_filename(&FileName::Real(path))); + } + if let Some((path, _)) = source.rlib { + files.push(escape_dep_filename(&FileName::Real(path))); + } + if let Some((path, _)) = source.rmeta { + files.push(escape_dep_filename(&FileName::Real(path))); + } } - if let Some((path, _)) = source.rmeta { - files.push(escape_dep_filename(&FileName::Real(path))); - } - } + }); } let mut file = fs::File::create(&deps_filename)?; @@ -679,6 +679,7 @@ pub fn prepare_outputs( sess: &Session, compiler: &Compiler, krate: &ast::Crate, + boxed_resolver: &Steal>>, crate_name: &str ) -> Result { // FIXME: rustdoc passes &[] instead of &krate.attrs here @@ -720,7 +721,7 @@ pub fn prepare_outputs( } } - write_out_deps(compiler, &outputs, &output_paths); + write_out_deps(sess, boxed_resolver, &outputs, &output_paths); let only_dep_info = sess.opts.output_types.contains_key(&OutputType::DepInfo) && sess.opts.output_types.len() == 1; @@ -790,21 +791,19 @@ pub fn create_global_ctxt( crate_name: &str, ) -> BoxedGlobalCtxt { let sess = compiler.session().clone(); - let cstore = compiler.cstore.clone(); let codegen_backend = compiler.codegen_backend().clone(); let crate_name = crate_name.to_string(); let defs = mem::take(&mut resolver_outputs.definitions); let ((), result) = BoxedGlobalCtxt::new(static move || { let sess = &*sess; - let cstore = &*cstore; let global_ctxt: Option>; let arenas = AllArenas::new(); // Construct the HIR map. let hir_map = time(sess, "indexing HIR", || { - hir::map::map_crate(sess, cstore, &mut hir_forest, &defs) + hir::map::map_crate(sess, &*resolver_outputs.cstore, &mut hir_forest, &defs) }); let query_result_on_disk_cache = time(sess, "load query result cache", || { @@ -822,7 +821,6 @@ pub fn create_global_ctxt( let gcx = TyCtxt::create_global_ctxt( sess, lint_store, - cstore, local_providers, extern_providers, &arenas, diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs index 2ff5c69b145d8..b5c356bf05a1b 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -164,7 +164,7 @@ impl Compiler { passes::configure_and_expand( self.sess.clone(), lint_store.clone(), - self.cstore().clone(), + self.codegen_backend().metadata_loader(), krate, &crate_name, plugin_info, @@ -202,7 +202,6 @@ impl Compiler { passes::lower_to_hir( self.session(), lint_store, - self.cstore(), resolver, &*self.dep_graph()?.peek(), &krate @@ -214,11 +213,11 @@ impl Compiler { pub fn prepare_outputs(&self) -> Result<&Query> { self.queries.prepare_outputs.compute(|| { - let krate = self.expansion()?; - let krate = krate.peek(); + let expansion_result = self.expansion()?; + let (krate, boxed_resolver) = &*expansion_result.peek(); let crate_name = self.crate_name()?; let crate_name = crate_name.peek(); - passes::prepare_outputs(self.session(), self, &krate.0, &*crate_name) + passes::prepare_outputs(self.session(), self, &krate, &boxed_resolver, &crate_name) }) } diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 2eaf7536a70ad..5f4abbc3bdc88 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -14,7 +14,7 @@ use rustc::session::{Session, CrateDisambiguator}; use rustc::session::config::{Sanitizer, self}; use rustc_target::spec::{PanicStrategy, TargetTriple}; use rustc::session::search_paths::PathKind; -use rustc::middle::cstore::{CrateSource, ExternCrate, ExternCrateSource}; +use rustc::middle::cstore::{CrateSource, ExternCrate, ExternCrateSource, MetadataLoaderDyn}; use rustc::util::common::record_time; use rustc::util::nodemap::FxHashSet; use rustc::hir::map::Definitions; @@ -38,9 +38,12 @@ crate struct Library { } pub struct CrateLoader<'a> { + // Immutable configuration. sess: &'a Session, - cstore: &'a CStore, + metadata_loader: &'a MetadataLoaderDyn, local_crate_name: Symbol, + // Mutable output. + cstore: CStore, } fn dump_crates(cstore: &CStore) { @@ -75,14 +78,27 @@ impl<'a> LoadError<'a> { } impl<'a> CrateLoader<'a> { - pub fn new(sess: &'a Session, cstore: &'a CStore, local_crate_name: &str) -> Self { + pub fn new( + sess: &'a Session, + metadata_loader: &'a MetadataLoaderDyn, + local_crate_name: &str, + ) -> Self { CrateLoader { sess, - cstore, + metadata_loader, local_crate_name: Symbol::intern(local_crate_name), + cstore: Default::default(), } } + pub fn cstore(&self) -> &CStore { + &self.cstore + } + + pub fn into_cstore(self) -> CStore { + self.cstore + } + fn existing_match(&self, name: Symbol, hash: Option<&Svh>, kind: PathKind) -> Option { let mut ret = None; @@ -346,7 +362,7 @@ impl<'a> CrateLoader<'a> { rejected_via_filename: vec![], should_match_name: true, is_proc_macro: Some(false), - metadata_loader: &*self.cstore.metadata_loader, + metadata_loader: self.metadata_loader, }; self.load(&mut locate_ctxt).map(|r| (r, None)).or_else(|| { diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index a2920884409ca..09d37a0070338 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -5,12 +5,13 @@ use crate::schema; use rustc::dep_graph::DepNodeIndex; use rustc::hir::def_id::{CrateNum, DefIndex}; use rustc::hir::map::definitions::DefPathTable; -use rustc::middle::cstore::{CrateSource, DepKind, ExternCrate, MetadataLoaderDyn}; +use rustc::middle::cstore::{CrateSource, DepKind, ExternCrate}; use rustc::mir::interpret::AllocDecodingState; use rustc_index::vec::IndexVec; use rustc::util::nodemap::FxHashMap; use rustc_data_structures::sync::{Lrc, RwLock, Lock, MetadataRef, AtomicCell}; use syntax::ast; +use syntax::edition::Edition; use syntax_expand::base::SyntaxExtension; use syntax_pos; use proc_macro::bridge::client::ProcMacro; @@ -36,7 +37,7 @@ crate struct ImportedSourceFile { pub translated_source_file: Lrc, } -pub struct CrateMetadata { +crate struct CrateMetadata { /// The primary crate data - binary metadata blob. crate blob: MetadataBlob, @@ -94,28 +95,29 @@ pub struct CrateMetadata { crate extern_crate: Lock>, } +#[derive(Clone)] pub struct CStore { metas: RwLock>>>, - crate metadata_loader: Box, } pub enum LoadedMacro { - MacroDef(ast::Item), + MacroDef(ast::Item, Edition), ProcMacro(SyntaxExtension), } -impl CStore { - pub fn new(metadata_loader: Box) -> CStore { +impl Default for CStore { + fn default() -> Self { CStore { // We add an empty entry for LOCAL_CRATE (which maps to zero) in // order to make array indices in `metas` match with the // corresponding `CrateNum`. This first entry will always remain // `None`. metas: RwLock::new(IndexVec::from_elem_n(None, 1)), - metadata_loader, } } +} +impl CStore { crate fn alloc_new_crate_num(&self) -> CrateNum { let mut metas = self.metas.borrow_mut(); let cnum = CrateNum::new(metas.len()); diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 6aba66a79ab3b..c20017ffef660 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -29,7 +29,6 @@ use std::sync::Arc; use syntax::ast; use syntax::attr; use syntax::source_map; -use syntax::edition::Edition; use syntax::parse::source_file_to_stream; use syntax::parse::parser::emit_unclosed_delims; use syntax::source_map::Spanned; @@ -411,10 +410,6 @@ impl cstore::CStore { } } - pub fn crate_edition_untracked(&self, cnum: CrateNum) -> Edition { - self.get_crate_data(cnum).root.edition - } - pub fn struct_field_names_untracked(&self, def: DefId, sess: &Session) -> Vec> { self.get_crate_data(def.krate).get_struct_field_names(def.index, sess) } @@ -470,7 +465,7 @@ impl cstore::CStore { }), vis: source_map::respan(local_span.shrink_to_lo(), ast::VisibilityKind::Inherited), tokens: None, - }) + }, data.root.edition) } pub fn associated_item_cloned_untracked(&self, def: DefId) -> ty::AssocItem { diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 6444a82fd7379..c0fb8e33a819e 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -110,9 +110,9 @@ impl<'a> Resolver<'a> { } let (name, parent) = if def_id.index == CRATE_DEF_INDEX { - (self.cstore.crate_name_untracked(def_id.krate), None) + (self.cstore().crate_name_untracked(def_id.krate), None) } else { - let def_key = self.cstore.def_key(def_id); + let def_key = self.cstore().def_key(def_id); (def_key.disambiguated_data.data.get_opt_name().unwrap(), Some(self.get_module(DefId { index: def_key.parent.unwrap(), ..def_id }))) }; @@ -153,9 +153,8 @@ impl<'a> Resolver<'a> { return Some(ext.clone()); } - let ext = Lrc::new(match self.cstore.load_macro_untracked(def_id, &self.session) { - LoadedMacro::MacroDef(item) => - self.compile_macro(&item, self.cstore.crate_edition_untracked(def_id.krate)), + let ext = Lrc::new(match self.cstore().load_macro_untracked(def_id, &self.session) { + LoadedMacro::MacroDef(item, edition) => self.compile_macro(&item, edition), LoadedMacro::ProcMacro(ext) => ext, }); @@ -177,7 +176,7 @@ impl<'a> Resolver<'a> { crate fn build_reduced_graph_external(&mut self, module: Module<'a>) { let def_id = module.def_id().expect("unpopulated module without a def-id"); - for child in self.cstore.item_children_untracked(def_id, self.session) { + for child in self.cstore().item_children_untracked(def_id, self.session) { let child = child.map_id(|_| panic!("unexpected id")); BuildReducedGraphVisitor { r: self, parent_scope: ParentScope::module(module) } .build_reduced_graph_for_external_crate_res(child); @@ -885,19 +884,19 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { bug!("unexpected resolution: {:?}", res) } // Record some extra data for better diagnostics. + let cstore = self.r.cstore(); match res { Res::Def(DefKind::Struct, def_id) | Res::Def(DefKind::Union, def_id) => { - let field_names = - self.r.cstore.struct_field_names_untracked(def_id, self.r.session); + let field_names = cstore.struct_field_names_untracked(def_id, self.r.session); self.insert_field_names(def_id, field_names); } Res::Def(DefKind::Method, def_id) => { - if self.r.cstore.associated_item_cloned_untracked(def_id).method_has_self_argument { + if cstore.associated_item_cloned_untracked(def_id).method_has_self_argument { self.r.has_self.insert(def_id); } } Res::Def(DefKind::Ctor(CtorOf::Struct, ..), def_id) => { - let parent = self.r.cstore.def_key(def_id).parent; + let parent = cstore.def_key(def_id).parent; if let Some(struct_def_id) = parent.map(|index| DefId { index, ..def_id }) { self.r.struct_constructors.insert(struct_def_id, (res, vis)); } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 5cdf4d2fb6926..1c67395fbf0b2 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -21,7 +21,7 @@ use Determinacy::*; use rustc::hir::map::Definitions; use rustc::hir::{self, PrimTy, Bool, Char, Float, Int, Uint, Str}; -use rustc::middle::cstore::CrateStore; +use rustc::middle::cstore::{CrateStore, MetadataLoaderDyn}; use rustc::session::Session; use rustc::lint; use rustc::hir::def::{self, DefKind, PartialRes, CtorKind, CtorOf, NonMacroAttrKind, ExportMap}; @@ -829,7 +829,6 @@ pub struct ExternPreludeEntry<'a> { /// This is the visitor that walks the whole crate. pub struct Resolver<'a> { session: &'a Session, - cstore: &'a CStore, definitions: Definitions, @@ -916,7 +915,7 @@ pub struct Resolver<'a> { arenas: &'a ResolverArenas<'a>, dummy_binding: &'a NameBinding<'a>, - crate_loader: &'a CrateLoader<'a>, + crate_loader: CrateLoader<'a>, macro_names: FxHashSet, builtin_macros: FxHashMap, macro_use_prelude: FxHashMap>, @@ -1015,7 +1014,7 @@ impl<'a, 'b> DefIdTree for &'a Resolver<'b> { fn parent(self, id: DefId) -> Option { match id.krate { LOCAL_CRATE => self.definitions.def_key(id.index).parent, - _ => self.cstore.def_key(id).parent, + _ => self.cstore().def_key(id).parent, }.map(|index| DefId { index, ..id }) } } @@ -1023,6 +1022,10 @@ impl<'a, 'b> DefIdTree for &'a Resolver<'b> { /// 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> hir::lowering::Resolver for Resolver<'a> { + fn cstore(&self) -> &dyn CrateStore { + self.cstore() + } + fn resolve_str_path( &mut self, span: Span, @@ -1083,10 +1086,9 @@ impl<'a> hir::lowering::Resolver for Resolver<'a> { impl<'a> Resolver<'a> { pub fn new(session: &'a Session, - cstore: &'a CStore, krate: &Crate, crate_name: &str, - crate_loader: &'a CrateLoader<'a>, + metadata_loader: &'a MetadataLoaderDyn, arenas: &'a ResolverArenas<'a>) -> Resolver<'a> { let root_def_id = DefId::local(CRATE_DEF_INDEX); @@ -1147,8 +1149,6 @@ impl<'a> Resolver<'a> { Resolver { session, - cstore, - definitions, // The outermost module has def ID 0; this is not reflected in the @@ -1202,7 +1202,7 @@ impl<'a> Resolver<'a> { vis: ty::Visibility::Public, }), - crate_loader, + crate_loader: CrateLoader::new(session, metadata_loader, crate_name), macro_names: FxHashSet::default(), builtin_macros: Default::default(), macro_use_prelude: FxHashMap::default(), @@ -1239,6 +1239,7 @@ impl<'a> Resolver<'a> { pub fn into_outputs(self) -> ResolverOutputs { ResolverOutputs { definitions: self.definitions, + cstore: Box::new(self.crate_loader.into_cstore()), extern_crate_map: self.extern_crate_map, export_map: self.export_map, trait_map: self.trait_map, @@ -1254,6 +1255,7 @@ impl<'a> Resolver<'a> { pub fn clone_outputs(&self) -> ResolverOutputs { ResolverOutputs { definitions: self.definitions.clone(), + cstore: Box::new(self.cstore().clone()), extern_crate_map: self.extern_crate_map.clone(), export_map: self.export_map.clone(), trait_map: self.trait_map.clone(), @@ -1266,6 +1268,10 @@ impl<'a> Resolver<'a> { } } + pub fn cstore(&self) -> &CStore { + self.crate_loader.cstore() + } + fn non_macro_attr(&self, mark_used: bool) -> Lrc { self.non_macro_attrs[mark_used as usize].clone() } diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 34edd5eaf4fc7..31340ddd68372 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -1344,7 +1344,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { if res != Res::Err { if let Some(def_id) = res.opt_def_id() { if !def_id.is_local() { - this.cstore.export_macros_untracked(def_id.krate); + this.cstore().export_macros_untracked(def_id.krate); } } reexports.push(Export { diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index e7cc8b76e485d..a6a8fec429e20 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -479,8 +479,8 @@ fn build_static(cx: &DocContext<'_>, did: DefId, mutable: bool) -> clean::Static fn build_macro(cx: &DocContext<'_>, did: DefId, name: ast::Name) -> clean::ItemEnum { let imported_from = cx.tcx.original_crate_name(did.krate); - match cx.cstore.load_macro_untracked(did, cx.sess()) { - LoadedMacro::MacroDef(def) => { + match cx.enter_resolver(|r| r.cstore().load_macro_untracked(did, cx.sess())) { + LoadedMacro::MacroDef(def, _) => { let matchers: hir::HirVec = if let ast::ItemKind::MacroDef(ref def) = def.kind { let tts: Vec<_> = def.stream().into_trees().collect(); tts.chunks(4).map(|arm| arm[0].span()).collect() diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 39ab30e8ecfc7..b227f432a4e98 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -12,7 +12,6 @@ use rustc::util::nodemap::{FxHashMap, FxHashSet}; use rustc_interface::interface; use rustc_driver::abort_on_err; use rustc_resolve as resolve; -use rustc_metadata::cstore::CStore; use syntax::source_map; use syntax::attr; @@ -43,7 +42,6 @@ pub struct DocContext<'tcx> { pub tcx: TyCtxt<'tcx>, pub resolver: Rc>, - pub cstore: Lrc, /// Later on moved into `html::render::CACHE_KEY` pub renderinfo: RefCell, /// Later on moved through `clean::Crate` into `html::render::CACHE_KEY` @@ -117,9 +115,7 @@ impl<'tcx> DocContext<'tcx> { .def_path_table() .next_id() } else { - self.cstore - .def_path_table(crate_num) - .next_id() + self.enter_resolver(|r| r.cstore().def_path_table(crate_num).next_id()) }; DefId { @@ -376,7 +372,6 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt let mut ctxt = DocContext { tcx, resolver, - cstore: compiler.cstore().clone(), external_traits: Default::default(), active_extern_traits: Default::default(), renderinfo: RefCell::new(renderinfo), From c5fee33e7aa71d7cfc5abd8848a81924cafd2b15 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 20 Oct 2019 12:49:14 +0300 Subject: [PATCH 21/23] rustc_metadata: Remove `RwLock` from `CStore` --- src/librustc_metadata/creader.rs | 26 +++++++++++++++----------- src/librustc_metadata/cstore.rs | 25 +++++++++++-------------- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 5f4abbc3bdc88..420595a690d5e 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -179,7 +179,7 @@ impl<'a> CrateLoader<'a> { } fn register_crate( - &self, + &mut self, host_lib: Option, root: Option<&CratePaths>, span: Span, @@ -319,7 +319,7 @@ impl<'a> CrateLoader<'a> { } fn resolve_crate<'b>( - &'b self, + &'b mut self, name: Symbol, span: Span, dep_kind: DepKind, @@ -329,7 +329,7 @@ impl<'a> CrateLoader<'a> { } fn maybe_resolve_crate<'b>( - &'b self, + &'b mut self, name: Symbol, span: Span, mut dep_kind: DepKind, @@ -458,7 +458,7 @@ impl<'a> CrateLoader<'a> { } // Go through the crate metadata and load any crates that it references - fn resolve_crate_deps(&self, + fn resolve_crate_deps(&mut self, root: &CratePaths, crate_root: &CrateRoot<'_>, metadata: &MetadataBlob, @@ -519,7 +519,7 @@ impl<'a> CrateLoader<'a> { decls } - fn inject_panic_runtime(&self, krate: &ast::Crate) { + fn inject_panic_runtime(&mut self, krate: &ast::Crate) { // If we're only compiling an rlib, then there's no need to select a // panic runtime, so we just skip this section entirely. let any_non_rlib = self.sess.crate_types.borrow().iter().any(|ct| { @@ -600,7 +600,7 @@ impl<'a> CrateLoader<'a> { &|data| data.root.needs_panic_runtime); } - fn inject_sanitizer_runtime(&self) { + fn inject_sanitizer_runtime(&mut self) { if let Some(ref sanitizer) = self.sess.opts.debugging_opts.sanitizer { // Sanitizers can only be used on some tested platforms with // executables linked to `std` @@ -698,7 +698,7 @@ impl<'a> CrateLoader<'a> { } } - fn inject_profiler_runtime(&self) { + fn inject_profiler_runtime(&mut self) { if self.sess.opts.debugging_opts.profile || self.sess.opts.cg.profile_generate.enabled() { @@ -852,7 +852,7 @@ impl<'a> CrateLoader<'a> { }); } - pub fn postprocess(&self, krate: &ast::Crate) { + pub fn postprocess(&mut self, krate: &ast::Crate) { self.inject_sanitizer_runtime(); self.inject_profiler_runtime(); self.inject_allocator_crate(krate); @@ -863,7 +863,11 @@ impl<'a> CrateLoader<'a> { } } - pub fn process_extern_crate(&self, item: &ast::Item, definitions: &Definitions) -> CrateNum { + pub fn process_extern_crate( + &mut self, + item: &ast::Item, + definitions: &Definitions, + ) -> CrateNum { match item.kind { ast::ItemKind::ExternCrate(orig_name) => { debug!("resolving extern crate stmt. ident: {} orig_name: {:?}", @@ -902,7 +906,7 @@ impl<'a> CrateLoader<'a> { } } - pub fn process_path_extern(&self, name: Symbol, span: Span) -> CrateNum { + pub fn process_path_extern(&mut self, name: Symbol, span: Span) -> CrateNum { let cnum = self.resolve_crate(name, span, DepKind::Explicit, None).0; self.update_extern_crate( @@ -920,7 +924,7 @@ impl<'a> CrateLoader<'a> { cnum } - pub fn maybe_process_path_extern(&self, name: Symbol, span: Span) -> Option { + pub fn maybe_process_path_extern(&mut self, name: Symbol, span: Span) -> Option { let cnum = self.maybe_resolve_crate(name, span, DepKind::Explicit, None).ok()?.0; self.update_extern_crate( diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index 09d37a0070338..a0589b1f3bd3e 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -97,7 +97,7 @@ crate struct CrateMetadata { #[derive(Clone)] pub struct CStore { - metas: RwLock>>>, + metas: IndexVec>>, } pub enum LoadedMacro { @@ -112,34 +112,31 @@ impl Default for CStore { // order to make array indices in `metas` match with the // corresponding `CrateNum`. This first entry will always remain // `None`. - metas: RwLock::new(IndexVec::from_elem_n(None, 1)), + metas: IndexVec::from_elem_n(None, 1), } } } impl CStore { - crate fn alloc_new_crate_num(&self) -> CrateNum { - let mut metas = self.metas.borrow_mut(); - let cnum = CrateNum::new(metas.len()); - metas.push(None); - cnum + crate fn alloc_new_crate_num(&mut self) -> CrateNum { + self.metas.push(None); + CrateNum::new(self.metas.len() - 1) } crate fn get_crate_data(&self, cnum: CrateNum) -> Lrc { - self.metas.borrow()[cnum].clone() + self.metas[cnum].clone() .unwrap_or_else(|| panic!("Failed to get crate data for {:?}", cnum)) } - crate fn set_crate_data(&self, cnum: CrateNum, data: Lrc) { - let mut metas = self.metas.borrow_mut(); - assert!(metas[cnum].is_none(), "Overwriting crate metadata entry"); - metas[cnum] = Some(data); + crate fn set_crate_data(&mut self, cnum: CrateNum, data: Lrc) { + assert!(self.metas[cnum].is_none(), "Overwriting crate metadata entry"); + self.metas[cnum] = Some(data); } crate fn iter_crate_data(&self, mut i: I) where I: FnMut(CrateNum, &Lrc) { - for (k, v) in self.metas.borrow().iter_enumerated() { + for (k, v) in self.metas.iter_enumerated() { if let &Some(ref v) = v { i(k, v); } @@ -170,7 +167,7 @@ impl CStore { crate fn do_postorder_cnums_untracked(&self) -> Vec { let mut ordering = Vec::new(); - for (num, v) in self.metas.borrow().iter_enumerated() { + for (num, v) in self.metas.iter_enumerated() { if let &Some(_) = v { self.push_dependencies_in_postorder(&mut ordering, num); } From 9f5a530b84c75e34c183eea50ce9a5d7fcf6581b Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 20 Oct 2019 14:06:48 +0300 Subject: [PATCH 22/23] rustc_metadata: Minimize use of `Lrc` in crate store Crate metadatas are still stored as `Lrc` in `CStore` because crate store has to be cloneable due to `Resolver::clone_outputs`. --- src/librustc/middle/cstore.rs | 6 ++--- src/librustc/ty/context.rs | 23 ++++++----------- src/librustc_metadata/creader.rs | 37 ++++++++++++++-------------- src/librustc_metadata/cstore.rs | 12 ++++----- src/librustc_metadata/cstore_impl.rs | 10 ++++---- 5 files changed, 41 insertions(+), 47 deletions(-) diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 8205383da9892..d5558db2397e7 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -16,7 +16,7 @@ use syntax::ast; use syntax::symbol::Symbol; use syntax_pos::Span; use rustc_target::spec::Target; -use rustc_data_structures::sync::{self, MetadataRef, Lrc}; +use rustc_data_structures::sync::{self, MetadataRef}; use rustc_macros::HashStable; pub use self::NativeLibraryKind::*; @@ -203,13 +203,13 @@ pub type MetadataLoaderDyn = dyn MetadataLoader + Sync; /// (it'd break incremental compilation) and should only be called pre-HIR (e.g. /// during resolve) pub trait CrateStore { - fn crate_data_as_rc_any(&self, krate: CrateNum) -> Lrc; + fn crate_data_as_any(&self, cnum: CrateNum) -> &dyn Any; // resolve fn def_key(&self, def: DefId) -> DefKey; fn def_path(&self, def: DefId) -> hir_map::DefPath; fn def_path_hash(&self, def: DefId) -> hir_map::DefPathHash; - fn def_path_table(&self, cnum: CrateNum) -> Lrc; + fn def_path_table(&self, cnum: CrateNum) -> &DefPathTable; // "queries" used in resolve that aren't tracked for incremental compilation fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol; diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 9b2e6df6bea14..f99298281fecc 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1213,34 +1213,27 @@ impl<'tcx> TyCtxt<'tcx> { let common_consts = CommonConsts::new(&interners, &common_types); let dep_graph = hir.dep_graph.clone(); let cstore = resolutions.cstore; - let max_cnum = cstore.crates_untracked().iter().map(|c| c.as_usize()).max().unwrap_or(0); + let crates = cstore.crates_untracked(); + let max_cnum = crates.iter().map(|c| c.as_usize()).max().unwrap_or(0); let mut providers = IndexVec::from_elem_n(extern_providers, max_cnum + 1); providers[LOCAL_CRATE] = local_providers; let def_path_hash_to_def_id = if s.opts.build_dep_graph() { - let upstream_def_path_tables: Vec<(CrateNum, Lrc<_>)> = cstore - .crates_untracked() + let def_path_tables = crates .iter() .map(|&cnum| (cnum, cstore.def_path_table(cnum))) - .collect(); - - let def_path_tables = || { - upstream_def_path_tables - .iter() - .map(|&(cnum, ref rc)| (cnum, &**rc)) - .chain(iter::once((LOCAL_CRATE, hir.definitions().def_path_table()))) - }; + .chain(iter::once((LOCAL_CRATE, hir.definitions().def_path_table()))); // Precompute the capacity of the hashmap so we don't have to // re-allocate when populating it. - let capacity = def_path_tables().map(|(_, t)| t.size()).sum::(); + let capacity = def_path_tables.clone().map(|(_, t)| t.size()).sum::(); let mut map: FxHashMap<_, _> = FxHashMap::with_capacity_and_hasher( capacity, ::std::default::Default::default() ); - for (cnum, def_path_table) in def_path_tables() { + for (cnum, def_path_table) in def_path_tables { def_path_table.add_def_path_hashes_to(cnum, &mut map); } @@ -1417,8 +1410,8 @@ impl<'tcx> TyCtxt<'tcx> { // Note that this is *untracked* and should only be used within the query // system if the result is otherwise tracked through queries - pub fn crate_data_as_rc_any(self, cnum: CrateNum) -> Lrc { - self.cstore.crate_data_as_rc_any(cnum) + pub fn crate_data_as_any(self, cnum: CrateNum) -> &'tcx dyn Any { + self.cstore.crate_data_as_any(cnum) } #[inline(always)] diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 420595a690d5e..f0a68058de8ca 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -3,7 +3,7 @@ use crate::cstore::{self, CStore, MetadataBlob}; use crate::locator::{self, CratePaths}; use crate::schema::{CrateRoot, CrateDep}; -use rustc_data_structures::sync::{Lrc, RwLock, Lock, AtomicCell}; +use rustc_data_structures::sync::{RwLock, Lock, AtomicCell}; use rustc::hir::def_id::CrateNum; use rustc_data_structures::svh::Svh; @@ -186,7 +186,7 @@ impl<'a> CrateLoader<'a> { lib: Library, dep_kind: DepKind, name: Symbol - ) -> (CrateNum, Lrc) { + ) -> CrateNum { let _prof_timer = self.sess.prof.generic_activity("metadata_register_crate"); let Library { source, metadata } = lib; @@ -240,9 +240,9 @@ impl<'a> CrateLoader<'a> { crate_root.def_path_table.decode((&metadata, self.sess)) }); - let cmeta = cstore::CrateMetadata { + self.cstore.set_crate_data(cnum, cstore::CrateMetadata { extern_crate: Lock::new(None), - def_path_table: Lrc::new(def_path_table), + def_path_table, trait_impls, root: crate_root, blob: metadata, @@ -256,11 +256,9 @@ impl<'a> CrateLoader<'a> { private_dep, raw_proc_macros, dep_node_index: AtomicCell::new(DepNodeIndex::INVALID), - }; + }); - let cmeta = Lrc::new(cmeta); - self.cstore.set_crate_data(cnum, cmeta.clone()); - (cnum, cmeta) + cnum } fn load_proc_macro<'b>( @@ -324,7 +322,7 @@ impl<'a> CrateLoader<'a> { span: Span, dep_kind: DepKind, dep: Option<(&'b CratePaths, &'b CrateDep)>, - ) -> (CrateNum, Lrc) { + ) -> CrateNum { self.maybe_resolve_crate(name, span, dep_kind, dep).unwrap_or_else(|err| err.report()) } @@ -334,7 +332,7 @@ impl<'a> CrateLoader<'a> { span: Span, mut dep_kind: DepKind, dep: Option<(&'b CratePaths, &'b CrateDep)>, - ) -> Result<(CrateNum, Lrc), LoadError<'b>> { + ) -> Result> { info!("resolving crate `{}`", name); let (root, hash, extra_filename, path_kind) = match dep { Some((root, dep)) => @@ -380,7 +378,7 @@ impl<'a> CrateLoader<'a> { data.dep_kind.with_lock(|data_dep_kind| { *data_dep_kind = cmp::max(*data_dep_kind, dep_kind); }); - Ok((cnum, data)) + Ok(cnum) } (LoadResult::Loaded(library), host_library) => { Ok(self.register_crate(host_library, root, span, library, dep_kind, name)) @@ -484,7 +482,7 @@ impl<'a> CrateLoader<'a> { DepKind::MacrosOnly => DepKind::MacrosOnly, _ => dep.kind, }; - self.resolve_crate(dep.name, span, dep_kind, Some((root, &dep))).0 + self.resolve_crate(dep.name, span, dep_kind, Some((root, &dep))) })).collect() } @@ -581,7 +579,8 @@ impl<'a> CrateLoader<'a> { }; info!("panic runtime not found -- loading {}", name); - let (cnum, data) = self.resolve_crate(name, DUMMY_SP, DepKind::Implicit, None); + let cnum = self.resolve_crate(name, DUMMY_SP, DepKind::Implicit, None); + let data = self.cstore.get_crate_data(cnum); // Sanity check the loaded crate to ensure it is indeed a panic runtime // and the panic strategy is indeed what we thought it was. @@ -685,7 +684,8 @@ impl<'a> CrateLoader<'a> { }); info!("loading sanitizer: {}", name); - let data = self.resolve_crate(name, DUMMY_SP, DepKind::Explicit, None).1; + let cnum = self.resolve_crate(name, DUMMY_SP, DepKind::Explicit, None); + let data = self.cstore.get_crate_data(cnum); // Sanity check the loaded crate to ensure it is indeed a sanitizer runtime if !data.root.sanitizer_runtime { @@ -705,7 +705,8 @@ impl<'a> CrateLoader<'a> { info!("loading profiler"); let name = Symbol::intern("profiler_builtins"); - let data = self.resolve_crate(name, DUMMY_SP, DepKind::Implicit, None).1; + let cnum = self.resolve_crate(name, DUMMY_SP, DepKind::Implicit, None); + let data = self.cstore.get_crate_data(cnum); // Sanity check the loaded crate to ensure it is indeed a profiler runtime if !data.root.profiler_runtime { @@ -886,7 +887,7 @@ impl<'a> CrateLoader<'a> { DepKind::Explicit }; - let cnum = self.resolve_crate(name, item.span, dep_kind, None).0; + let cnum = self.resolve_crate(name, item.span, dep_kind, None); let def_id = definitions.opt_local_def_id(item.id).unwrap(); let path_len = definitions.def_path(def_id.index).data.len(); @@ -907,7 +908,7 @@ impl<'a> CrateLoader<'a> { } pub fn process_path_extern(&mut self, name: Symbol, span: Span) -> CrateNum { - let cnum = self.resolve_crate(name, span, DepKind::Explicit, None).0; + let cnum = self.resolve_crate(name, span, DepKind::Explicit, None); self.update_extern_crate( cnum, @@ -925,7 +926,7 @@ impl<'a> CrateLoader<'a> { } pub fn maybe_process_path_extern(&mut self, name: Symbol, span: Span) -> Option { - let cnum = self.maybe_resolve_crate(name, span, DepKind::Explicit, None).ok()?.0; + let cnum = self.maybe_resolve_crate(name, span, DepKind::Explicit, None).ok()?; self.update_extern_crate( cnum, diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index a0589b1f3bd3e..6b06cf575edcf 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -54,7 +54,7 @@ crate struct CrateMetadata { /// hashmap, which gives the reverse mapping. This allows us to /// quickly retrace a `DefPath`, which is needed for incremental /// compilation support. - crate def_path_table: Lrc, + crate def_path_table: DefPathTable, /// Trait impl data. /// FIXME: Used only from queries and can use query cache, /// so pre-decoding can probably be avoided. @@ -123,18 +123,18 @@ impl CStore { CrateNum::new(self.metas.len() - 1) } - crate fn get_crate_data(&self, cnum: CrateNum) -> Lrc { - self.metas[cnum].clone() + crate fn get_crate_data(&self, cnum: CrateNum) -> &CrateMetadata { + self.metas[cnum].as_ref() .unwrap_or_else(|| panic!("Failed to get crate data for {:?}", cnum)) } - crate fn set_crate_data(&mut self, cnum: CrateNum, data: Lrc) { + crate fn set_crate_data(&mut self, cnum: CrateNum, data: CrateMetadata) { assert!(self.metas[cnum].is_none(), "Overwriting crate metadata entry"); - self.metas[cnum] = Some(data); + self.metas[cnum] = Some(Lrc::new(data)); } crate fn iter_crate_data(&self, mut i: I) - where I: FnMut(CrateNum, &Lrc) + where I: FnMut(CrateNum, &CrateMetadata) { for (k, v) in self.metas.iter_enumerated() { if let &Some(ref v) = v { diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index c20017ffef660..d942a19194a14 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -53,7 +53,7 @@ macro_rules! provide { let ($def_id, $other) = def_id_arg.into_args(); assert!(!$def_id.is_local()); - let $cdata = $tcx.crate_data_as_rc_any($def_id.krate); + let $cdata = $tcx.crate_data_as_any($def_id.krate); let $cdata = $cdata.downcast_ref::() .expect("CrateStore created data is not a CrateMetadata"); @@ -478,8 +478,8 @@ impl cstore::CStore { } impl CrateStore for cstore::CStore { - fn crate_data_as_rc_any(&self, krate: CrateNum) -> Lrc { - self.get_crate_data(krate) + fn crate_data_as_any(&self, cnum: CrateNum) -> &dyn Any { + self.get_crate_data(cnum) } fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics { @@ -520,8 +520,8 @@ impl CrateStore for cstore::CStore { self.get_crate_data(def.krate).def_path_hash(def.index) } - fn def_path_table(&self, cnum: CrateNum) -> Lrc { - self.get_crate_data(cnum).def_path_table.clone() + fn def_path_table(&self, cnum: CrateNum) -> &DefPathTable { + &self.get_crate_data(cnum).def_path_table } fn crates_untracked(&self) -> Vec From 94216ce3adfdb7d6c206505fca736d274a98ad2b Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 21 Oct 2019 23:32:51 +0300 Subject: [PATCH 23/23] rustc_interface: Remove `ExpansionResult` and some `Steal`s --- src/librustc_interface/passes.rs | 25 ++++--------------------- src/librustc_interface/queries.rs | 17 ++++++++++------- 2 files changed, 14 insertions(+), 28 deletions(-) diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 80ce203b4fbb6..58936172c5bce 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -102,7 +102,7 @@ fn count_nodes(krate: &ast::Crate) -> usize { declare_box_region_type!( pub BoxedResolver, for(), - (&mut Resolver<'_>) -> (Result, ExpansionResult) + (&mut Resolver<'_>) -> (Result, ResolverOutputs) ); /// Runs the "early phases" of the compiler: initial `cfg` processing, @@ -149,33 +149,16 @@ pub fn configure_and_expand( } }; box_region_allow_access!(for(), (&mut Resolver<'_>), (&mut resolver)); - ExpansionResult::from_resolver_outputs(resolver.into_outputs()) + resolver.into_outputs() }); result.map(|k| (k, resolver)) } -pub struct ExpansionResult { - pub resolver_outputs: Steal, -} - -impl ExpansionResult { - fn from_resolver_outputs(resolver_outputs: ResolverOutputs) -> Self { - ExpansionResult { resolver_outputs: Steal::new(resolver_outputs) } - } -} - impl BoxedResolver { - pub fn to_expansion_result( - resolver: Rc>, - ) -> ExpansionResult { + pub fn to_resolver_outputs(resolver: Rc>) -> ResolverOutputs { match Rc::try_unwrap(resolver) { Ok(resolver) => resolver.into_inner().complete(), - Err(resolver) => { - let resolver = &*resolver; - resolver.borrow_mut().access(|resolver| { - ExpansionResult::from_resolver_outputs(resolver.clone_outputs()) - }) - } + Err(resolver) => resolver.borrow_mut().access(|resolver| resolver.clone_outputs()), } } } diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs index b5c356bf05a1b..ea51e63725ea2 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -1,5 +1,5 @@ use crate::interface::{Compiler, Result}; -use crate::passes::{self, BoxedResolver, ExpansionResult, BoxedGlobalCtxt, PluginInfo}; +use crate::passes::{self, BoxedResolver, BoxedGlobalCtxt, PluginInfo}; use rustc_incremental::DepGraphFuture; use rustc_data_structures::sync::Lrc; @@ -11,6 +11,7 @@ use rustc::session::Session; use rustc::lint::LintStore; use rustc::hir::def_id::LOCAL_CRATE; use rustc::ty::steal::Steal; +use rustc::ty::ResolverOutputs; use rustc::dep_graph::DepGraph; use std::cell::{Ref, RefMut, RefCell}; use std::rc::Rc; @@ -81,7 +82,7 @@ pub(crate) struct Queries { register_plugins: Query<(ast::Crate, PluginInfo, Lrc)>, expansion: Query<(ast::Crate, Steal>>, Lrc)>, dep_graph: Query, - lower_to_hir: Query<(Steal, ExpansionResult)>, + lower_to_hir: Query<(Steal, Steal)>, prepare_outputs: Query, global_ctxt: Query, ongoing_codegen: Query>, @@ -191,7 +192,9 @@ impl Compiler { }) } - pub fn lower_to_hir(&self) -> Result<&Query<(Steal, ExpansionResult)>> { + pub fn lower_to_hir( + &self, + ) -> Result<&Query<(Steal, Steal)>> { self.queries.lower_to_hir.compute(|| { let expansion_result = self.expansion()?; let peeked = expansion_result.peek(); @@ -207,14 +210,14 @@ impl Compiler { &krate ) })?); - Ok((hir, BoxedResolver::to_expansion_result(resolver))) + Ok((hir, Steal::new(BoxedResolver::to_resolver_outputs(resolver)))) }) } pub fn prepare_outputs(&self) -> Result<&Query> { self.queries.prepare_outputs.compute(|| { let expansion_result = self.expansion()?; - let (krate, boxed_resolver) = &*expansion_result.peek(); + let (krate, boxed_resolver, _) = &*expansion_result.peek(); let crate_name = self.crate_name()?; let crate_name = crate_name.peek(); passes::prepare_outputs(self.session(), self, &krate, &boxed_resolver, &crate_name) @@ -228,12 +231,12 @@ impl Compiler { let lint_store = self.expansion()?.peek().2.clone(); let hir = self.lower_to_hir()?; let hir = hir.peek(); - let (ref hir_forest, ref expansion) = *hir; + let (hir_forest, resolver_outputs) = &*hir; Ok(passes::create_global_ctxt( self, lint_store, hir_forest.steal(), - expansion.resolver_outputs.steal(), + resolver_outputs.steal(), outputs, &crate_name)) })