diff options
Diffstat (limited to 'compiler/rustc_hir')
| -rw-r--r-- | compiler/rustc_hir/src/arena.rs | 83 | ||||
| -rw-r--r-- | compiler/rustc_hir/src/def.rs | 15 | ||||
| -rw-r--r-- | compiler/rustc_hir/src/definitions.rs | 39 | ||||
| -rw-r--r-- | compiler/rustc_hir/src/hir.rs | 330 | ||||
| -rw-r--r-- | compiler/rustc_hir/src/hir_id.rs | 20 | ||||
| -rw-r--r-- | compiler/rustc_hir/src/intravisit.rs | 188 | ||||
| -rw-r--r-- | compiler/rustc_hir/src/lang_items.rs | 19 | ||||
| -rw-r--r-- | compiler/rustc_hir/src/lib.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_hir/src/pat_util.rs | 11 | ||||
| -rw-r--r-- | compiler/rustc_hir/src/stable_hash_impls.rs | 22 | ||||
| -rw-r--r-- | compiler/rustc_hir/src/weak_lang_items.rs | 8 | 
11 files changed, 355 insertions, 382 deletions
| diff --git a/compiler/rustc_hir/src/arena.rs b/compiler/rustc_hir/src/arena.rs index 1a34dd04428..27ec4619064 100644 --- a/compiler/rustc_hir/src/arena.rs +++ b/compiler/rustc_hir/src/arena.rs @@ -1,57 +1,52 @@ -/// This declares a list of types which can be allocated by `Arena`. -/// -/// The `few` modifier will cause allocation to use the shared arena and recording the destructor. -/// This is faster and more memory efficient if there's only a few allocations of the type. -/// Leaving `few` out will cause the type to get its own dedicated `TypedArena` which is -/// faster and more memory efficient if there is lots of allocations. +/// This higher-order macro declares a list of types which can be allocated by `Arena`. /// /// Specifying the `decode` modifier will add decode impls for `&T` and `&[T]`, /// where `T` is the type listed. These impls will appear in the implement_ty_decoder! macro. #[macro_export] macro_rules! arena_types { - ($macro:path, $tcx:lifetime) => ( + ($macro:path) => ( $macro!([ // HIR types - [few] hir_krate: rustc_hir::Crate<$tcx>, - [] arm: rustc_hir::Arm<$tcx>, - [] asm_operand: (rustc_hir::InlineAsmOperand<$tcx>, Span), + [] hir_krate: rustc_hir::Crate<'tcx>, + [] arm: rustc_hir::Arm<'tcx>, + [] asm_operand: (rustc_hir::InlineAsmOperand<'tcx>, Span), [] asm_template: rustc_ast::InlineAsmTemplatePiece, [] attribute: rustc_ast::Attribute, - [] block: rustc_hir::Block<$tcx>, - [] bare_fn_ty: rustc_hir::BareFnTy<$tcx>, - [] body: rustc_hir::Body<$tcx>, - [] generic_arg: rustc_hir::GenericArg<$tcx>, - [] generic_args: rustc_hir::GenericArgs<$tcx>, - [] generic_bound: rustc_hir::GenericBound<$tcx>, - [] generic_param: rustc_hir::GenericParam<$tcx>, - [] expr: rustc_hir::Expr<$tcx>, - [] expr_field: rustc_hir::ExprField<$tcx>, - [] pat_field: rustc_hir::PatField<$tcx>, - [] fn_decl: rustc_hir::FnDecl<$tcx>, - [] foreign_item: rustc_hir::ForeignItem<$tcx>, - [few] foreign_item_ref: rustc_hir::ForeignItemRef, - [] impl_item: rustc_hir::ImplItem<$tcx>, + [] block: rustc_hir::Block<'tcx>, + [] bare_fn_ty: rustc_hir::BareFnTy<'tcx>, + [] body: rustc_hir::Body<'tcx>, + [] generic_arg: rustc_hir::GenericArg<'tcx>, + [] generic_args: rustc_hir::GenericArgs<'tcx>, + [] generic_bound: rustc_hir::GenericBound<'tcx>, + [] generic_param: rustc_hir::GenericParam<'tcx>, + [] expr: rustc_hir::Expr<'tcx>, + [] let_expr: rustc_hir::Let<'tcx>, + [] expr_field: rustc_hir::ExprField<'tcx>, + [] pat_field: rustc_hir::PatField<'tcx>, + [] fn_decl: rustc_hir::FnDecl<'tcx>, + [] foreign_item: rustc_hir::ForeignItem<'tcx>, + [] foreign_item_ref: rustc_hir::ForeignItemRef, + [] impl_item: rustc_hir::ImplItem<'tcx>, [] impl_item_ref: rustc_hir::ImplItemRef, - [] item: rustc_hir::Item<$tcx>, - [few] inline_asm: rustc_hir::InlineAsm<$tcx>, - [few] llvm_inline_asm: rustc_hir::LlvmInlineAsm<$tcx>, - [] local: rustc_hir::Local<$tcx>, - [few] mod_: rustc_hir::Mod<$tcx>, - [] owner_info: rustc_hir::OwnerInfo<$tcx>, - [] param: rustc_hir::Param<$tcx>, - [] pat: rustc_hir::Pat<$tcx>, - [] path: rustc_hir::Path<$tcx>, - [] path_segment: rustc_hir::PathSegment<$tcx>, - [] poly_trait_ref: rustc_hir::PolyTraitRef<$tcx>, - [] qpath: rustc_hir::QPath<$tcx>, - [] stmt: rustc_hir::Stmt<$tcx>, - [] field_def: rustc_hir::FieldDef<$tcx>, - [] trait_item: rustc_hir::TraitItem<$tcx>, + [] item: rustc_hir::Item<'tcx>, + [] inline_asm: rustc_hir::InlineAsm<'tcx>, + [] local: rustc_hir::Local<'tcx>, + [] mod_: rustc_hir::Mod<'tcx>, + [] owner_info: rustc_hir::OwnerInfo<'tcx>, + [] param: rustc_hir::Param<'tcx>, + [] pat: rustc_hir::Pat<'tcx>, + [] path: rustc_hir::Path<'tcx>, + [] path_segment: rustc_hir::PathSegment<'tcx>, + [] poly_trait_ref: rustc_hir::PolyTraitRef<'tcx>, + [] qpath: rustc_hir::QPath<'tcx>, + [] stmt: rustc_hir::Stmt<'tcx>, + [] field_def: rustc_hir::FieldDef<'tcx>, + [] trait_item: rustc_hir::TraitItem<'tcx>, [] trait_item_ref: rustc_hir::TraitItemRef, - [] ty: rustc_hir::Ty<$tcx>, - [] type_binding: rustc_hir::TypeBinding<$tcx>, - [] variant: rustc_hir::Variant<$tcx>, - [] where_predicate: rustc_hir::WherePredicate<$tcx>, - ], $tcx); + [] ty: rustc_hir::Ty<'tcx>, + [] type_binding: rustc_hir::TypeBinding<'tcx>, + [] variant: rustc_hir::Variant<'tcx>, + [] where_predicate: rustc_hir::WherePredicate<'tcx>, + ]); ) } diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index cb668eb35e0..a43cb0203dd 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -104,14 +104,16 @@ pub enum DefKind { Use, /// An `extern` block. ForeignMod, - /// Anonymous constant, e.g. the `1 + 2` in `[u8; 1 + 2]`, or `const { 1 + 2}` + /// Anonymous constant, e.g. the `1 + 2` in `[u8; 1 + 2]` AnonConst, + /// An inline constant, e.g. `const { 1 + 2 }` + InlineConst, /// Opaque type, aka `impl Trait`. OpaqueTy, Field, /// Lifetime parameter: the `'a` in `struct Foo<'a> { ... }` LifetimeParam, - /// A use of [`global_asm!`]. + /// A use of `global_asm!`. GlobalAsm, Impl, Closure, @@ -155,6 +157,7 @@ impl DefKind { DefKind::Use => "import", DefKind::ForeignMod => "foreign module", DefKind::AnonConst => "constant expression", + DefKind::InlineConst => "inline constant", DefKind::Field => "field", DefKind::Impl => "implementation", DefKind::Closure => "closure", @@ -174,6 +177,7 @@ impl DefKind { | DefKind::OpaqueTy | DefKind::Impl | DefKind::Use + | DefKind::InlineConst | DefKind::ExternCrate => "an", DefKind::Macro(macro_kind) => macro_kind.article(), _ => "a", @@ -207,6 +211,7 @@ impl DefKind { // Not namespaced. DefKind::AnonConst + | DefKind::InlineConst | DefKind::Field | DefKind::LifetimeParam | DefKind::ExternCrate @@ -438,11 +443,11 @@ impl<T> PerNS<T> { } pub fn into_iter(self) -> IntoIter<T, 3> { - IntoIter::new([self.value_ns, self.type_ns, self.macro_ns]) + [self.value_ns, self.type_ns, self.macro_ns].into_iter() } pub fn iter(&self) -> IntoIter<&T, 3> { - IntoIter::new([&self.value_ns, &self.type_ns, &self.macro_ns]) + [&self.value_ns, &self.type_ns, &self.macro_ns].into_iter() } } @@ -476,7 +481,7 @@ impl<T> PerNS<Option<T>> { /// Returns an iterator over the items which are `Some`. pub fn present_items(self) -> impl Iterator<Item = T> { - IntoIter::new([self.type_ns, self.value_ns, self.macro_ns]).flatten() + [self.type_ns, self.value_ns, self.macro_ns].into_iter().flatten() } } diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs index ca29351455e..74d6b05ca5f 100644 --- a/compiler/rustc_hir/src/definitions.rs +++ b/compiler/rustc_hir/src/definitions.rs @@ -101,10 +101,12 @@ impl DefPathTable { pub struct Definitions { table: DefPathTable, - // FIXME(eddyb) ideally all `LocalDefId`s would be HIR owners. + /// Only [`LocalDefId`]s for items and item-like are HIR owners. + /// The associated `HirId` has a `local_id` of `0`. + /// Generic parameters and closures are also assigned a `LocalDefId` but are not HIR owners. + /// Their `HirId`s are defined by their position while lowering the enclosing owner. + // FIXME(cjgillot) Some `LocalDefId`s from `use` items are dropped during lowering and lack a `HirId`. pub(super) def_id_to_hir_id: IndexVec<LocalDefId, Option<hir::HirId>>, - /// The reverse mapping of `def_id_to_hir_id`. - pub(super) hir_id_to_def_id: FxHashMap<hir::HirId, LocalDefId>, /// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`. expansions_that_defined: FxHashMap<LocalDefId, ExpnId>, @@ -173,7 +175,7 @@ impl DisambiguatedDefPathData { if verbose && self.disambiguator != 0 { write!(writer, "{}#{}", name, self.disambiguator) } else { - writer.write_str(&name.as_str()) + writer.write_str(name.as_str()) } } DefPathDataName::Anon { namespace } => { @@ -267,6 +269,8 @@ pub enum DefPathData { // Different kinds of items and item-like things: /// An impl. Impl, + /// An `extern` block. + ForeignMod, /// Something in the type namespace. TypeNs(Symbol), /// Something in the value namespace. @@ -324,11 +328,6 @@ impl Definitions { self.def_id_to_hir_id[id].unwrap() } - #[inline] - pub fn opt_hir_id_to_local_def_id(&self, hir_id: hir::HirId) -> Option<LocalDefId> { - self.hir_id_to_def_id.get(&hir_id).copied() - } - /// Adds a root definition (no parent) and a few other reserved definitions. pub fn new(stable_crate_id: StableCrateId, crate_span: Span) -> Definitions { let key = DefKey { @@ -356,7 +355,6 @@ impl Definitions { Definitions { table, def_id_to_hir_id: Default::default(), - hir_id_to_def_id: Default::default(), expansions_that_defined: Default::default(), def_id_to_span, stable_crate_id, @@ -419,12 +417,6 @@ impl Definitions { "trying to initialize `LocalDefId` <-> `HirId` mappings twice" ); - // Build the reverse mapping of `def_id_to_hir_id`. - self.hir_id_to_def_id = mapping - .iter_enumerated() - .filter_map(|(def_id, hir_id)| hir_id.map(|hir_id| (hir_id, def_id))) - .collect(); - self.def_id_to_hir_id = mapping; } @@ -443,13 +435,17 @@ impl Definitions { } #[inline(always)] - pub fn local_def_path_hash_to_def_id(&self, hash: DefPathHash) -> LocalDefId { + pub fn local_def_path_hash_to_def_id( + &self, + hash: DefPathHash, + err: &mut dyn FnMut() -> !, + ) -> LocalDefId { debug_assert!(hash.stable_crate_id() == self.stable_crate_id); self.table .def_path_hash_to_index .get(&hash) .map(|local_def_index| LocalDefId { local_def_index }) - .unwrap() + .unwrap_or_else(|| err()) } pub fn def_path_hash_to_def_index_map(&self) -> &DefPathHashMap { @@ -469,7 +465,9 @@ impl DefPathData { match *self { TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name), - Impl | CrateRoot | Misc | ClosureExpr | Ctor | AnonConst | ImplTrait => None, + Impl | ForeignMod | CrateRoot | Misc | ClosureExpr | Ctor | AnonConst | ImplTrait => { + None + } } } @@ -482,6 +480,7 @@ impl DefPathData { // Note that this does not show up in user print-outs. CrateRoot => DefPathDataName::Anon { namespace: kw::Crate }, Impl => DefPathDataName::Anon { namespace: kw::Impl }, + ForeignMod => DefPathDataName::Anon { namespace: kw::Extern }, Misc => DefPathDataName::Anon { namespace: sym::misc }, ClosureExpr => DefPathDataName::Anon { namespace: sym::closure }, Ctor => DefPathDataName::Anon { namespace: sym::constructor }, @@ -494,7 +493,7 @@ impl DefPathData { impl fmt::Display for DefPathData { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.name() { - DefPathDataName::Named(name) => f.write_str(&name.as_str()), + DefPathDataName::Named(name) => f.write_str(name.as_str()), // FIXME(#70334): this will generate legacy {{closure}}, {{impl}}, etc DefPathDataName::Anon { namespace } => write!(f, "{{{{{}}}}}", namespace), } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index a441a635c1e..a0ed72c9e9e 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -5,8 +5,8 @@ use crate::intravisit::FnKind; use crate::LangItem; use rustc_ast::util::parser::ExprPrecedence; -use rustc_ast::{self as ast, CrateSugar, LlvmAsmDialect}; -use rustc_ast::{Attribute, FloatTy, IntTy, Label, LitKind, StrStyle, TraitObjectSyntax, UintTy}; +use rustc_ast::{self as ast, CrateSugar}; +use rustc_ast::{Attribute, FloatTy, IntTy, Label, LitKind, TraitObjectSyntax, UintTy}; pub use rustc_ast::{BorrowKind, ImplPolarity, IsAuto}; pub use rustc_ast::{CaptureBy, Movability, Mutability}; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; @@ -17,8 +17,7 @@ use rustc_index::vec::IndexVec; use rustc_macros::HashStable_Generic; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident, Symbol}; -use rustc_span::{def_id::LocalDefId, BytePos}; -use rustc_span::{MultiSpan, Span, DUMMY_SP}; +use rustc_span::{def_id::LocalDefId, BytePos, MultiSpan, Span, DUMMY_SP}; use rustc_target::asm::InlineAsmRegOrRegClass; use rustc_target::spec::abi::Abi; @@ -92,7 +91,9 @@ pub enum LifetimeName { Param(ParamName), /// User wrote nothing (e.g., the lifetime in `&u32`). - Implicit, + /// + /// The bool indicates whether the user should have written something. + Implicit(bool), /// Implicit lifetime in a context like `dyn Foo`. This is /// distinguished from implicit lifetimes elsewhere because the @@ -122,7 +123,7 @@ impl LifetimeName { pub fn ident(&self) -> Ident { match *self { LifetimeName::ImplicitObjectLifetimeDefault - | LifetimeName::Implicit + | LifetimeName::Implicit(_) | LifetimeName::Error => Ident::empty(), LifetimeName::Underscore => Ident::with_dummy_span(kw::UnderscoreLifetime), LifetimeName::Static => Ident::with_dummy_span(kw::StaticLifetime), @@ -133,7 +134,7 @@ impl LifetimeName { pub fn is_elided(&self) -> bool { match self { LifetimeName::ImplicitObjectLifetimeDefault - | LifetimeName::Implicit + | LifetimeName::Implicit(_) | LifetimeName::Underscore => true, // It might seem surprising that `Fresh(_)` counts as @@ -204,7 +205,6 @@ impl Path<'_> { #[derive(Debug, HashStable_Generic)] pub struct PathSegment<'hir> { /// The identifier portion of this path segment. - #[stable_hasher(project(name))] pub ident: Ident, // `id` and `res` are optional. We currently only use these in save-analysis, // any path segments without these will not have save-analysis info and @@ -254,23 +254,9 @@ pub struct ConstArg { pub span: Span, } -#[derive(Copy, Clone, Encodable, Debug, HashStable_Generic)] -pub enum InferKind { - Const, - Type, -} - -impl InferKind { - #[inline] - pub fn is_type(self) -> bool { - matches!(self, InferKind::Type) - } -} - #[derive(Encodable, Debug, HashStable_Generic)] pub struct InferArg { pub hir_id: HirId, - pub kind: InferKind, pub span: Span, } @@ -307,10 +293,6 @@ impl GenericArg<'_> { } } - pub fn is_const(&self) -> bool { - matches!(self, GenericArg::Const(_)) - } - pub fn is_synthetic(&self) -> bool { matches!(self, GenericArg::Lifetime(lifetime) if lifetime.name.ident() == Ident::empty()) } @@ -324,16 +306,21 @@ impl GenericArg<'_> { } } - pub fn to_ord(&self, feats: &rustc_feature::Features) -> ast::ParamKindOrd { + pub fn to_ord(&self) -> ast::ParamKindOrd { match self { GenericArg::Lifetime(_) => ast::ParamKindOrd::Lifetime, GenericArg::Type(_) => ast::ParamKindOrd::Type, - GenericArg::Const(_) => { - ast::ParamKindOrd::Const { unordered: feats.unordered_const_ty_params() } - } + GenericArg::Const(_) => ast::ParamKindOrd::Const, GenericArg::Infer(_) => ast::ParamKindOrd::Infer, } } + + pub fn is_ty_or_const(&self) -> bool { + match self { + GenericArg::Lifetime(_) => false, + GenericArg::Type(_) | GenericArg::Const(_) | GenericArg::Infer(_) => true, + } + } } #[derive(Debug, HashStable_Generic)] @@ -390,7 +377,7 @@ impl GenericArgs<'_> { GenericArg::Type(ty) => matches!(ty.kind, TyKind::Err), _ => false, }) || self.bindings.iter().any(|arg| match arg.kind { - TypeBindingKind::Equality { ty } => matches!(ty.kind, TyKind::Err), + TypeBindingKind::Equality { term: Term::Ty(ty) } => matches!(ty.kind, TyKind::Err), _ => false, }) } @@ -504,7 +491,7 @@ pub enum GenericParamKind<'hir> { }, Type { default: Option<&'hir Ty<'hir>>, - synthetic: Option<SyntheticTyParamKind>, + synthetic: bool, }, Const { ty: &'hir Ty<'hir>, @@ -523,13 +510,21 @@ pub struct GenericParam<'hir> { pub kind: GenericParamKind<'hir>, } -impl GenericParam<'hir> { - pub fn bounds_span(&self) -> Option<Span> { - self.bounds.iter().fold(None, |span, bound| { - let span = span.map(|s| s.to(bound.span())).unwrap_or_else(|| bound.span()); - - Some(span) - }) +impl<'hir> GenericParam<'hir> { + pub fn bounds_span_for_suggestions(&self) -> Option<Span> { + self.bounds + .iter() + .fold(None, |span: Option<Span>, bound| { + // We include bounds that come from a `#[derive(_)]` but point at the user's code, + // as we use this method to get a span appropriate for suggestions. + if !bound.span().can_be_used_for_suggestions() { + None + } else { + let span = span.map(|s| s.to(bound.span())).unwrap_or_else(|| bound.span()); + Some(span) + } + }) + .map(|sp| sp.shrink_to_hi()) } } @@ -550,7 +545,7 @@ pub struct Generics<'hir> { pub span: Span, } -impl Generics<'hir> { +impl<'hir> Generics<'hir> { pub const fn empty() -> Generics<'hir> { Generics { params: &[], @@ -577,16 +572,6 @@ impl Generics<'hir> { } } -/// Synthetic type parameters are converted to another form during lowering; this allows -/// us to track the original form they had, and is useful for error messages. -#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] -#[derive(HashStable_Generic)] -pub enum SyntheticTyParamKind { - ImplTrait, - // Created by the `#[rustc_synthetic]` attribute. - FromAttr, -} - /// A where-clause in a definition. #[derive(Debug, HashStable_Generic)] pub struct WhereClause<'hir> { @@ -625,7 +610,7 @@ pub enum WherePredicate<'hir> { EqPredicate(WhereEqPredicate<'hir>), } -impl WherePredicate<'_> { +impl<'hir> WherePredicate<'hir> { pub fn span(&self) -> Span { match self { WherePredicate::BoundPredicate(p) => p.span, @@ -647,6 +632,22 @@ pub struct WhereBoundPredicate<'hir> { pub bounds: GenericBounds<'hir>, } +impl<'hir> WhereBoundPredicate<'hir> { + /// Returns `true` if `param_def_id` matches the `bounded_ty` of this predicate. + pub fn is_param_bound(&self, param_def_id: DefId) -> bool { + let path = match self.bounded_ty.kind { + TyKind::Path(QPath::Resolved(None, path)) => path, + _ => return false, + }; + match path.res { + Res::Def(DefKind::TyParam, def_id) | Res::SelfTy(Some(def_id), None) => { + def_id == param_def_id + } + _ => false, + } + } +} + /// A lifetime predicate (e.g., `'a: 'b + 'c`). #[derive(Debug, HashStable_Generic)] pub struct WhereRegionPredicate<'hir> { @@ -706,6 +707,8 @@ pub struct OwnerNodes<'tcx> { pub nodes: IndexVec<ItemLocalId, Option<ParentedNode<'tcx>>>, /// Content of local bodies. pub bodies: SortedMap<ItemLocalId, &'tcx Body<'tcx>>, + /// Non-owning definitions contained in this owner. + pub local_id_to_def_id: SortedMap<ItemLocalId, LocalDefId>, } /// Full information resulting from lowering an AST node. @@ -851,7 +854,6 @@ pub struct PatField<'hir> { #[stable_hasher(ignore)] pub hir_id: HirId, /// The identifier for the field. - #[stable_hasher(project(name))] pub ident: Ident, /// The pattern the field is destructured to. pub pat: &'hir Pat<'hir>, @@ -1161,10 +1163,24 @@ pub struct Arm<'hir> { pub body: &'hir Expr<'hir>, } +/// Represents a `let <pat>[: <ty>] = <expr>` expression (not a Local), occurring in an `if-let` or +/// `let-else`, evaluating to a boolean. Typically the pattern is refutable. +/// +/// In an if-let, imagine it as `if (let <pat> = <expr>) { ... }`; in a let-else, it is part of the +/// desugaring to if-let. Only let-else supports the type annotation at present. +#[derive(Debug, HashStable_Generic)] +pub struct Let<'hir> { + pub hir_id: HirId, + pub span: Span, + pub pat: &'hir Pat<'hir>, + pub ty: Option<&'hir Ty<'hir>>, + pub init: &'hir Expr<'hir>, +} + #[derive(Debug, HashStable_Generic)] pub enum Guard<'hir> { If(&'hir Expr<'hir>), - // FIXME use ExprKind::Let for this. + // FIXME use hir::Let for this. IfLet(&'hir Pat<'hir>, &'hir Expr<'hir>), } @@ -1190,7 +1206,7 @@ pub enum UnsafeSource { UserProvided, } -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Encodable, Hash, Debug)] pub struct BodyId { pub hir_id: HirId, } @@ -1223,7 +1239,7 @@ pub struct Body<'hir> { pub generator_kind: Option<GeneratorKind>, } -impl Body<'hir> { +impl<'hir> Body<'hir> { pub fn id(&self) -> BodyId { BodyId { hir_id: self.value.hir_id } } @@ -1394,6 +1410,20 @@ impl fmt::Display for ConstContext { /// A literal. pub type Lit = Spanned<LitKind>; +#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug, HashStable_Generic)] +pub enum ArrayLen { + Infer(HirId, Span), + Body(AnonConst), +} + +impl ArrayLen { + pub fn hir_id(&self) -> HirId { + match self { + &ArrayLen::Infer(hir_id, _) | &ArrayLen::Body(AnonConst { hir_id, body: _ }) => hir_id, + } + } +} + /// A constant (expression) that's not an item or associated item, /// but needs its own `DefId` for type-checking, const-eval, etc. /// These are usually found nested inside types (e.g., array lengths) @@ -1446,7 +1476,6 @@ impl Expr<'_> { ExprKind::Continue(..) => ExprPrecedence::Continue, ExprKind::Ret(..) => ExprPrecedence::Ret, ExprKind::InlineAsm(..) => ExprPrecedence::InlineAsm, - ExprKind::LlvmInlineAsm(..) => ExprPrecedence::InlineAsm, ExprKind::Struct(..) => ExprPrecedence::Struct, ExprKind::Repeat(..) => ExprPrecedence::Repeat, ExprKind::Yield(..) => ExprPrecedence::Yield, @@ -1506,7 +1535,6 @@ impl Expr<'_> { | ExprKind::Loop(..) | ExprKind::Assign(..) | ExprKind::InlineAsm(..) - | ExprKind::LlvmInlineAsm(..) | ExprKind::AssignOp(..) | ExprKind::Lit(_) | ExprKind::ConstBlock(..) @@ -1589,7 +1617,6 @@ impl Expr<'_> { | ExprKind::Loop(..) | ExprKind::Assign(..) | ExprKind::InlineAsm(..) - | ExprKind::LlvmInlineAsm(..) | ExprKind::AssignOp(..) | ExprKind::ConstBlock(..) | ExprKind::Box(..) @@ -1614,13 +1641,13 @@ pub fn is_range_literal(expr: &Expr<'_>) -> bool { | LangItem::RangeFrom | LangItem::RangeFull | LangItem::RangeToInclusive, - _, + .. ) ), // `..=` desugars into `::std::ops::RangeInclusive::new(...)`. ExprKind::Call(ref func, _) => { - matches!(func.kind, ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, _))) + matches!(func.kind, ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, ..))) } _ => false, @@ -1644,13 +1671,13 @@ pub enum ExprKind<'hir> { Call(&'hir Expr<'hir>, &'hir [Expr<'hir>]), /// A method call (e.g., `x.foo::<'static, Bar, Baz>(a, b, c, d)`). /// - /// The `PathSegment`/`Span` represent the method name and its generic arguments + /// The `PathSegment` represents the method name and its generic arguments /// (within the angle brackets). - /// The first element of the vector of `Expr`s is the expression that evaluates + /// The first element of the `&[Expr]` is the expression that evaluates /// to the object on which the method is being called on (the receiver), /// and the remaining elements are the rest of the arguments. /// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as - /// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d])`. + /// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d], span)`. /// The final `Span` represents the span of the function and arguments /// (e.g. `foo::<Bar, Baz>(a, b, c, d)` in `x.foo::<Bar, Baz>(a, b, c, d)` /// @@ -1658,7 +1685,7 @@ pub enum ExprKind<'hir> { /// the `hir_id` of the `MethodCall` node itself. /// /// [`type_dependent_def_id`]: ../ty/struct.TypeckResults.html#method.type_dependent_def_id - MethodCall(&'hir PathSegment<'hir>, Span, &'hir [Expr<'hir>], Span), + MethodCall(&'hir PathSegment<'hir>, &'hir [Expr<'hir>], Span), /// A tuple (e.g., `(a, b, c, d)`). Tup(&'hir [Expr<'hir>]), /// A binary operation (e.g., `a + b`, `a * b`). @@ -1681,7 +1708,7 @@ pub enum ExprKind<'hir> { /// /// These are not `Local` and only occur as expressions. /// The `let Some(x) = foo()` in `if let Some(x) = foo()` is an example of `Let(..)`. - Let(&'hir Pat<'hir>, &'hir Expr<'hir>, Span), + Let(&'hir Let<'hir>), /// An `if` block, with an optional else block. /// /// I.e., `if <expr> { <expr> } else { <expr> }`. @@ -1730,8 +1757,6 @@ pub enum ExprKind<'hir> { /// Inline assembly (from `asm!`), with its outputs and inputs. InlineAsm(&'hir InlineAsm<'hir>), - /// Inline assembly (from `llvm_asm!`), with its outputs and inputs. - LlvmInlineAsm(&'hir LlvmInlineAsm<'hir>), /// A struct or struct-like variant literal expression. /// @@ -1743,7 +1768,7 @@ pub enum ExprKind<'hir> { /// /// E.g., `[1; 5]`. The first expression is the element /// to be repeated; the second is the number of times to repeat it. - Repeat(&'hir Expr<'hir>, AnonConst), + Repeat(&'hir Expr<'hir>, ArrayLen), /// A suspension point for generators (i.e., `yield <expr>`). Yield(&'hir Expr<'hir>, YieldSource), @@ -1775,8 +1800,8 @@ pub enum QPath<'hir> { /// the `X` and `Y` nodes each being a `TyKind::Path(QPath::TypeRelative(..))`. TypeRelative(&'hir Ty<'hir>, &'hir PathSegment<'hir>), - /// Reference to a `#[lang = "foo"]` item. - LangItem(LangItem, Span), + /// Reference to a `#[lang = "foo"]` item. `HirId` of the inner expr. + LangItem(LangItem, Span, Option<HirId>), } impl<'hir> QPath<'hir> { @@ -1785,7 +1810,7 @@ impl<'hir> QPath<'hir> { match *self { QPath::Resolved(_, path) => path.span, QPath::TypeRelative(qself, ps) => qself.span.to(ps.ident.span), - QPath::LangItem(_, span) => span, + QPath::LangItem(_, span, _) => span, } } @@ -1795,7 +1820,7 @@ impl<'hir> QPath<'hir> { match *self { QPath::Resolved(_, path) => path.span, QPath::TypeRelative(qself, _) => qself.span, - QPath::LangItem(_, span) => span, + QPath::LangItem(_, span, _) => span, } } @@ -1805,7 +1830,7 @@ impl<'hir> QPath<'hir> { match *self { QPath::Resolved(_, path) => path.segments.last().unwrap().ident.span, QPath::TypeRelative(_, segment) => segment.ident.span, - QPath::LangItem(_, span) => span, + QPath::LangItem(_, span, _) => span, } } } @@ -1815,8 +1840,6 @@ impl<'hir> QPath<'hir> { pub enum LocalSource { /// A `match _ { .. }`. Normal, - /// A desugared `for _ in _ { .. }` loop. - ForLoopDesugar, /// When lowering async functions, we create locals within the `async move` so that /// all parameters are dropped after the future is polled. /// @@ -1969,7 +1992,7 @@ pub struct FnSig<'hir> { // The bodies for items are stored "out of line", in a separate // hashmap in the `Crate`. Here we just record the hir-id of the item // so it can fetched later. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug)] pub struct TraitItemId { pub def_id: LocalDefId, } @@ -2032,7 +2055,7 @@ pub enum TraitItemKind<'hir> { // The bodies for items are stored "out of line", in a separate // hashmap in the `Crate`. Here we just record the hir-id of the item // so it can fetched later. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug)] pub struct ImplItemId { pub def_id: LocalDefId, } @@ -2102,26 +2125,43 @@ pub const FN_OUTPUT_NAME: Symbol = sym::Output; #[derive(Debug, HashStable_Generic)] pub struct TypeBinding<'hir> { pub hir_id: HirId, - #[stable_hasher(project(name))] pub ident: Ident, pub gen_args: &'hir GenericArgs<'hir>, pub kind: TypeBindingKind<'hir>, pub span: Span, } +#[derive(Debug, HashStable_Generic)] +pub enum Term<'hir> { + Ty(&'hir Ty<'hir>), + Const(AnonConst), +} + +impl<'hir> From<&'hir Ty<'hir>> for Term<'hir> { + fn from(ty: &'hir Ty<'hir>) -> Self { + Term::Ty(ty) + } +} + +impl<'hir> From<AnonConst> for Term<'hir> { + fn from(c: AnonConst) -> Self { + Term::Const(c) + } +} + // Represents the two kinds of type bindings. #[derive(Debug, HashStable_Generic)] pub enum TypeBindingKind<'hir> { /// E.g., `Foo<Bar: Send>`. Constraint { bounds: &'hir [GenericBound<'hir>] }, - /// E.g., `Foo<Bar = ()>`. - Equality { ty: &'hir Ty<'hir> }, + /// E.g., `Foo<Bar = ()>`, `Foo<Bar = ()>` + Equality { term: Term<'hir> }, } impl TypeBinding<'_> { pub fn ty(&self) -> &Ty<'_> { match self.kind { - TypeBindingKind::Equality { ref ty } => ty, + TypeBindingKind::Equality { term: Term::Ty(ref ty) } => ty, _ => panic!("expected equality type binding for parenthesized generic args"), } } @@ -2235,7 +2275,6 @@ pub struct BareFnTy<'hir> { pub struct OpaqueTy<'hir> { pub generics: Generics<'hir>, pub bounds: GenericBounds<'hir>, - pub impl_trait_fn: Option<DefId>, pub origin: OpaqueTyOrigin, } @@ -2243,9 +2282,9 @@ pub struct OpaqueTy<'hir> { #[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)] pub enum OpaqueTyOrigin { /// `-> impl Trait` - FnReturn, + FnReturn(LocalDefId), /// `async fn` - AsyncFn, + AsyncFn(LocalDefId), /// type aliases: `type Foo = impl Trait;` TyAlias, } @@ -2256,7 +2295,7 @@ pub enum TyKind<'hir> { /// A variable length slice (i.e., `[T]`). Slice(&'hir Ty<'hir>), /// A fixed length array (i.e., `[T; n]`). - Array(&'hir Ty<'hir>, AnonConst), + Array(&'hir Ty<'hir>, ArrayLen), /// A raw pointer (i.e., `*const T` or `*mut T`). Ptr(MutTy<'hir>), /// A reference (i.e., `&'a T` or `&'a mut T`). @@ -2347,36 +2386,6 @@ pub struct InlineAsm<'hir> { pub line_spans: &'hir [Span], } -#[derive(Copy, Clone, Encodable, Decodable, Debug, Hash, HashStable_Generic, PartialEq)] -pub struct LlvmInlineAsmOutput { - pub constraint: Symbol, - pub is_rw: bool, - pub is_indirect: bool, - pub span: Span, -} - -// NOTE(eddyb) This is used within MIR as well, so unlike the rest of the HIR, -// it needs to be `Clone` and `Decodable` and use plain `Vec<T>` instead of -// arena-allocated slice. -#[derive(Clone, Encodable, Decodable, Debug, Hash, HashStable_Generic, PartialEq)] -pub struct LlvmInlineAsmInner { - pub asm: Symbol, - pub asm_str_style: StrStyle, - pub outputs: Vec<LlvmInlineAsmOutput>, - pub inputs: Vec<Symbol>, - pub clobbers: Vec<Symbol>, - pub volatile: bool, - pub alignstack: bool, - pub dialect: LlvmAsmDialect, -} - -#[derive(Debug, HashStable_Generic)] -pub struct LlvmInlineAsm<'hir> { - pub inner: LlvmInlineAsmInner, - pub outputs_exprs: &'hir [Expr<'hir>], - pub inputs_exprs: &'hir [Expr<'hir>], -} - /// Represents a parameter in a function header. #[derive(Debug, HashStable_Generic)] pub struct Param<'hir> { @@ -2474,7 +2483,7 @@ impl FnRetTy<'_> { } } -#[derive(Encodable, Debug)] +#[derive(Encodable, Debug, HashStable_Generic)] pub struct Mod<'hir> { /// A span from the first token past `{` to the last token until `}`. /// For `mod foo;`, the inner span ranges from the first token @@ -2491,7 +2500,6 @@ pub struct EnumDef<'hir> { #[derive(Debug, HashStable_Generic)] pub struct Variant<'hir> { /// Name of the variant. - #[stable_hasher(project(name))] pub ident: Ident, /// Id of the variant (not the constructor, see `VariantData::ctor_hir_id()`). pub id: HirId, @@ -2581,7 +2589,6 @@ impl VisibilityKind<'_> { #[derive(Debug, HashStable_Generic)] pub struct FieldDef<'hir> { pub span: Span, - #[stable_hasher(project(name))] pub ident: Ident, pub vis: Visibility<'hir>, pub hir_id: HirId, @@ -2613,7 +2620,7 @@ pub enum VariantData<'hir> { Unit(HirId), } -impl VariantData<'hir> { +impl<'hir> VariantData<'hir> { /// Return the fields of this variant. pub fn fields(&self) -> &'hir [FieldDef<'hir>] { match *self { @@ -2634,7 +2641,7 @@ impl VariantData<'hir> { // The bodies for items are stored "out of line", in a separate // hashmap in the `Crate`. Here we just record the hir-id of the item // so it can fetched later. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Debug, Hash)] +#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug, Hash)] pub struct ItemId { pub def_id: LocalDefId, } @@ -2721,6 +2728,10 @@ pub struct FnHeader { } impl FnHeader { + pub fn is_async(&self) -> bool { + matches!(&self.asyncness, IsAsync::Async) + } + pub fn is_const(&self) -> bool { matches!(&self.constness, Constness::Const) } @@ -2796,7 +2807,9 @@ impl ItemKind<'_> { Some(match *self { ItemKind::Fn(_, ref generics, _) | ItemKind::TyAlias(_, ref generics) - | ItemKind::OpaqueTy(OpaqueTy { ref generics, impl_trait_fn: None, .. }) + | ItemKind::OpaqueTy(OpaqueTy { + ref generics, origin: OpaqueTyOrigin::TyAlias, .. + }) | ItemKind::Enum(_, ref generics) | ItemKind::Struct(_, ref generics) | ItemKind::Union(_, ref generics) @@ -2838,7 +2851,6 @@ impl ItemKind<'_> { #[derive(Encodable, Debug, HashStable_Generic)] pub struct TraitItemRef { pub id: TraitItemId, - #[stable_hasher(project(name))] pub ident: Ident, pub kind: AssocItemKind, pub span: Span, @@ -2854,11 +2866,12 @@ pub struct TraitItemRef { #[derive(Debug, HashStable_Generic)] pub struct ImplItemRef { pub id: ImplItemId, - #[stable_hasher(project(name))] pub ident: Ident, pub kind: AssocItemKind, pub span: Span, pub defaultness: Defaultness, + /// When we are in a trait impl, link to the trait-item's id. + pub trait_item_def_id: Option<DefId>, } #[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)] @@ -2871,7 +2884,7 @@ pub enum AssocItemKind { // The bodies for items are stored "out of line", in a separate // hashmap in the `Crate`. Here we just record the hir-id of the item // so it can fetched later. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug)] pub struct ForeignItemId { pub def_id: LocalDefId, } @@ -2893,7 +2906,6 @@ impl ForeignItemId { #[derive(Debug, HashStable_Generic)] pub struct ForeignItemRef { pub id: ForeignItemId, - #[stable_hasher(project(name))] pub ident: Ident, pub span: Span, } @@ -3163,7 +3175,7 @@ impl<'hir> Node<'hir> { } } - pub fn fn_decl(&self) -> Option<&FnDecl<'hir>> { + pub fn fn_decl(&self) -> Option<&'hir FnDecl<'hir>> { match self { Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. }) | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. }) @@ -3175,6 +3187,15 @@ impl<'hir> Node<'hir> { } } + pub fn fn_sig(&self) -> Option<&'hir FnSig<'hir>> { + match self { + Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. }) + | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. }) + | Node::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) => Some(fn_sig), + _ => None, + } + } + pub fn body_id(&self) -> Option<BodyId> { match self { Node::TraitItem(TraitItem { @@ -3196,59 +3217,6 @@ impl<'hir> Node<'hir> { } } - pub fn hir_id(&self) -> Option<HirId> { - match self { - Node::Item(Item { def_id, .. }) - | Node::TraitItem(TraitItem { def_id, .. }) - | Node::ImplItem(ImplItem { def_id, .. }) - | Node::ForeignItem(ForeignItem { def_id, .. }) => Some(HirId::make_owner(*def_id)), - Node::Field(FieldDef { hir_id, .. }) - | Node::AnonConst(AnonConst { hir_id, .. }) - | Node::Expr(Expr { hir_id, .. }) - | Node::Stmt(Stmt { hir_id, .. }) - | Node::Ty(Ty { hir_id, .. }) - | Node::Binding(Pat { hir_id, .. }) - | Node::Pat(Pat { hir_id, .. }) - | Node::Arm(Arm { hir_id, .. }) - | Node::Block(Block { hir_id, .. }) - | Node::Local(Local { hir_id, .. }) - | Node::Lifetime(Lifetime { hir_id, .. }) - | Node::Param(Param { hir_id, .. }) - | Node::Infer(InferArg { hir_id, .. }) - | Node::GenericParam(GenericParam { hir_id, .. }) => Some(*hir_id), - Node::TraitRef(TraitRef { hir_ref_id, .. }) => Some(*hir_ref_id), - Node::PathSegment(PathSegment { hir_id, .. }) => *hir_id, - Node::Variant(Variant { id, .. }) => Some(*id), - Node::Ctor(variant) => variant.ctor_hir_id(), - Node::Crate(_) | Node::Visibility(_) => None, - } - } - - /// Returns `Constness::Const` when this node is a const fn/impl/item. - pub fn constness_for_typeck(&self) -> Constness { - match self { - Node::Item(Item { - kind: ItemKind::Fn(FnSig { header: FnHeader { constness, .. }, .. }, ..), - .. - }) - | Node::TraitItem(TraitItem { - kind: TraitItemKind::Fn(FnSig { header: FnHeader { constness, .. }, .. }, ..), - .. - }) - | Node::ImplItem(ImplItem { - kind: ImplItemKind::Fn(FnSig { header: FnHeader { constness, .. }, .. }, ..), - .. - }) - | Node::Item(Item { kind: ItemKind::Impl(Impl { constness, .. }), .. }) => *constness, - - Node::Item(Item { kind: ItemKind::Const(..), .. }) - | Node::TraitItem(TraitItem { kind: TraitItemKind::Const(..), .. }) - | Node::ImplItem(ImplItem { kind: ImplItemKind::Const(..), .. }) => Constness::Const, - - _ => Constness::NotConst, - } - } - pub fn as_owner(self) -> Option<OwnerNode<'hir>> { match self { Node::Item(i) => Some(OwnerNode::Item(i)), @@ -3291,10 +3259,10 @@ impl<'hir> Node<'hir> { #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] mod size_asserts { rustc_data_structures::static_assert_size!(super::Block<'static>, 48); - rustc_data_structures::static_assert_size!(super::Expr<'static>, 64); + rustc_data_structures::static_assert_size!(super::Expr<'static>, 56); rustc_data_structures::static_assert_size!(super::Pat<'static>, 88); rustc_data_structures::static_assert_size!(super::QPath<'static>, 24); - rustc_data_structures::static_assert_size!(super::Ty<'static>, 72); + rustc_data_structures::static_assert_size!(super::Ty<'static>, 80); rustc_data_structures::static_assert_size!(super::Item<'static>, 184); rustc_data_structures::static_assert_size!(super::TraitItem<'static>, 128); diff --git a/compiler/rustc_hir/src/hir_id.rs b/compiler/rustc_hir/src/hir_id.rs index 39552eb9f31..5b486819c35 100644 --- a/compiler/rustc_hir/src/hir_id.rs +++ b/compiler/rustc_hir/src/hir_id.rs @@ -11,7 +11,7 @@ use std::fmt; /// the `local_id` part of the `HirId` changing, which is a very useful property in /// incremental compilation where we have to persist things through changes to /// the code base. -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] #[derive(Encodable, Decodable)] pub struct HirId { pub owner: LocalDefId, @@ -19,11 +19,13 @@ pub struct HirId { } impl HirId { + #[inline] pub fn expect_owner(self) -> LocalDefId { assert_eq!(self.local_id.index(), 0); self.owner } + #[inline] pub fn as_owner(self) -> Option<LocalDefId> { if self.local_id.index() == 0 { Some(self.owner) } else { None } } @@ -32,6 +34,10 @@ impl HirId { pub fn make_owner(owner: LocalDefId) -> Self { Self { owner, local_id: ItemLocalId::from_u32(0) } } + + pub fn index(self) -> (usize, usize) { + (rustc_index::vec::Idx::index(self.owner), rustc_index::vec::Idx::index(self.local_id)) + } } impl fmt::Display for HirId { @@ -40,6 +46,18 @@ impl fmt::Display for HirId { } } +impl Ord for HirId { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + (self.index()).cmp(&(other.index())) + } +} + +impl PartialOrd for HirId { + fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { + Some(self.cmp(&other)) + } +} + rustc_data_structures::define_id_collections!(HirIdMap, HirIdSet, HirId); rustc_data_structures::define_id_collections!(ItemLocalMap, ItemLocalSet, ItemLocalId); diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index cff543760f4..1d10e79d300 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -139,7 +139,7 @@ pub trait Map<'hir> { } // Used when no map is actually available, forcing manual implementation of nested visitors. -impl Map<'hir> for ! { +impl<'hir> Map<'hir> for ! { fn find(&self, _: HirId) -> Option<Node<'hir>> { unreachable!() } @@ -160,39 +160,27 @@ impl Map<'hir> for ! { } } -/// An erased version of `Map<'hir>`, using dynamic dispatch. -/// NOTE: This type is effectively only usable with `NestedVisitorMap::None`. -pub struct ErasedMap<'hir>(&'hir dyn Map<'hir>); +pub mod nested_filter { + use super::Map; -impl<'hir> Map<'hir> for ErasedMap<'hir> { - fn find(&self, _: HirId) -> Option<Node<'hir>> { - None - } - fn body(&self, id: BodyId) -> &'hir Body<'hir> { - self.0.body(id) - } - fn item(&self, id: ItemId) -> &'hir Item<'hir> { - self.0.item(id) - } - fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir> { - self.0.trait_item(id) - } - fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir> { - self.0.impl_item(id) - } - fn foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir> { - self.0.foreign_item(id) + /// Specifies what nested things a visitor wants to visit. The most + /// common choice is `OnlyBodies`, which will cause the visitor to + /// visit fn bodies for fns that it encounters, but skip over nested + /// item-like things. + /// + /// See the comments on `ItemLikeVisitor` for more details on the overall + /// visit strategy. + pub trait NestedFilter<'hir> { + type Map: Map<'hir>; + + /// Whether the visitor visits nested "item-like" things. + /// E.g., item, impl-item. + const INTER: bool; + /// Whether the visitor visits "intra item-like" things. + /// E.g., function body, closure, `AnonConst` + const INTRA: bool; } -} -/// Specifies what nested things a visitor wants to visit. The most -/// common choice is `OnlyBodies`, which will cause the visitor to -/// visit fn bodies for fns that it encounters, but skip over nested -/// item-like things. -/// -/// See the comments on `ItemLikeVisitor` for more details on the overall -/// visit strategy. -pub enum NestedVisitorMap<M> { /// Do not visit any nested things. When you add a new /// "non-nested" thing, you will want to audit such uses to see if /// they remain valid. @@ -200,47 +188,16 @@ pub enum NestedVisitorMap<M> { /// Use this if you are only walking some particular kind of tree /// (i.e., a type, or fn signature) and you don't want to thread a /// HIR map around. - None, - - /// Do not visit nested item-like things, but visit nested things - /// that are inside of an item-like. - /// - /// **This is the most common choice.** A very common pattern is - /// to use `visit_all_item_likes()` as an outer loop, - /// and to have the visitor that visits the contents of each item - /// using this setting. - OnlyBodies(M), - - /// Visits all nested things, including item-likes. - /// - /// **This is an unusual choice.** It is used when you want to - /// process everything within their lexical context. Typically you - /// kick off the visit by doing `walk_krate()`. - All(M), -} - -impl<M> NestedVisitorMap<M> { - /// Returns the map to use for an "intra item-like" thing (if any). - /// E.g., function body. - fn intra(self) -> Option<M> { - match self { - NestedVisitorMap::None => None, - NestedVisitorMap::OnlyBodies(map) => Some(map), - NestedVisitorMap::All(map) => Some(map), - } - } - - /// Returns the map to use for an "item-like" thing (if any). - /// E.g., item, impl-item. - fn inter(self) -> Option<M> { - match self { - NestedVisitorMap::None => None, - NestedVisitorMap::OnlyBodies(_) => None, - NestedVisitorMap::All(map) => Some(map), - } + pub struct None(()); + impl NestedFilter<'_> for None { + type Map = !; + const INTER: bool = false; + const INTRA: bool = false; } } +use nested_filter::NestedFilter; + /// Each method of the Visitor trait is a hook to be potentially /// overridden. Each method's default implementation recursively visits /// the substructure of the input via the corresponding `walk` method; @@ -258,7 +215,9 @@ impl<M> NestedVisitorMap<M> { /// to monitor future changes to `Visitor` in case a new method with a /// new default implementation gets introduced.) pub trait Visitor<'v>: Sized { - type Map: Map<'v>; + // this type should not be overridden, it exists for convenient usage as `Self::Map` + type Map: Map<'v> = <Self::NestedFilter as NestedFilter<'v>>::Map; + type NestedFilter: NestedFilter<'v> = nested_filter::None; /////////////////////////////////////////////////////////////////////////// // Nested items. @@ -279,7 +238,12 @@ pub trait Visitor<'v>: Sized { /// `panic!()`. This way, if a new `visit_nested_XXX` variant is /// added in the future, we will see the panic in your code and /// fix it appropriately. - fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map>; + fn nested_visit_map(&mut self) -> Self::Map { + panic!( + "nested_visit_map must be implemented or consider using \ + `type NestedFilter = nested_filter::None` (the default)" + ); + } /// Invoked when a nested item is encountered. By default does /// nothing unless you override `nested_visit_map` to return other than @@ -290,32 +254,40 @@ pub trait Visitor<'v>: Sized { /// reason to override this method is if you want a nested pattern /// but cannot supply a `Map`; see `nested_visit_map` for advice. fn visit_nested_item(&mut self, id: ItemId) { - let opt_item = self.nested_visit_map().inter().map(|map| map.item(id)); - walk_list!(self, visit_item, opt_item); + if Self::NestedFilter::INTER { + let item = self.nested_visit_map().item(id); + self.visit_item(item); + } } /// Like `visit_nested_item()`, but for trait items. See /// `visit_nested_item()` for advice on when to override this /// method. fn visit_nested_trait_item(&mut self, id: TraitItemId) { - let opt_item = self.nested_visit_map().inter().map(|map| map.trait_item(id)); - walk_list!(self, visit_trait_item, opt_item); + if Self::NestedFilter::INTER { + let item = self.nested_visit_map().trait_item(id); + self.visit_trait_item(item); + } } /// Like `visit_nested_item()`, but for impl items. See /// `visit_nested_item()` for advice on when to override this /// method. fn visit_nested_impl_item(&mut self, id: ImplItemId) { - let opt_item = self.nested_visit_map().inter().map(|map| map.impl_item(id)); - walk_list!(self, visit_impl_item, opt_item); + if Self::NestedFilter::INTER { + let item = self.nested_visit_map().impl_item(id); + self.visit_impl_item(item); + } } /// Like `visit_nested_item()`, but for foreign items. See /// `visit_nested_item()` for advice on when to override this /// method. fn visit_nested_foreign_item(&mut self, id: ForeignItemId) { - let opt_item = self.nested_visit_map().inter().map(|map| map.foreign_item(id)); - walk_list!(self, visit_foreign_item, opt_item); + if Self::NestedFilter::INTER { + let item = self.nested_visit_map().foreign_item(id); + self.visit_foreign_item(item); + } } /// Invoked to visit the body of a function, method or closure. Like @@ -323,8 +295,10 @@ pub trait Visitor<'v>: Sized { /// `nested_visit_map` to return other than `None`, in which case it will walk /// the body. fn visit_nested_body(&mut self, id: BodyId) { - let opt_body = self.nested_visit_map().intra().map(|map| map.body(id)); - walk_list!(self, visit_body, opt_body); + if Self::NestedFilter::INTRA { + let body = self.nested_visit_map().body(id); + self.visit_body(body); + } } fn visit_param(&mut self, param: &'v Param<'v>) { @@ -383,12 +357,18 @@ pub trait Visitor<'v>: Sized { fn visit_pat(&mut self, p: &'v Pat<'v>) { walk_pat(self, p) } + fn visit_array_length(&mut self, len: &'v ArrayLen) { + walk_array_len(self, len) + } fn visit_anon_const(&mut self, c: &'v AnonConst) { walk_anon_const(self, c) } fn visit_expr(&mut self, ex: &'v Expr<'v>) { walk_expr(self, ex) } + fn visit_let_expr(&mut self, lex: &'v Let<'v>) { + walk_let_expr(self, lex) + } fn visit_ty(&mut self, t: &'v Ty<'v>) { walk_ty(self, t) } @@ -545,7 +525,7 @@ pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime | LifetimeName::Param(ParamName::Error) | LifetimeName::Static | LifetimeName::Error - | LifetimeName::Implicit + | LifetimeName::Implicit(_) | LifetimeName::ImplicitObjectLifetimeDefault | LifetimeName::Underscore => {} } @@ -750,7 +730,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) { } TyKind::Array(ref ty, ref length) => { visitor.visit_ty(ty); - visitor.visit_anon_const(length) + visitor.visit_array_length(length) } TyKind::TraitObject(bounds, ref lifetime, _syntax) => { for bound in bounds { @@ -821,12 +801,11 @@ pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>( visitor.visit_ident(type_binding.ident); visitor.visit_generic_args(type_binding.span, type_binding.gen_args); match type_binding.kind { - TypeBindingKind::Equality { ref ty } => { - visitor.visit_ty(ty); - } - TypeBindingKind::Constraint { bounds } => { - walk_list!(visitor, visit_param_bound, bounds); - } + TypeBindingKind::Equality { ref term } => match term { + Term::Ty(ref ty) => visitor.visit_ty(ty), + Term::Const(ref c) => visitor.visit_anon_const(c), + }, + TypeBindingKind::Constraint { bounds } => walk_list!(visitor, visit_param_bound, bounds), } } @@ -1082,7 +1061,8 @@ pub fn walk_foreign_item_ref<'v, V: Visitor<'v>>( pub fn walk_impl_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, impl_item_ref: &'v ImplItemRef) { // N.B., deliberately force a compilation error if/when new fields are added. - let ImplItemRef { id, ident, ref kind, span: _, ref defaultness } = *impl_item_ref; + let ImplItemRef { id, ident, ref kind, span: _, ref defaultness, trait_item_def_id: _ } = + *impl_item_ref; visitor.visit_nested_impl_item(id); visitor.visit_ident(ident); visitor.visit_associated_item_kind(kind); @@ -1121,11 +1101,26 @@ pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt<'v>) { } } +pub fn walk_array_len<'v, V: Visitor<'v>>(visitor: &mut V, len: &'v ArrayLen) { + match len { + &ArrayLen::Infer(hir_id, _span) => visitor.visit_id(hir_id), + ArrayLen::Body(c) => visitor.visit_anon_const(c), + } +} + pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonConst) { visitor.visit_id(constant.hir_id); visitor.visit_nested_body(constant.body); } +pub fn walk_let_expr<'v, V: Visitor<'v>>(visitor: &mut V, let_expr: &'v Let<'v>) { + // match the visit order in walk_local + visitor.visit_expr(let_expr.init); + visitor.visit_id(let_expr.hir_id); + visitor.visit_pat(let_expr.pat); + walk_list!(visitor, visit_ty, let_expr.ty); +} + pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) { visitor.visit_id(expression.hir_id); match expression.kind { @@ -1136,7 +1131,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) ExprKind::ConstBlock(ref anon_const) => visitor.visit_anon_const(anon_const), ExprKind::Repeat(ref element, ref count) => { visitor.visit_expr(element); - visitor.visit_anon_const(count) + visitor.visit_array_length(count) } ExprKind::Struct(ref qpath, fields, ref optional_base) => { visitor.visit_qpath(qpath, expression.hir_id, expression.span); @@ -1154,7 +1149,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) visitor.visit_expr(callee_expression); walk_list!(visitor, visit_expr, arguments); } - ExprKind::MethodCall(ref segment, _, arguments, _) => { + ExprKind::MethodCall(ref segment, arguments, _) => { visitor.visit_path_segment(expression.span, segment); walk_list!(visitor, visit_expr, arguments); } @@ -1172,10 +1167,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) ExprKind::DropTemps(ref subexpression) => { visitor.visit_expr(subexpression); } - ExprKind::Let(ref pat, ref expr, _) => { - visitor.visit_expr(expr); - visitor.visit_pat(pat); - } + ExprKind::Let(ref let_expr) => visitor.visit_let_expr(let_expr), ExprKind::If(ref cond, ref then, ref else_opt) => { visitor.visit_expr(cond); visitor.visit_expr(then); @@ -1233,10 +1225,6 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) ExprKind::InlineAsm(ref asm) => { walk_inline_asm(visitor, asm); } - ExprKind::LlvmInlineAsm(ref asm) => { - walk_list!(visitor, visit_expr, asm.outputs_exprs); - walk_list!(visitor, visit_expr, asm.inputs_exprs); - } ExprKind::Yield(ref subexpression, _) => { visitor.visit_expr(subexpression); } diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 3037996d48b..be4849d0b84 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -151,20 +151,12 @@ impl<CTX> HashStable<CTX> for LangItem { /// Extracts the first `lang = "$name"` out of a list of attributes. /// The attributes `#[panic_handler]` and `#[alloc_error_handler]` /// are also extracted out when found. -/// -/// About the `check_name` argument: passing in a `Session` would be simpler, -/// because then we could call `Session::check_name` directly. But we want to -/// avoid the need for `rustc_hir` to depend on `rustc_session`, so we -/// use a closure instead. -pub fn extract<'a, F>(check_name: F, attrs: &'a [ast::Attribute]) -> Option<(Symbol, Span)> -where - F: Fn(&'a ast::Attribute, Symbol) -> bool, -{ +pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> { attrs.iter().find_map(|attr| { Some(match attr { - _ if check_name(attr, sym::lang) => (attr.value_str()?, attr.span), - _ if check_name(attr, sym::panic_handler) => (sym::panic_impl, attr.span), - _ if check_name(attr, sym::alloc_error_handler) => (sym::oom, attr.span), + _ if attr.has_name(sym::lang) => (attr.value_str()?, attr.span), + _ if attr.has_name(sym::panic_handler) => (sym::panic_impl, attr.span), + _ if attr.has_name(sym::alloc_error_handler) => (sym::oom, attr.span), _ => return None, }) }) @@ -268,6 +260,7 @@ language_item_table! { Future, sym::future_trait, future_trait, Target::Trait, GenericRequirement::Exact(0); GeneratorState, sym::generator_state, gen_state, Target::Enum, GenericRequirement::None; Generator, sym::generator, gen_trait, Target::Trait, GenericRequirement::Minimum(1); + GeneratorReturn, sym::generator_return, generator_return, Target::AssocTy, GenericRequirement::None; Unpin, sym::unpin, unpin_trait, Target::Trait, GenericRequirement::None; Pin, sym::pin, pin_type, Target::Struct, GenericRequirement::None; @@ -290,6 +283,7 @@ language_item_table! { PanicInfo, sym::panic_info, panic_info, Target::Struct, GenericRequirement::None; PanicLocation, sym::panic_location, panic_location, Target::Struct, GenericRequirement::None; PanicImpl, sym::panic_impl, panic_impl, Target::Fn, GenericRequirement::None; + PanicNoUnwind, sym::panic_no_unwind, panic_no_unwind, Target::Fn, GenericRequirement::Exact(0); /// libstd panic entry point. Necessary for const eval to be able to catch it BeginPanic, sym::begin_panic, begin_panic_fn, Target::Fn, GenericRequirement::None; @@ -347,6 +341,7 @@ language_item_table! { ControlFlowContinue, sym::Continue, cf_continue_variant, Target::Variant, GenericRequirement::None; ControlFlowBreak, sym::Break, cf_break_variant, Target::Variant, GenericRequirement::None; + IntoFutureIntoFuture, sym::into_future, into_future_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None; IntoIterIntoIter, sym::into_iter, into_iter_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None; IteratorNext, sym::next, next_fn, Target::Method(MethodKind::Trait { body: false}), GenericRequirement::None; diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 93224d388c0..f1d62d03cbc 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -2,9 +2,9 @@ //! //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html +#![feature(associated_type_defaults)] #![feature(const_btree_new)] #![feature(crate_visibility_modifier)] -#![feature(in_band_lifetimes)] #![feature(once_cell)] #![feature(min_specialization)] #![feature(never_type)] diff --git a/compiler/rustc_hir/src/pat_util.rs b/compiler/rustc_hir/src/pat_util.rs index b1f78a83e74..b30076100bb 100644 --- a/compiler/rustc_hir/src/pat_util.rs +++ b/compiler/rustc_hir/src/pat_util.rs @@ -2,6 +2,7 @@ use crate::def::{CtorOf, DefKind, Res}; use crate::def_id::DefId; use crate::hir::{self, HirId, PatKind}; use rustc_data_structures::stable_set::FxHashSet; +use rustc_span::hygiene::DesugaringKind; use rustc_span::symbol::Ident; use rustc_span::Span; @@ -143,4 +144,14 @@ impl hir::Pat<'_> { }); result } + + /// If the pattern is `Some(<pat>)` from a desugared for loop, returns the inner pattern + pub fn for_loop_some(&self) -> Option<&Self> { + if self.span.desugaring_kind() == Some(DesugaringKind::ForLoop) { + if let hir::PatKind::Struct(_, [pat_field], _) = self.kind { + return Some(pat_field.pat); + } + } + None + } } diff --git a/compiler/rustc_hir/src/stable_hash_impls.rs b/compiler/rustc_hir/src/stable_hash_impls.rs index 6e7b765a0c4..b15054ae6d6 100644 --- a/compiler/rustc_hir/src/stable_hash_impls.rs +++ b/compiler/rustc_hir/src/stable_hash_impls.rs @@ -2,7 +2,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHas use crate::hir::{ AttributeMap, BodyId, Crate, Expr, ForeignItem, ForeignItemId, ImplItem, ImplItemId, Item, - ItemId, Mod, OwnerNodes, TraitCandidate, TraitItem, TraitItemId, Ty, VisibilityKind, + ItemId, OwnerNodes, TraitCandidate, TraitItem, TraitItemId, Ty, VisibilityKind, }; use crate::hir_id::{HirId, ItemLocalId}; use rustc_span::def_id::DefPathHash; @@ -16,7 +16,6 @@ pub trait HashStableContext: fn hash_hir_id(&mut self, _: HirId, hasher: &mut StableHasher); fn hash_body_id(&mut self, _: BodyId, hasher: &mut StableHasher); fn hash_reference_to_item(&mut self, _: HirId, hasher: &mut StableHasher); - fn hash_hir_mod(&mut self, _: &Mod<'_>, hasher: &mut StableHasher); fn hash_hir_expr(&mut self, _: &Expr<'_>, hasher: &mut StableHasher); fn hash_hir_ty(&mut self, _: &Ty<'_>, hasher: &mut StableHasher); fn hash_hir_visibility_kind(&mut self, _: &VisibilityKind<'_>, hasher: &mut StableHasher); @@ -132,12 +131,6 @@ impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for TraitItemId { } } -impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for Mod<'_> { - fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { - hcx.hash_hir_mod(self, hasher) - } -} - impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for Expr<'_> { fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { hcx.hash_hir_expr(self, hasher) @@ -211,17 +204,22 @@ impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for Item<'_> { } } -impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for OwnerNodes<'tcx> { +impl<'tcx, HirCtx: crate::HashStableContext> HashStable<HirCtx> for OwnerNodes<'tcx> { fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { // We ignore the `nodes` and `bodies` fields since these refer to information included in // `hash` which is hashed in the collector and used for the crate hash. - let OwnerNodes { hash_including_bodies, hash_without_bodies: _, nodes: _, bodies: _ } = - *self; + let OwnerNodes { + hash_including_bodies, + hash_without_bodies: _, + nodes: _, + bodies: _, + local_id_to_def_id: _, + } = *self; hash_including_bodies.hash_stable(hcx, hasher); } } -impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for AttributeMap<'tcx> { +impl<'tcx, HirCtx: crate::HashStableContext> HashStable<HirCtx> for AttributeMap<'tcx> { fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { // We ignore the `map` since it refers to information included in `hash` which is hashed in // the collector and used for the crate hash. diff --git a/compiler/rustc_hir/src/weak_lang_items.rs b/compiler/rustc_hir/src/weak_lang_items.rs index 58c3065240c..78748209d1a 100644 --- a/compiler/rustc_hir/src/weak_lang_items.rs +++ b/compiler/rustc_hir/src/weak_lang_items.rs @@ -18,13 +18,9 @@ pub static WEAK_ITEMS_REFS: SyncLazy<StableMap<Symbol, LangItem>> = SyncLazy::ne map }); -/// The `check_name` argument avoids the need for `rustc_hir` to depend on -/// `rustc_session`. -pub fn link_name<'a, F>(check_name: F, attrs: &'a [ast::Attribute]) -> Option<Symbol> -where - F: Fn(&'a ast::Attribute, Symbol) -> bool +pub fn link_name(attrs: &[ast::Attribute]) -> Option<Symbol> { - lang_items::extract(check_name, attrs).and_then(|(name, _)| { + lang_items::extract(attrs).and_then(|(name, _)| { $(if name == sym::$name { Some(sym::$sym) } else)* { | 
