diff options
Diffstat (limited to 'compiler/rustc_hir')
-rw-r--r-- | compiler/rustc_hir/src/arena.rs | 1 | ||||
-rw-r--r-- | compiler/rustc_hir/src/def.rs | 22 | ||||
-rw-r--r-- | compiler/rustc_hir/src/definitions.rs | 8 | ||||
-rw-r--r-- | compiler/rustc_hir/src/hir.rs | 223 | ||||
-rw-r--r-- | compiler/rustc_hir/src/hir_id.rs | 22 | ||||
-rw-r--r-- | compiler/rustc_hir/src/intravisit.rs | 742 | ||||
-rw-r--r-- | compiler/rustc_hir/src/lang_items.rs | 230 | ||||
-rw-r--r-- | compiler/rustc_hir/src/lib.rs | 3 | ||||
-rw-r--r-- | compiler/rustc_hir/src/pat_util.rs | 5 | ||||
-rw-r--r-- | compiler/rustc_hir/src/tests.rs | 38 | ||||
-rw-r--r-- | compiler/rustc_hir/src/weak_lang_items.rs | 59 |
11 files changed, 706 insertions, 647 deletions
diff --git a/compiler/rustc_hir/src/arena.rs b/compiler/rustc_hir/src/arena.rs index 44335b7f4..c89e7eb75 100644 --- a/compiler/rustc_hir/src/arena.rs +++ b/compiler/rustc_hir/src/arena.rs @@ -39,6 +39,7 @@ macro_rules! arena_types { [] param: rustc_hir::Param<'tcx>, [] pat: rustc_hir::Pat<'tcx>, [] path: rustc_hir::Path<'tcx>, + [] use_path: rustc_hir::UsePath<'tcx>, [] path_segment: rustc_hir::PathSegment<'tcx>, [] poly_trait_ref: rustc_hir::PolyTraitRef<'tcx>, [] qpath: rustc_hir::QPath<'tcx>, diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 4ef4aad90..149cf4ece 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -28,8 +28,6 @@ pub enum CtorKind { Fn, /// Constructor constant automatically created by a unit struct/variant. Const, - /// Unusable name in value namespace created by a struct variant. - Fictive, } /// An attribute that is not a macro; e.g., `#[inline]` or `#[rustfmt::skip]`. @@ -132,13 +130,9 @@ impl DefKind { DefKind::Variant => "variant", DefKind::Ctor(CtorOf::Variant, CtorKind::Fn) => "tuple variant", DefKind::Ctor(CtorOf::Variant, CtorKind::Const) => "unit variant", - DefKind::Ctor(CtorOf::Variant, CtorKind::Fictive) => "struct variant", DefKind::Struct => "struct", DefKind::Ctor(CtorOf::Struct, CtorKind::Fn) => "tuple struct", DefKind::Ctor(CtorOf::Struct, CtorKind::Const) => "unit struct", - DefKind::Ctor(CtorOf::Struct, CtorKind::Fictive) => { - panic!("impossible struct constructor") - } DefKind::OpaqueTy => "opaque type", DefKind::ImplTraitPlaceholder => "opaque type in trait", DefKind::TyAlias => "type alias", @@ -562,19 +556,11 @@ impl<T> PerNS<Option<T>> { } impl CtorKind { - pub fn from_ast(vdata: &ast::VariantData) -> CtorKind { - match *vdata { - ast::VariantData::Tuple(..) => CtorKind::Fn, - ast::VariantData::Unit(..) => CtorKind::Const, - ast::VariantData::Struct(..) => CtorKind::Fictive, - } - } - - pub fn from_hir(vdata: &hir::VariantData<'_>) -> CtorKind { + pub fn from_ast(vdata: &ast::VariantData) -> Option<(CtorKind, NodeId)> { match *vdata { - hir::VariantData::Tuple(..) => CtorKind::Fn, - hir::VariantData::Unit(..) => CtorKind::Const, - hir::VariantData::Struct(..) => CtorKind::Fictive, + ast::VariantData::Tuple(_, node_id) => Some((CtorKind::Fn, node_id)), + ast::VariantData::Unit(node_id) => Some((CtorKind::Const, node_id)), + ast::VariantData::Struct(..) => None, } } } diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs index d85ac960f..dd37efb69 100644 --- a/compiler/rustc_hir/src/definitions.rs +++ b/compiler/rustc_hir/src/definitions.rs @@ -368,10 +368,6 @@ impl Definitions { LocalDefId { local_def_index: self.table.allocate(key, def_path_hash) } } - pub fn iter_local_def_id(&self) -> impl Iterator<Item = LocalDefId> + '_ { - self.table.def_path_hashes.indices().map(|local_def_index| LocalDefId { local_def_index }) - } - #[inline(always)] pub fn local_def_path_hash_to_def_id( &self, @@ -389,6 +385,10 @@ impl Definitions { pub fn def_path_hash_to_def_index_map(&self) -> &DefPathHashMap { &self.table.def_path_hash_to_index } + + pub fn num_definitions(&self) -> usize { + self.table.def_path_hashes.len() + } } #[derive(Copy, Clone, PartialEq, Debug)] diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index ef00c1ffc..8bc022e1e 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -29,15 +29,16 @@ use std::fmt; #[derive(Debug, Copy, Clone, Encodable, HashStable_Generic)] pub struct Lifetime { pub hir_id: HirId, - pub span: Span, /// Either "`'a`", referring to a named lifetime definition, - /// or "``" (i.e., `kw::Empty`), for elision placeholders. + /// `'_` referring to an anonymous lifetime (either explicitly `'_` or `&type`), + /// or "``" (i.e., `kw::Empty`) when appearing in path. /// - /// HIR lowering inserts these placeholders in type paths that - /// refer to type definitions needing lifetime parameters, - /// `&T` and `&mut T`, and trait objects without `... + 'a`. - pub name: LifetimeName, + /// See `Lifetime::suggestion_position` for practical use. + pub ident: Ident, + + /// Semantics of this lifetime. + pub res: LifetimeName, } #[derive(Debug, Clone, PartialEq, Eq, Encodable, Hash, Copy)] @@ -88,7 +89,7 @@ impl ParamName { #[derive(HashStable_Generic)] pub enum LifetimeName { /// User-given names or fresh (synthetic) names. - Param(LocalDefId, ParamName), + Param(LocalDefId), /// Implicit lifetime in a context like `dyn Foo`. This is /// distinguished from implicit lifetimes elsewhere because the @@ -116,25 +117,6 @@ pub enum LifetimeName { } impl LifetimeName { - pub fn ident(&self) -> Ident { - match *self { - LifetimeName::ImplicitObjectLifetimeDefault | LifetimeName::Error => Ident::empty(), - LifetimeName::Infer => Ident::with_dummy_span(kw::UnderscoreLifetime), - LifetimeName::Static => Ident::with_dummy_span(kw::StaticLifetime), - LifetimeName::Param(_, param_name) => param_name.ident(), - } - } - - pub fn is_anonymous(&self) -> bool { - match *self { - LifetimeName::ImplicitObjectLifetimeDefault - | LifetimeName::Infer - | LifetimeName::Param(_, ParamName::Fresh) - | LifetimeName::Error => true, - LifetimeName::Static | LifetimeName::Param(..) => false, - } - } - pub fn is_elided(&self) -> bool { match self { LifetimeName::ImplicitObjectLifetimeDefault | LifetimeName::Infer => true, @@ -146,34 +128,54 @@ impl LifetimeName { LifetimeName::Error | LifetimeName::Param(..) | LifetimeName::Static => false, } } - - fn is_static(&self) -> bool { - self == &LifetimeName::Static - } - - pub fn normalize_to_macros_2_0(&self) -> LifetimeName { - match *self { - LifetimeName::Param(def_id, param_name) => { - LifetimeName::Param(def_id, param_name.normalize_to_macros_2_0()) - } - lifetime_name => lifetime_name, - } - } } impl fmt::Display for Lifetime { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.name.ident().fmt(f) + if self.ident.name != kw::Empty { self.ident.name.fmt(f) } else { "'_".fmt(f) } } } +pub enum LifetimeSuggestionPosition { + /// The user wrote `'a` or `'_`. + Normal, + /// The user wrote `&type` or `&mut type`. + Ampersand, + /// The user wrote `Path` and omitted the `<'_>`. + ElidedPath, + /// The user wrote `Path<T>`, and omitted the `'_,`. + ElidedPathArgument, + /// The user wrote `dyn Trait` and omitted the `+ '_`. + ObjectDefault, +} + impl Lifetime { pub fn is_elided(&self) -> bool { - self.name.is_elided() + self.res.is_elided() + } + + pub fn is_anonymous(&self) -> bool { + self.ident.name == kw::Empty || self.ident.name == kw::UnderscoreLifetime + } + + pub fn suggestion_position(&self) -> (LifetimeSuggestionPosition, Span) { + if self.ident.name == kw::Empty { + if self.ident.span.is_empty() { + (LifetimeSuggestionPosition::ElidedPathArgument, self.ident.span) + } else { + (LifetimeSuggestionPosition::ElidedPath, self.ident.span.shrink_to_hi()) + } + } else if self.res == LifetimeName::ImplicitObjectLifetimeDefault { + (LifetimeSuggestionPosition::ObjectDefault, self.ident.span) + } else if self.ident.span.is_empty() { + (LifetimeSuggestionPosition::Ampersand, self.ident.span) + } else { + (LifetimeSuggestionPosition::Normal, self.ident.span) + } } pub fn is_static(&self) -> bool { - self.name.is_static() + self.res == LifetimeName::Static } } @@ -181,14 +183,17 @@ impl Lifetime { /// `std::cmp::PartialEq`. It's represented as a sequence of identifiers, /// along with a bunch of supporting information. #[derive(Debug, HashStable_Generic)] -pub struct Path<'hir> { +pub struct Path<'hir, R = Res> { pub span: Span, /// The resolution for the path. - pub res: Res, + pub res: R, /// The segments in the path: the things separated by `::`. pub segments: &'hir [PathSegment<'hir>], } +/// Up to three resolutions for type, value and macro namespaces. +pub type UsePath<'hir> = Path<'hir, SmallVec<[Res; 3]>>; + impl Path<'_> { pub fn is_global(&self) -> bool { !self.segments.is_empty() && self.segments[0].ident.name == kw::PathRoot @@ -267,7 +272,7 @@ pub enum GenericArg<'hir> { impl GenericArg<'_> { pub fn span(&self) -> Span { match self { - GenericArg::Lifetime(l) => l.span, + GenericArg::Lifetime(l) => l.ident.span, GenericArg::Type(t) => t.span, GenericArg::Const(c) => c.span, GenericArg::Infer(i) => i.span, @@ -284,7 +289,7 @@ impl GenericArg<'_> { } pub fn is_synthetic(&self) -> bool { - matches!(self, GenericArg::Lifetime(lifetime) if lifetime.name.ident() == Ident::empty()) + matches!(self, GenericArg::Lifetime(lifetime) if lifetime.ident == Ident::empty()) } pub fn descr(&self) -> &'static str { @@ -388,6 +393,8 @@ impl<'hir> GenericArgs<'hir> { } #[inline] + /// This function returns the number of type and const generic params. + /// It should only be used for diagnostics. pub fn num_generic_params(&self) -> usize { self.args.iter().filter(|arg| !matches!(arg, GenericArg::Lifetime(_))).count() } @@ -444,7 +451,7 @@ impl GenericBound<'_> { match self { GenericBound::Trait(t, ..) => t.span, GenericBound::LangItemTrait(_, span, ..) => *span, - GenericBound::Outlives(l) => l.span, + GenericBound::Outlives(l) => l.ident.span, } } } @@ -485,6 +492,7 @@ pub enum GenericParamKind<'hir> { #[derive(Debug, HashStable_Generic)] pub struct GenericParam<'hir> { pub hir_id: HirId, + pub def_id: LocalDefId, pub name: ParamName, pub span: Span, pub pure_wrt_drop: bool, @@ -557,6 +565,19 @@ impl<'hir> Generics<'hir> { } /// If there are generic parameters, return where to introduce a new one. + pub fn span_for_lifetime_suggestion(&self) -> Option<Span> { + if let Some(first) = self.params.first() + && self.span.contains(first.span) + { + // `fn foo<A>(t: impl Trait)` + // ^ suggest `'a, ` here + Some(first.span.shrink_to_lo()) + } else { + None + } + } + + /// If there are generic parameters, return where to introduce a new one. pub fn span_for_param_suggestion(&self) -> Option<Span> { if self.params.iter().any(|p| self.span.contains(p.span)) { // `fn foo<A>(t: impl Trait)` @@ -762,10 +783,7 @@ pub struct WhereRegionPredicate<'hir> { impl<'hir> WhereRegionPredicate<'hir> { /// Returns `true` if `param_def_id` matches the `lifetime` of this predicate. pub fn is_param_bound(&self, param_def_id: LocalDefId) -> bool { - match self.lifetime.name { - LifetimeName::Param(id, _) => id == param_def_id, - _ => false, - } + self.lifetime.res == LifetimeName::Param(param_def_id) } } @@ -809,7 +827,7 @@ impl<'tcx> AttributeMap<'tcx> { pub struct OwnerNodes<'tcx> { /// Pre-computed hash of the full HIR. pub hash_including_bodies: Fingerprint, - /// Pre-computed hash of the item signature, sithout recursing into the body. + /// Pre-computed hash of the item signature, without recursing into the body. pub hash_without_bodies: Fingerprint, /// Full HIR for the current owner. // The zeroth node's parent should never be accessed: the owner's parent is computed by the @@ -919,12 +937,16 @@ pub struct Crate<'hir> { #[derive(Debug, HashStable_Generic)] pub struct Closure<'hir> { + pub def_id: LocalDefId, pub binder: ClosureBinder, pub capture_clause: CaptureBy, pub bound_generic_params: &'hir [GenericParam<'hir>], pub fn_decl: &'hir FnDecl<'hir>, pub body: BodyId, + /// The span of the declaration block: 'move |...| -> ...' pub fn_decl_span: Span, + /// The span of the argument block `|...|` + pub fn_arg_span: Option<Span>, pub movability: Option<Movability>, } @@ -965,8 +987,8 @@ pub struct Pat<'hir> { pub hir_id: HirId, pub kind: PatKind<'hir>, pub span: Span, - // Whether to use default binding modes. - // At present, this is false only for destructuring assignment. + /// Whether to use default binding modes. + /// At present, this is false only for destructuring assignment. pub default_binding_modes: bool, } @@ -1074,7 +1096,7 @@ impl fmt::Display for RangeEnd { pub struct DotDotPos(u32); impl DotDotPos { - // Panics if n >= u32::MAX. + /// Panics if n >= u32::MAX. pub fn new(n: Option<usize>) -> Self { match n { Some(n) => { @@ -1510,9 +1532,9 @@ pub enum AsyncGeneratorKind { impl fmt::Display for AsyncGeneratorKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(match self { - AsyncGeneratorKind::Block => "`async` block", - AsyncGeneratorKind::Closure => "`async` closure body", - AsyncGeneratorKind::Fn => "`async fn` body", + AsyncGeneratorKind::Block => "async block", + AsyncGeneratorKind::Closure => "async closure body", + AsyncGeneratorKind::Fn => "async fn body", }) } } @@ -1613,7 +1635,7 @@ pub enum ArrayLen { impl ArrayLen { pub fn hir_id(&self) -> HirId { match self { - &ArrayLen::Infer(hir_id, _) | &ArrayLen::Body(AnonConst { hir_id, body: _ }) => hir_id, + &ArrayLen::Infer(hir_id, _) | &ArrayLen::Body(AnonConst { hir_id, .. }) => hir_id, } } } @@ -1625,10 +1647,11 @@ impl ArrayLen { /// explicit discriminant values for enum variants. /// /// You can check if this anon const is a default in a const param -/// `const N: usize = { ... }` with `tcx.hir().opt_const_param_default_param_hir_id(..)` +/// `const N: usize = { ... }` with `tcx.hir().opt_const_param_default_param_def_id(..)` #[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug, HashStable_Generic)] pub struct AnonConst { pub hir_id: HirId, + pub def_id: LocalDefId, pub body: BodyId, } @@ -1677,10 +1700,10 @@ impl Expr<'_> { } } - // Whether this looks like a place expr, without checking for deref - // adjustments. - // This will return `true` in some potentially surprising cases such as - // `CONSTANT.field`. + /// Whether this looks like a place expr, without checking for deref + /// adjustments. + /// This will return `true` in some potentially surprising cases such as + /// `CONSTANT.field`. pub fn is_syntactic_place_expr(&self) -> bool { self.is_place_expr(|_| true) } @@ -1821,7 +1844,7 @@ impl Expr<'_> { } } - // To a first-order approximation, is this a pattern + /// To a first-order approximation, is this a pattern? pub fn is_approximately_pattern(&self) -> bool { match &self.kind { ExprKind::Box(_) @@ -2143,11 +2166,11 @@ impl fmt::Display for LoopIdError { #[derive(Copy, Clone, Encodable, Debug, HashStable_Generic)] pub struct Destination { - // This is `Some(_)` iff there is an explicit user-specified `label + /// This is `Some(_)` iff there is an explicit user-specified 'label pub label: Option<Label>, - // These errors are caught and then reported during the diagnostics pass in - // librustc_passes/loops.rs + /// These errors are caught and then reported during the diagnostics pass in + /// `librustc_passes/loops.rs` pub target_id: Result<HirId, LoopIdError>, } @@ -2318,7 +2341,7 @@ pub enum ImplItemKind<'hir> { Type(&'hir Ty<'hir>), } -// The name of the associated type for `Fn` return types. +/// The name of the associated type for `Fn` return types. pub const FN_OUTPUT_NAME: Symbol = sym::Output; /// Bind a type to an associated type (i.e., `A = Foo`). @@ -2414,7 +2437,7 @@ impl<'hir> Ty<'hir> { pub fn peel_refs(&self) -> &Self { let mut final_ty = self; while let TyKind::Rptr(_, MutTy { ty, .. }) = &final_ty.kind { - final_ty = &ty; + final_ty = ty; } final_ty } @@ -2683,6 +2706,8 @@ pub struct FnDecl<'hir> { pub c_variadic: bool, /// Does the function have an implicit self? pub implicit_self: ImplicitSelfKind, + /// Is lifetime elision allowed. + pub lifetime_elision_allowed: bool, } /// Represents what type of implicit self a function has, if any. @@ -2715,6 +2740,12 @@ pub enum IsAsync { NotAsync, } +impl IsAsync { + pub fn is_async(self) -> bool { + self == IsAsync::Async + } +} + #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Encodable, Decodable, HashStable_Generic)] pub enum Defaultness { Default { has_value: bool }, @@ -2796,7 +2827,8 @@ pub struct Variant<'hir> { /// Name of the variant. pub ident: Ident, /// Id of the variant (not the constructor, see `VariantData::ctor_hir_id()`). - pub id: HirId, + pub hir_id: HirId, + pub def_id: LocalDefId, /// Fields and constructor id of the variant. pub data: VariantData<'hir>, /// Explicit discriminant (e.g., `Foo = 1`). @@ -2863,6 +2895,7 @@ pub struct FieldDef<'hir> { pub vis_span: Span, pub ident: Ident, pub hir_id: HirId, + pub def_id: LocalDefId, pub ty: &'hir Ty<'hir>, } @@ -2884,11 +2917,11 @@ pub enum VariantData<'hir> { /// A tuple variant. /// /// E.g., `Bar(..)` as in `enum Foo { Bar(..) }`. - Tuple(&'hir [FieldDef<'hir>], HirId), + Tuple(&'hir [FieldDef<'hir>], HirId, LocalDefId), /// A unit variant. /// /// E.g., `Bar = ..` as in `enum Foo { Bar = .. }`. - Unit(HirId), + Unit(HirId, LocalDefId), } impl<'hir> VariantData<'hir> { @@ -2900,13 +2933,30 @@ impl<'hir> VariantData<'hir> { } } - /// Return the `HirId` of this variant's constructor, if it has one. - pub fn ctor_hir_id(&self) -> Option<HirId> { + pub fn ctor(&self) -> Option<(CtorKind, HirId, LocalDefId)> { match *self { - VariantData::Struct(_, _) => None, - VariantData::Tuple(_, hir_id) | VariantData::Unit(hir_id) => Some(hir_id), + VariantData::Tuple(_, hir_id, def_id) => Some((CtorKind::Fn, hir_id, def_id)), + VariantData::Unit(hir_id, def_id) => Some((CtorKind::Const, hir_id, def_id)), + VariantData::Struct(..) => None, } } + + #[inline] + pub fn ctor_kind(&self) -> Option<CtorKind> { + self.ctor().map(|(kind, ..)| kind) + } + + /// Return the `HirId` of this variant's constructor, if it has one. + #[inline] + pub fn ctor_hir_id(&self) -> Option<HirId> { + self.ctor().map(|(_, hir_id, _)| hir_id) + } + + /// Return the `LocalDefId` of this variant's constructor, if it has one. + #[inline] + pub fn ctor_def_id(&self) -> Option<LocalDefId> { + self.ctor().map(|(.., def_id)| def_id) + } } // The bodies for items are stored "out of line", in a separate @@ -3024,7 +3074,7 @@ pub enum ItemKind<'hir> { /// or just /// /// `use foo::bar::baz;` (with `as baz` implicitly on the right). - Use(&'hir Path<'hir>, UseKind), + Use(&'hir UsePath<'hir>, UseKind), /// A `static` item. Static(&'hir Ty<'hir>, Mutability, BodyId), @@ -3217,7 +3267,7 @@ pub enum ForeignItemKind<'hir> { /// A variable captured by a closure. #[derive(Debug, Copy, Clone, Encodable, HashStable_Generic)] pub struct Upvar { - // First span where it is accessed (there can be multiple). + /// First span where it is accessed (there can be multiple). pub span: Span, } @@ -3423,7 +3473,7 @@ impl<'hir> Node<'hir> { | Node::Variant(Variant { ident, .. }) | Node::Item(Item { ident, .. }) | Node::PathSegment(PathSegment { ident, .. }) => Some(*ident), - Node::Lifetime(lt) => Some(lt.name.ident()), + Node::Lifetime(lt) => Some(lt.ident), Node::GenericParam(p) => Some(p.name.ident()), Node::TypeBinding(b) => Some(b.ident), Node::Param(..) @@ -3530,7 +3580,7 @@ impl<'hir> Node<'hir> { /// Get the fields for the tuple-constructor, /// if this node is a tuple constructor, otherwise None pub fn tuple_fields(&self) -> Option<&'hir [FieldDef<'hir>]> { - if let Node::Ctor(&VariantData::Tuple(fields, _)) = self { Some(fields) } else { None } + if let Node::Ctor(&VariantData::Tuple(fields, _, _)) = self { Some(fields) } else { None } } } @@ -3546,7 +3596,7 @@ mod size_asserts { static_assert_size!(FnDecl<'_>, 40); static_assert_size!(ForeignItem<'_>, 72); static_assert_size!(ForeignItemKind<'_>, 40); - static_assert_size!(GenericArg<'_>, 24); + static_assert_size!(GenericArg<'_>, 32); static_assert_size!(GenericBound<'_>, 48); static_assert_size!(Generics<'_>, 56); static_assert_size!(Impl<'_>, 80); @@ -3564,9 +3614,16 @@ mod size_asserts { static_assert_size!(Res, 12); static_assert_size!(Stmt<'_>, 32); static_assert_size!(StmtKind<'_>, 16); + // tidy-alphabetical-end + // FIXME: move the tidy directive to the end after the next bootstrap bump + #[cfg(bootstrap)] static_assert_size!(TraitItem<'_>, 88); + #[cfg(not(bootstrap))] + static_assert_size!(TraitItem<'_>, 80); + #[cfg(bootstrap)] static_assert_size!(TraitItemKind<'_>, 48); + #[cfg(not(bootstrap))] + static_assert_size!(TraitItemKind<'_>, 40); static_assert_size!(Ty<'_>, 48); static_assert_size!(TyKind<'_>, 32); - // tidy-alphabetical-end } diff --git a/compiler/rustc_hir/src/hir_id.rs b/compiler/rustc_hir/src/hir_id.rs index 752f760ea..060f40919 100644 --- a/compiler/rustc_hir/src/hir_id.rs +++ b/compiler/rustc_hir/src/hir_id.rs @@ -1,5 +1,5 @@ -use crate::def_id::{DefId, LocalDefId, CRATE_DEF_ID}; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; +use crate::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_ID}; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableOrd, ToStableHashKey}; use rustc_span::{def_id::DefPathHash, HashStableContext}; use std::fmt; @@ -22,6 +22,18 @@ impl OwnerId { } } +impl rustc_index::vec::Idx for OwnerId { + #[inline] + fn new(idx: usize) -> Self { + OwnerId { def_id: LocalDefId { local_def_index: DefIndex::from_usize(idx) } } + } + + #[inline] + fn index(self) -> usize { + self.def_id.local_def_index.as_usize() + } +} + impl<CTX: HashStableContext> HashStable<CTX> for OwnerId { #[inline] fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { @@ -104,7 +116,7 @@ impl Ord for HirId { impl PartialOrd for HirId { fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { - Some(self.cmp(&other)) + Some(self.cmp(other)) } } @@ -134,6 +146,10 @@ impl ItemLocalId { pub const INVALID: ItemLocalId = ItemLocalId::MAX; } +// Safety: Ord is implement as just comparing the LocalItemId's numerical +// values and these are not changed by (de-)serialization. +unsafe impl StableOrd for ItemLocalId {} + /// The `HirId` corresponding to `CRATE_NODE_ID` and `CRATE_DEF_ID`. pub const CRATE_HIR_ID: HirId = HirId { owner: OwnerId { def_id: CRATE_DEF_ID }, local_id: ItemLocalId::from_u32(0) }; diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index be77e6fd3..938ace2c7 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -358,13 +358,16 @@ pub trait Visitor<'v>: Sized { fn visit_where_predicate(&mut self, predicate: &'v WherePredicate<'v>) { walk_where_predicate(self, predicate) } + fn visit_fn_ret_ty(&mut self, ret_ty: &'v FnRetTy<'v>) { + walk_fn_ret_ty(self, ret_ty) + } fn visit_fn_decl(&mut self, fd: &'v FnDecl<'v>) { walk_fn_decl(self, fd) } fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl<'v>, b: BodyId, _: Span, id: HirId) { walk_fn(self, fk, fd, b, id) } - fn visit_use(&mut self, path: &'v Path<'v>, hir_id: HirId) { + fn visit_use(&mut self, path: &'v UsePath<'v>, hir_id: HirId) { walk_use(self, path, hir_id) } fn visit_trait_item(&mut self, ti: &'v TraitItem<'v>) { @@ -410,12 +413,7 @@ pub trait Visitor<'v>: Sized { walk_inf(self, inf); } fn visit_generic_arg(&mut self, generic_arg: &'v GenericArg<'v>) { - match generic_arg { - GenericArg::Lifetime(lt) => self.visit_lifetime(lt), - GenericArg::Type(ty) => self.visit_ty(ty), - GenericArg::Const(ct) => self.visit_anon_const(&ct.value), - GenericArg::Infer(inf) => self.visit_infer(inf), - } + walk_generic_arg(self, generic_arg); } fn visit_lifetime(&mut self, lifetime: &'v Lifetime) { walk_lifetime(self, lifetime) @@ -424,7 +422,7 @@ pub trait Visitor<'v>: Sized { fn visit_qpath(&mut self, qpath: &'v QPath<'v>, id: HirId, _span: Span) { walk_qpath(self, qpath, id) } - fn visit_path(&mut self, path: &'v Path<'v>, _id: HirId) { + fn visit_path(&mut self, path: &Path<'v>, _id: HirId) { walk_path(self, path) } fn visit_path_segment(&mut self, path_segment: &'v PathSegment<'v>) { @@ -448,66 +446,9 @@ pub trait Visitor<'v>: Sized { } } -pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod<'v>, mod_hir_id: HirId) { - visitor.visit_id(mod_hir_id); - for &item_id in module.item_ids { - visitor.visit_nested_item(item_id); - } -} - -pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &'v Body<'v>) { - walk_list!(visitor, visit_param, body.params); - visitor.visit_expr(&body.value); -} - -pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local<'v>) { - // Intentionally visiting the expr first - the initialization expr - // dominates the local's definition. - walk_list!(visitor, visit_expr, &local.init); - visitor.visit_id(local.hir_id); - visitor.visit_pat(&local.pat); - if let Some(els) = local.els { - visitor.visit_block(els); - } - walk_list!(visitor, visit_ty, &local.ty); -} - -pub fn walk_ident<'v, V: Visitor<'v>>(visitor: &mut V, ident: Ident) { - visitor.visit_name(ident.name); -} - -pub fn walk_label<'v, V: Visitor<'v>>(visitor: &mut V, label: &'v Label) { - visitor.visit_ident(label.ident); -} - -pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime) { - visitor.visit_id(lifetime.hir_id); - match lifetime.name { - LifetimeName::Param(_, ParamName::Plain(ident)) => { - visitor.visit_ident(ident); - } - LifetimeName::Param(_, ParamName::Fresh) - | LifetimeName::Param(_, ParamName::Error) - | LifetimeName::Static - | LifetimeName::Error - | LifetimeName::ImplicitObjectLifetimeDefault - | LifetimeName::Infer => {} - } -} - -pub fn walk_poly_trait_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_ref: &'v PolyTraitRef<'v>) { - walk_list!(visitor, visit_generic_param, trait_ref.bound_generic_params); - visitor.visit_trait_ref(&trait_ref.trait_ref); -} - -pub fn walk_trait_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_ref: &'v TraitRef<'v>) { - visitor.visit_id(trait_ref.hir_ref_id); - visitor.visit_path(&trait_ref.path, trait_ref.hir_ref_id) -} - pub fn walk_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Param<'v>) { visitor.visit_id(param.hir_id); - visitor.visit_pat(¶m.pat); + visitor.visit_pat(param.pat); } pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) { @@ -529,7 +470,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) { } ItemKind::Fn(ref sig, ref generics, body_id) => visitor.visit_fn( FnKind::ItemFn(item.ident, generics, sig.header), - &sig.decl, + sig.decl, body_id, item.span, item.hir_id(), @@ -601,142 +542,80 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) { } } -pub fn walk_inline_asm<'v, V: Visitor<'v>>(visitor: &mut V, asm: &'v InlineAsm<'v>, id: HirId) { - for (op, op_sp) in asm.operands { - match op { - InlineAsmOperand::In { expr, .. } | InlineAsmOperand::InOut { expr, .. } => { - visitor.visit_expr(expr) - } - InlineAsmOperand::Out { expr, .. } => { - if let Some(expr) = expr { - visitor.visit_expr(expr); - } - } - InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => { - visitor.visit_expr(in_expr); - if let Some(out_expr) = out_expr { - visitor.visit_expr(out_expr); - } - } - InlineAsmOperand::Const { anon_const, .. } - | InlineAsmOperand::SymFn { anon_const, .. } => visitor.visit_anon_const(anon_const), - InlineAsmOperand::SymStatic { path, .. } => visitor.visit_qpath(path, id, *op_sp), - } - } -} - -pub fn walk_use<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path<'v>, hir_id: HirId) { - visitor.visit_id(hir_id); - visitor.visit_path(path, hir_id); +pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &'v Body<'v>) { + walk_list!(visitor, visit_param, body.params); + visitor.visit_expr(body.value); } -pub fn walk_enum_def<'v, V: Visitor<'v>>( - visitor: &mut V, - enum_definition: &'v EnumDef<'v>, - item_id: HirId, -) { - visitor.visit_id(item_id); - walk_list!(visitor, visit_variant, enum_definition.variants); +pub fn walk_ident<'v, V: Visitor<'v>>(visitor: &mut V, ident: Ident) { + visitor.visit_name(ident.name); } -pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V, variant: &'v Variant<'v>) { - visitor.visit_ident(variant.ident); - visitor.visit_id(variant.id); - visitor.visit_variant_data(&variant.data); - walk_list!(visitor, visit_anon_const, &variant.disr_expr); +pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod<'v>, mod_hir_id: HirId) { + visitor.visit_id(mod_hir_id); + for &item_id in module.item_ids { + visitor.visit_nested_item(item_id); + } } -pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) { - visitor.visit_id(typ.hir_id); +pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v ForeignItem<'v>) { + visitor.visit_id(foreign_item.hir_id()); + visitor.visit_ident(foreign_item.ident); - match typ.kind { - TyKind::Slice(ref ty) => visitor.visit_ty(ty), - TyKind::Ptr(ref mutable_type) => visitor.visit_ty(&mutable_type.ty), - TyKind::Rptr(ref lifetime, ref mutable_type) => { - visitor.visit_lifetime(lifetime); - visitor.visit_ty(&mutable_type.ty) - } - TyKind::Never => {} - TyKind::Tup(tuple_element_types) => { - walk_list!(visitor, visit_ty, tuple_element_types); - } - TyKind::BareFn(ref function_declaration) => { - walk_list!(visitor, visit_generic_param, function_declaration.generic_params); - visitor.visit_fn_decl(&function_declaration.decl); - } - TyKind::Path(ref qpath) => { - visitor.visit_qpath(qpath, typ.hir_id, typ.span); - } - TyKind::OpaqueDef(item_id, lifetimes, _in_trait) => { - visitor.visit_nested_item(item_id); - walk_list!(visitor, visit_generic_arg, lifetimes); - } - TyKind::Array(ref ty, ref length) => { - visitor.visit_ty(ty); - visitor.visit_array_length(length) - } - TyKind::TraitObject(bounds, ref lifetime, _syntax) => { - for bound in bounds { - visitor.visit_poly_trait_ref(bound); + match foreign_item.kind { + ForeignItemKind::Fn(ref function_declaration, param_names, ref generics) => { + visitor.visit_generics(generics); + visitor.visit_fn_decl(function_declaration); + for ¶m_name in param_names { + visitor.visit_ident(param_name); } - visitor.visit_lifetime(lifetime); } - TyKind::Typeof(ref expression) => visitor.visit_anon_const(expression), - TyKind::Infer | TyKind::Err => {} + ForeignItemKind::Static(ref typ, _) => visitor.visit_ty(typ), + ForeignItemKind::Type => (), } } -pub fn walk_inf<'v, V: Visitor<'v>>(visitor: &mut V, inf: &'v InferArg) { - visitor.visit_id(inf.hir_id); -} - -pub fn walk_qpath<'v, V: Visitor<'v>>(visitor: &mut V, qpath: &'v QPath<'v>, id: HirId) { - match *qpath { - QPath::Resolved(ref maybe_qself, ref path) => { - walk_list!(visitor, visit_ty, maybe_qself); - visitor.visit_path(path, id) - } - QPath::TypeRelative(ref qself, ref segment) => { - visitor.visit_ty(qself); - visitor.visit_path_segment(segment); - } - QPath::LangItem(..) => {} +pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local<'v>) { + // Intentionally visiting the expr first - the initialization expr + // dominates the local's definition. + walk_list!(visitor, visit_expr, &local.init); + visitor.visit_id(local.hir_id); + visitor.visit_pat(local.pat); + if let Some(els) = local.els { + visitor.visit_block(els); } + walk_list!(visitor, visit_ty, &local.ty); } -pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path<'v>) { - for segment in path.segments { - visitor.visit_path_segment(segment); - } +pub fn walk_block<'v, V: Visitor<'v>>(visitor: &mut V, block: &'v Block<'v>) { + visitor.visit_id(block.hir_id); + walk_list!(visitor, visit_stmt, block.stmts); + walk_list!(visitor, visit_expr, &block.expr); } -pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V, segment: &'v PathSegment<'v>) { - visitor.visit_ident(segment.ident); - visitor.visit_id(segment.hir_id); - if let Some(ref args) = segment.args { - visitor.visit_generic_args(args); +pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt<'v>) { + visitor.visit_id(statement.hir_id); + match statement.kind { + StmtKind::Local(ref local) => visitor.visit_local(local), + StmtKind::Item(item) => visitor.visit_nested_item(item), + StmtKind::Expr(ref expression) | StmtKind::Semi(ref expression) => { + visitor.visit_expr(expression) + } } } -pub fn walk_generic_args<'v, V: Visitor<'v>>(visitor: &mut V, generic_args: &'v GenericArgs<'v>) { - walk_list!(visitor, visit_generic_arg, generic_args.args); - walk_list!(visitor, visit_assoc_type_binding, generic_args.bindings); -} - -pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>( - visitor: &mut V, - type_binding: &'v TypeBinding<'v>, -) { - visitor.visit_id(type_binding.hir_id); - visitor.visit_ident(type_binding.ident); - visitor.visit_generic_args(type_binding.gen_args); - match type_binding.kind { - 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), +pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm<'v>) { + visitor.visit_id(arm.hir_id); + visitor.visit_pat(arm.pat); + if let Some(ref g) = arm.guard { + match g { + Guard::If(ref e) => visitor.visit_expr(e), + Guard::IfLet(ref l) => { + visitor.visit_let_expr(l); + } + } } + visitor.visit_expr(arm.body); } pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) { @@ -781,36 +660,186 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) { pub fn walk_pat_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v PatField<'v>) { visitor.visit_id(field.hir_id); visitor.visit_ident(field.ident); - visitor.visit_pat(&field.pat) + visitor.visit_pat(field.pat) } -pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v ForeignItem<'v>) { - visitor.visit_id(foreign_item.hir_id()); - visitor.visit_ident(foreign_item.ident); +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), + } +} - match foreign_item.kind { - ForeignItemKind::Fn(ref function_declaration, param_names, ref generics) => { - visitor.visit_generics(generics); - visitor.visit_fn_decl(function_declaration); - for ¶m_name in param_names { - visitor.visit_ident(param_name); - } +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_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) { + visitor.visit_id(expression.hir_id); + match expression.kind { + ExprKind::Box(ref subexpression) => visitor.visit_expr(subexpression), + ExprKind::Array(subexpressions) => { + walk_list!(visitor, visit_expr, subexpressions); } - ForeignItemKind::Static(ref typ, _) => visitor.visit_ty(typ), - ForeignItemKind::Type => (), + ExprKind::ConstBlock(ref anon_const) => visitor.visit_anon_const(anon_const), + ExprKind::Repeat(ref element, ref count) => { + visitor.visit_expr(element); + visitor.visit_array_length(count) + } + ExprKind::Struct(ref qpath, fields, ref optional_base) => { + visitor.visit_qpath(qpath, expression.hir_id, expression.span); + walk_list!(visitor, visit_expr_field, fields); + walk_list!(visitor, visit_expr, optional_base); + } + ExprKind::Tup(subexpressions) => { + walk_list!(visitor, visit_expr, subexpressions); + } + ExprKind::Call(ref callee_expression, arguments) => { + visitor.visit_expr(callee_expression); + walk_list!(visitor, visit_expr, arguments); + } + ExprKind::MethodCall(ref segment, receiver, arguments, _) => { + visitor.visit_path_segment(segment); + visitor.visit_expr(receiver); + walk_list!(visitor, visit_expr, arguments); + } + ExprKind::Binary(_, ref left_expression, ref right_expression) => { + visitor.visit_expr(left_expression); + visitor.visit_expr(right_expression) + } + ExprKind::AddrOf(_, _, ref subexpression) | ExprKind::Unary(_, ref subexpression) => { + visitor.visit_expr(subexpression) + } + ExprKind::Cast(ref subexpression, ref typ) | ExprKind::Type(ref subexpression, ref typ) => { + visitor.visit_expr(subexpression); + visitor.visit_ty(typ) + } + ExprKind::DropTemps(ref subexpression) => { + visitor.visit_expr(subexpression); + } + 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); + walk_list!(visitor, visit_expr, else_opt); + } + ExprKind::Loop(ref block, ref opt_label, _, _) => { + walk_list!(visitor, visit_label, opt_label); + visitor.visit_block(block); + } + ExprKind::Match(ref subexpression, arms, _) => { + visitor.visit_expr(subexpression); + walk_list!(visitor, visit_arm, arms); + } + ExprKind::Closure(&Closure { + def_id: _, + binder: _, + bound_generic_params, + fn_decl, + body, + capture_clause: _, + fn_decl_span: _, + fn_arg_span: _, + movability: _, + }) => { + walk_list!(visitor, visit_generic_param, bound_generic_params); + visitor.visit_fn(FnKind::Closure, fn_decl, body, expression.span, expression.hir_id) + } + ExprKind::Block(ref block, ref opt_label) => { + walk_list!(visitor, visit_label, opt_label); + visitor.visit_block(block); + } + ExprKind::Assign(ref lhs, ref rhs, _) => { + visitor.visit_expr(rhs); + visitor.visit_expr(lhs) + } + ExprKind::AssignOp(_, ref left_expression, ref right_expression) => { + visitor.visit_expr(right_expression); + visitor.visit_expr(left_expression); + } + ExprKind::Field(ref subexpression, ident) => { + visitor.visit_expr(subexpression); + visitor.visit_ident(ident); + } + ExprKind::Index(ref main_expression, ref index_expression) => { + visitor.visit_expr(main_expression); + visitor.visit_expr(index_expression) + } + ExprKind::Path(ref qpath) => { + visitor.visit_qpath(qpath, expression.hir_id, expression.span); + } + ExprKind::Break(ref destination, ref opt_expr) => { + walk_list!(visitor, visit_label, &destination.label); + walk_list!(visitor, visit_expr, opt_expr); + } + ExprKind::Continue(ref destination) => { + walk_list!(visitor, visit_label, &destination.label); + } + ExprKind::Ret(ref optional_expression) => { + walk_list!(visitor, visit_expr, optional_expression); + } + ExprKind::InlineAsm(ref asm) => { + visitor.visit_inline_asm(asm, expression.hir_id); + } + ExprKind::Yield(ref subexpression, _) => { + visitor.visit_expr(subexpression); + } + ExprKind::Lit(_) | ExprKind::Err => {} } } -pub fn walk_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v GenericBound<'v>) { - match *bound { - GenericBound::Trait(ref typ, _modifier) => { - visitor.visit_poly_trait_ref(typ); +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_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v ExprField<'v>) { + visitor.visit_id(field.hir_id); + visitor.visit_ident(field.ident); + visitor.visit_expr(field.expr) +} + +pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) { + visitor.visit_id(typ.hir_id); + + match typ.kind { + TyKind::Slice(ref ty) => visitor.visit_ty(ty), + TyKind::Ptr(ref mutable_type) => visitor.visit_ty(mutable_type.ty), + TyKind::Rptr(ref lifetime, ref mutable_type) => { + visitor.visit_lifetime(lifetime); + visitor.visit_ty(mutable_type.ty) } - GenericBound::LangItemTrait(_, _span, hir_id, args) => { - visitor.visit_id(hir_id); - visitor.visit_generic_args(args); + TyKind::Never => {} + TyKind::Tup(tuple_element_types) => { + walk_list!(visitor, visit_ty, tuple_element_types); } - GenericBound::Outlives(ref lifetime) => visitor.visit_lifetime(lifetime), + TyKind::BareFn(ref function_declaration) => { + walk_list!(visitor, visit_generic_param, function_declaration.generic_params); + visitor.visit_fn_decl(function_declaration.decl); + } + TyKind::Path(ref qpath) => { + visitor.visit_qpath(qpath, typ.hir_id, typ.span); + } + TyKind::OpaqueDef(item_id, lifetimes, _in_trait) => { + visitor.visit_nested_item(item_id); + walk_list!(visitor, visit_generic_arg, lifetimes); + } + TyKind::Array(ref ty, ref length) => { + visitor.visit_ty(ty); + visitor.visit_array_length(length) + } + TyKind::TraitObject(bounds, ref lifetime, _syntax) => { + for bound in bounds { + visitor.visit_poly_trait_ref(bound); + } + visitor.visit_lifetime(lifetime); + } + TyKind::Typeof(ref expression) => visitor.visit_anon_const(expression), + TyKind::Infer | TyKind::Err => {} } } @@ -875,25 +904,16 @@ pub fn walk_where_predicate<'v, V: Visitor<'v>>( } } -pub fn walk_fn_ret_ty<'v, V: Visitor<'v>>(visitor: &mut V, ret_ty: &'v FnRetTy<'v>) { - if let FnRetTy::Return(ref output_ty) = *ret_ty { - visitor.visit_ty(output_ty) - } -} - pub fn walk_fn_decl<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: &'v FnDecl<'v>) { for ty in function_declaration.inputs { visitor.visit_ty(ty) } - walk_fn_ret_ty(visitor, &function_declaration.output) + visitor.visit_fn_ret_ty(&function_declaration.output) } -pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<'v>) { - match function_kind { - FnKind::ItemFn(_, generics, ..) => { - visitor.visit_generics(generics); - } - FnKind::Closure | FnKind::Method(..) => {} +pub fn walk_fn_ret_ty<'v, V: Visitor<'v>>(visitor: &mut V, ret_ty: &'v FnRetTy<'v>) { + if let FnRetTy::Return(ref output_ty) = *ret_ty { + visitor.visit_ty(output_ty) } } @@ -910,13 +930,30 @@ pub fn walk_fn<'v, V: Visitor<'v>>( visitor.visit_nested_body(body_id) } +pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<'v>) { + match function_kind { + FnKind::ItemFn(_, generics, ..) => { + visitor.visit_generics(generics); + } + FnKind::Closure | FnKind::Method(..) => {} + } +} + +pub fn walk_use<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v UsePath<'v>, hir_id: HirId) { + visitor.visit_id(hir_id); + let UsePath { segments, ref res, span } = *path; + for &res in res { + visitor.visit_path(&Path { segments, res, span }, hir_id); + } +} + pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem<'v>) { // N.B., deliberately force a compilation error if/when new fields are added. let TraitItem { ident, generics, ref defaultness, ref kind, span, owner_id: _ } = *trait_item; let hir_id = trait_item.hir_id(); visitor.visit_ident(ident); - visitor.visit_generics(&generics); - visitor.visit_defaultness(&defaultness); + visitor.visit_generics(generics); + visitor.visit_defaultness(defaultness); match *kind { TraitItemKind::Const(ref ty, default) => { visitor.visit_id(hir_id); @@ -925,13 +962,13 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai } TraitItemKind::Fn(ref sig, TraitFn::Required(param_names)) => { visitor.visit_id(hir_id); - visitor.visit_fn_decl(&sig.decl); + visitor.visit_fn_decl(sig.decl); for ¶m_name in param_names { visitor.visit_ident(param_name); } } TraitItemKind::Fn(ref sig, TraitFn::Provided(body_id)) => { - visitor.visit_fn(FnKind::Method(ident, sig), &sig.decl, body_id, span, hir_id); + visitor.visit_fn(FnKind::Method(ident, sig), sig.decl, body_id, span, hir_id); } TraitItemKind::Type(bounds, ref default) => { visitor.visit_id(hir_id); @@ -973,7 +1010,7 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt ImplItemKind::Fn(ref sig, body_id) => { visitor.visit_fn( FnKind::Method(impl_item.ident, sig), - &sig.decl, + sig.decl, body_id, impl_item.span, impl_item.hir_id(), @@ -1004,6 +1041,29 @@ pub fn walk_impl_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, impl_item_ref: &' visitor.visit_associated_item_kind(kind); } +pub fn walk_trait_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_ref: &'v TraitRef<'v>) { + visitor.visit_id(trait_ref.hir_ref_id); + visitor.visit_path(trait_ref.path, trait_ref.hir_ref_id) +} + +pub fn walk_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v GenericBound<'v>) { + match *bound { + GenericBound::Trait(ref typ, _modifier) => { + visitor.visit_poly_trait_ref(typ); + } + GenericBound::LangItemTrait(_, _span, hir_id, args) => { + visitor.visit_id(hir_id); + visitor.visit_generic_args(args); + } + GenericBound::Outlives(ref lifetime) => visitor.visit_lifetime(lifetime), + } +} + +pub fn walk_poly_trait_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_ref: &'v PolyTraitRef<'v>) { + walk_list!(visitor, visit_generic_param, trait_ref.bound_generic_params); + visitor.visit_trait_ref(&trait_ref.trait_ref); +} + pub fn walk_struct_def<'v, V: Visitor<'v>>( visitor: &mut V, struct_definition: &'v VariantData<'v>, @@ -1015,176 +1075,94 @@ pub fn walk_struct_def<'v, V: Visitor<'v>>( pub fn walk_field_def<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v FieldDef<'v>) { visitor.visit_id(field.hir_id); visitor.visit_ident(field.ident); - visitor.visit_ty(&field.ty); + visitor.visit_ty(field.ty); } -pub fn walk_block<'v, V: Visitor<'v>>(visitor: &mut V, block: &'v Block<'v>) { - visitor.visit_id(block.hir_id); - walk_list!(visitor, visit_stmt, block.stmts); - walk_list!(visitor, visit_expr, &block.expr); +pub fn walk_enum_def<'v, V: Visitor<'v>>( + visitor: &mut V, + enum_definition: &'v EnumDef<'v>, + item_id: HirId, +) { + visitor.visit_id(item_id); + walk_list!(visitor, visit_variant, enum_definition.variants); } -pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt<'v>) { - visitor.visit_id(statement.hir_id); - match statement.kind { - StmtKind::Local(ref local) => visitor.visit_local(local), - StmtKind::Item(item) => visitor.visit_nested_item(item), - StmtKind::Expr(ref expression) | StmtKind::Semi(ref expression) => { - visitor.visit_expr(expression) - } - } +pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V, variant: &'v Variant<'v>) { + visitor.visit_ident(variant.ident); + visitor.visit_id(variant.hir_id); + visitor.visit_variant_data(&variant.data); + walk_list!(visitor, visit_anon_const, &variant.disr_expr); } -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_label<'v, V: Visitor<'v>>(visitor: &mut V, label: &'v Label) { + visitor.visit_ident(label.ident); } -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_inf<'v, V: Visitor<'v>>(visitor: &mut V, inf: &'v InferArg) { + visitor.visit_id(inf.hir_id); } -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_generic_arg<'v, V: Visitor<'v>>(visitor: &mut V, generic_arg: &'v GenericArg<'v>) { + match generic_arg { + GenericArg::Lifetime(lt) => visitor.visit_lifetime(lt), + GenericArg::Type(ty) => visitor.visit_ty(ty), + GenericArg::Const(ct) => visitor.visit_anon_const(&ct.value), + GenericArg::Infer(inf) => visitor.visit_infer(inf), + } } -pub fn walk_expr_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v ExprField<'v>) { - visitor.visit_id(field.hir_id); - visitor.visit_ident(field.ident); - visitor.visit_expr(&field.expr) +pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime) { + visitor.visit_id(lifetime.hir_id); + visitor.visit_ident(lifetime.ident); } -pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) { - visitor.visit_id(expression.hir_id); - match expression.kind { - ExprKind::Box(ref subexpression) => visitor.visit_expr(subexpression), - ExprKind::Array(subexpressions) => { - walk_list!(visitor, visit_expr, subexpressions); - } - ExprKind::ConstBlock(ref anon_const) => visitor.visit_anon_const(anon_const), - ExprKind::Repeat(ref element, ref count) => { - visitor.visit_expr(element); - visitor.visit_array_length(count) - } - ExprKind::Struct(ref qpath, fields, ref optional_base) => { - visitor.visit_qpath(qpath, expression.hir_id, expression.span); - walk_list!(visitor, visit_expr_field, fields); - walk_list!(visitor, visit_expr, optional_base); - } - ExprKind::Tup(subexpressions) => { - walk_list!(visitor, visit_expr, subexpressions); - } - ExprKind::Call(ref callee_expression, arguments) => { - visitor.visit_expr(callee_expression); - walk_list!(visitor, visit_expr, arguments); +pub fn walk_qpath<'v, V: Visitor<'v>>(visitor: &mut V, qpath: &'v QPath<'v>, id: HirId) { + match *qpath { + QPath::Resolved(ref maybe_qself, ref path) => { + walk_list!(visitor, visit_ty, maybe_qself); + visitor.visit_path(path, id) } - ExprKind::MethodCall(ref segment, receiver, arguments, _) => { + QPath::TypeRelative(ref qself, ref segment) => { + visitor.visit_ty(qself); visitor.visit_path_segment(segment); - visitor.visit_expr(receiver); - walk_list!(visitor, visit_expr, arguments); - } - ExprKind::Binary(_, ref left_expression, ref right_expression) => { - visitor.visit_expr(left_expression); - visitor.visit_expr(right_expression) - } - ExprKind::AddrOf(_, _, ref subexpression) | ExprKind::Unary(_, ref subexpression) => { - visitor.visit_expr(subexpression) - } - ExprKind::Cast(ref subexpression, ref typ) | ExprKind::Type(ref subexpression, ref typ) => { - visitor.visit_expr(subexpression); - visitor.visit_ty(typ) - } - ExprKind::DropTemps(ref subexpression) => { - visitor.visit_expr(subexpression); - } - 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); - walk_list!(visitor, visit_expr, else_opt); - } - ExprKind::Loop(ref block, ref opt_label, _, _) => { - walk_list!(visitor, visit_label, opt_label); - visitor.visit_block(block); - } - ExprKind::Match(ref subexpression, arms, _) => { - visitor.visit_expr(subexpression); - walk_list!(visitor, visit_arm, arms); - } - ExprKind::Closure(&Closure { - binder: _, - bound_generic_params, - fn_decl, - body, - capture_clause: _, - fn_decl_span: _, - movability: _, - }) => { - walk_list!(visitor, visit_generic_param, bound_generic_params); - visitor.visit_fn(FnKind::Closure, fn_decl, body, expression.span, expression.hir_id) - } - ExprKind::Block(ref block, ref opt_label) => { - walk_list!(visitor, visit_label, opt_label); - visitor.visit_block(block); - } - ExprKind::Assign(ref lhs, ref rhs, _) => { - visitor.visit_expr(rhs); - visitor.visit_expr(lhs) - } - ExprKind::AssignOp(_, ref left_expression, ref right_expression) => { - visitor.visit_expr(right_expression); - visitor.visit_expr(left_expression); - } - ExprKind::Field(ref subexpression, ident) => { - visitor.visit_expr(subexpression); - visitor.visit_ident(ident); - } - ExprKind::Index(ref main_expression, ref index_expression) => { - visitor.visit_expr(main_expression); - visitor.visit_expr(index_expression) - } - ExprKind::Path(ref qpath) => { - visitor.visit_qpath(qpath, expression.hir_id, expression.span); - } - ExprKind::Break(ref destination, ref opt_expr) => { - walk_list!(visitor, visit_label, &destination.label); - walk_list!(visitor, visit_expr, opt_expr); - } - ExprKind::Continue(ref destination) => { - walk_list!(visitor, visit_label, &destination.label); - } - ExprKind::Ret(ref optional_expression) => { - walk_list!(visitor, visit_expr, optional_expression); } - ExprKind::InlineAsm(ref asm) => { - visitor.visit_inline_asm(asm, expression.hir_id); - } - ExprKind::Yield(ref subexpression, _) => { - visitor.visit_expr(subexpression); - } - ExprKind::Lit(_) | ExprKind::Err => {} + QPath::LangItem(..) => {} } } -pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm<'v>) { - visitor.visit_id(arm.hir_id); - visitor.visit_pat(&arm.pat); - if let Some(ref g) = arm.guard { - match g { - Guard::If(ref e) => visitor.visit_expr(e), - Guard::IfLet(ref l) => { - visitor.visit_let_expr(l); - } - } +pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &Path<'v>) { + for segment in path.segments { + visitor.visit_path_segment(segment); + } +} + +pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V, segment: &'v PathSegment<'v>) { + visitor.visit_ident(segment.ident); + visitor.visit_id(segment.hir_id); + if let Some(ref args) = segment.args { + visitor.visit_generic_args(args); + } +} + +pub fn walk_generic_args<'v, V: Visitor<'v>>(visitor: &mut V, generic_args: &'v GenericArgs<'v>) { + walk_list!(visitor, visit_generic_arg, generic_args.args); + walk_list!(visitor, visit_assoc_type_binding, generic_args.bindings); +} + +pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>( + visitor: &mut V, + type_binding: &'v TypeBinding<'v>, +) { + visitor.visit_id(type_binding.hir_id); + visitor.visit_ident(type_binding.ident); + visitor.visit_generic_args(type_binding.gen_args); + match type_binding.kind { + 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), } - visitor.visit_expr(&arm.body); } pub fn walk_associated_item_kind<'v, V: Visitor<'v>>(_: &mut V, _: &'v AssocItemKind) { @@ -1198,3 +1176,27 @@ pub fn walk_defaultness<'v, V: Visitor<'v>>(_: &mut V, _: &'v Defaultness) { // the right thing to do, should content be added in the future, // would be to walk it. } + +pub fn walk_inline_asm<'v, V: Visitor<'v>>(visitor: &mut V, asm: &'v InlineAsm<'v>, id: HirId) { + for (op, op_sp) in asm.operands { + match op { + InlineAsmOperand::In { expr, .. } | InlineAsmOperand::InOut { expr, .. } => { + visitor.visit_expr(expr) + } + InlineAsmOperand::Out { expr, .. } => { + if let Some(expr) = expr { + visitor.visit_expr(expr); + } + } + InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => { + visitor.visit_expr(in_expr); + if let Some(out_expr) = out_expr { + visitor.visit_expr(out_expr); + } + } + InlineAsmOperand::Const { anon_const, .. } + | InlineAsmOperand::SymFn { anon_const, .. } => visitor.visit_anon_const(anon_const), + InlineAsmOperand::SymStatic { path, .. } => visitor.visit_qpath(path, id, *op_sp), + } + } +} diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index ca615a491..038509031 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -12,35 +12,56 @@ use crate::errors::LangItemError; use crate::{MethodKind, Target}; use rustc_ast as ast; -use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_macros::HashStable_Generic; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::Span; -use std::sync::LazyLock; - -pub enum LangItemGroup { - Op, - Fn, +/// All of the language items, defined or not. +/// Defined lang items can come from the current crate or its dependencies. +#[derive(HashStable_Generic, Debug)] +pub struct LanguageItems { + /// Mappings from lang items to their possibly found [`DefId`]s. + /// The index corresponds to the order in [`LangItem`]. + items: [Option<DefId>; std::mem::variant_count::<LangItem>()], + /// Lang items that were not found during collection. + pub missing: Vec<LangItem>, } -const NUM_GROUPS: usize = 2; +impl LanguageItems { + /// Construct an empty collection of lang items and no missing ones. + pub fn new() -> Self { + Self { items: [None; std::mem::variant_count::<LangItem>()], missing: Vec::new() } + } + + pub fn get(&self, item: LangItem) -> Option<DefId> { + self.items[item as usize] + } + + pub fn set(&mut self, item: LangItem, def_id: DefId) { + self.items[item as usize] = Some(def_id); + } + + /// Requires that a given `LangItem` was bound and returns the corresponding `DefId`. + /// If it wasn't bound, e.g. due to a missing `#[lang = "<it.name()>"]`, + /// returns an error encapsulating the `LangItem`. + pub fn require(&self, it: LangItem) -> Result<DefId, LangItemError> { + self.get(it).ok_or_else(|| LangItemError(it)) + } -macro_rules! expand_group { - () => { - None - }; - ($group:expr) => { - Some($group) - }; + pub fn iter<'a>(&'a self) -> impl Iterator<Item = (LangItem, DefId)> + 'a { + self.items + .iter() + .enumerate() + .filter_map(|(i, id)| id.map(|id| (LangItem::from_u32(i as u32).unwrap(), id))) + } } // The actual lang items defined come at the end of this file in one handy table. // So you probably just want to nip down to the end. macro_rules! language_item_table { ( - $( $(#[$attr:meta])* $variant:ident $($group:expr)?, $module:ident :: $name:ident, $method:ident, $target:expr, $generics:expr; )* + $( $(#[$attr:meta])* $variant:ident, $module:ident :: $name:ident, $method:ident, $target:expr, $generics:expr; )* ) => { enum_from_u32! { @@ -66,66 +87,36 @@ macro_rules! language_item_table { } } - /// The [group](LangItemGroup) that this lang item belongs to, - /// or `None` if it doesn't belong to a group. - pub fn group(self) -> Option<LangItemGroup> { - use LangItemGroup::*; - match self { - $( LangItem::$variant => expand_group!($($group)*), )* + /// Opposite of [`LangItem::name`] + pub fn from_name(name: Symbol) -> Option<Self> { + match name { + $( $module::$name => Some(LangItem::$variant), )* + _ => None, } } - pub fn required_generics(&self) -> GenericRequirement { + /// Returns the name of the `LangItem` enum variant. + // This method is used by Clippy for internal lints. + pub fn variant_name(self) -> &'static str { match self { - $( LangItem::$variant => $generics, )* + $( LangItem::$variant => stringify!($variant), )* } } - } - - /// All of the language items, defined or not. - /// Defined lang items can come from the current crate or its dependencies. - #[derive(HashStable_Generic, Debug)] - pub struct LanguageItems { - /// Mappings from lang items to their possibly found [`DefId`]s. - /// The index corresponds to the order in [`LangItem`]. - pub items: Vec<Option<DefId>>, - /// Lang items that were not found during collection. - pub missing: Vec<LangItem>, - /// Mapping from [`LangItemGroup`] discriminants to all - /// [`DefId`]s of lang items in that group. - pub groups: [Vec<DefId>; NUM_GROUPS], - } - impl LanguageItems { - /// Construct an empty collection of lang items and no missing ones. - pub fn new() -> Self { - fn init_none(_: LangItem) -> Option<DefId> { None } - const EMPTY: Vec<DefId> = Vec::new(); - - Self { - items: vec![$(init_none(LangItem::$variant)),*], - missing: Vec::new(), - groups: [EMPTY; NUM_GROUPS], + pub fn target(self) -> Target { + match self { + $( LangItem::$variant => $target, )* } } - /// Returns the mappings to the possibly found `DefId`s for each lang item. - pub fn items(&self) -> &[Option<DefId>] { - &*self.items - } - - /// Requires that a given `LangItem` was bound and returns the corresponding `DefId`. - /// If it wasn't bound, e.g. due to a missing `#[lang = "<it.name()>"]`, - /// returns an error encapsulating the `LangItem`. - pub fn require(&self, it: LangItem) -> Result<DefId, LangItemError> { - self.items[it as usize].ok_or_else(|| LangItemError(it)) - } - - /// Returns the [`DefId`]s of all lang items in a group. - pub fn group(&self, group: LangItemGroup) -> &[DefId] { - self.groups[group as usize].as_ref() + pub fn required_generics(&self) -> GenericRequirement { + match self { + $( LangItem::$variant => $generics, )* + } } + } + impl LanguageItems { $( #[doc = concat!("Returns the [`DefId`] of the `", stringify!($name), "` lang item if it is defined.")] pub fn $method(&self) -> Option<DefId> { @@ -133,15 +124,6 @@ macro_rules! language_item_table { } )* } - - /// A mapping from the name of the lang item to its order and the form it must be of. - pub static ITEM_REFS: LazyLock<FxIndexMap<Symbol, (usize, Target)>> = LazyLock::new(|| { - let mut item_refs = FxIndexMap::default(); - $( item_refs.insert($module::$name, (LangItem::$variant as usize, $target)); )* - item_refs - }); - -// End of the macro } } @@ -152,14 +134,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. +/// The `#[panic_handler]` attribute is also extracted out when found. pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> { attrs.iter().find_map(|attr| { Some(match attr { _ 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, }) }) @@ -196,30 +176,30 @@ language_item_table! { TransmuteOpts, sym::transmute_opts, transmute_opts, Target::Struct, GenericRequirement::Exact(0); TransmuteTrait, sym::transmute_trait, transmute_trait, Target::Trait, GenericRequirement::Exact(3); - Add(Op), sym::add, add_trait, Target::Trait, GenericRequirement::Exact(1); - Sub(Op), sym::sub, sub_trait, Target::Trait, GenericRequirement::Exact(1); - Mul(Op), sym::mul, mul_trait, Target::Trait, GenericRequirement::Exact(1); - Div(Op), sym::div, div_trait, Target::Trait, GenericRequirement::Exact(1); - Rem(Op), sym::rem, rem_trait, Target::Trait, GenericRequirement::Exact(1); - Neg(Op), sym::neg, neg_trait, Target::Trait, GenericRequirement::Exact(0); - Not(Op), sym::not, not_trait, Target::Trait, GenericRequirement::Exact(0); - BitXor(Op), sym::bitxor, bitxor_trait, Target::Trait, GenericRequirement::Exact(1); - BitAnd(Op), sym::bitand, bitand_trait, Target::Trait, GenericRequirement::Exact(1); - BitOr(Op), sym::bitor, bitor_trait, Target::Trait, GenericRequirement::Exact(1); - Shl(Op), sym::shl, shl_trait, Target::Trait, GenericRequirement::Exact(1); - Shr(Op), sym::shr, shr_trait, Target::Trait, GenericRequirement::Exact(1); - AddAssign(Op), sym::add_assign, add_assign_trait, Target::Trait, GenericRequirement::Exact(1); - SubAssign(Op), sym::sub_assign, sub_assign_trait, Target::Trait, GenericRequirement::Exact(1); - MulAssign(Op), sym::mul_assign, mul_assign_trait, Target::Trait, GenericRequirement::Exact(1); - DivAssign(Op), sym::div_assign, div_assign_trait, Target::Trait, GenericRequirement::Exact(1); - RemAssign(Op), sym::rem_assign, rem_assign_trait, Target::Trait, GenericRequirement::Exact(1); - BitXorAssign(Op), sym::bitxor_assign, bitxor_assign_trait, Target::Trait, GenericRequirement::Exact(1); - BitAndAssign(Op), sym::bitand_assign, bitand_assign_trait, Target::Trait, GenericRequirement::Exact(1); - BitOrAssign(Op), sym::bitor_assign, bitor_assign_trait, Target::Trait, GenericRequirement::Exact(1); - ShlAssign(Op), sym::shl_assign, shl_assign_trait, Target::Trait, GenericRequirement::Exact(1); - ShrAssign(Op), sym::shr_assign, shr_assign_trait, Target::Trait, GenericRequirement::Exact(1); - Index(Op), sym::index, index_trait, Target::Trait, GenericRequirement::Exact(1); - IndexMut(Op), sym::index_mut, index_mut_trait, Target::Trait, GenericRequirement::Exact(1); + Add, sym::add, add_trait, Target::Trait, GenericRequirement::Exact(1); + Sub, sym::sub, sub_trait, Target::Trait, GenericRequirement::Exact(1); + Mul, sym::mul, mul_trait, Target::Trait, GenericRequirement::Exact(1); + Div, sym::div, div_trait, Target::Trait, GenericRequirement::Exact(1); + Rem, sym::rem, rem_trait, Target::Trait, GenericRequirement::Exact(1); + Neg, sym::neg, neg_trait, Target::Trait, GenericRequirement::Exact(0); + Not, sym::not, not_trait, Target::Trait, GenericRequirement::Exact(0); + BitXor, sym::bitxor, bitxor_trait, Target::Trait, GenericRequirement::Exact(1); + BitAnd, sym::bitand, bitand_trait, Target::Trait, GenericRequirement::Exact(1); + BitOr, sym::bitor, bitor_trait, Target::Trait, GenericRequirement::Exact(1); + Shl, sym::shl, shl_trait, Target::Trait, GenericRequirement::Exact(1); + Shr, sym::shr, shr_trait, Target::Trait, GenericRequirement::Exact(1); + AddAssign, sym::add_assign, add_assign_trait, Target::Trait, GenericRequirement::Exact(1); + SubAssign, sym::sub_assign, sub_assign_trait, Target::Trait, GenericRequirement::Exact(1); + MulAssign, sym::mul_assign, mul_assign_trait, Target::Trait, GenericRequirement::Exact(1); + DivAssign, sym::div_assign, div_assign_trait, Target::Trait, GenericRequirement::Exact(1); + RemAssign, sym::rem_assign, rem_assign_trait, Target::Trait, GenericRequirement::Exact(1); + BitXorAssign, sym::bitxor_assign, bitxor_assign_trait, Target::Trait, GenericRequirement::Exact(1); + BitAndAssign, sym::bitand_assign, bitand_assign_trait, Target::Trait, GenericRequirement::Exact(1); + BitOrAssign, sym::bitor_assign, bitor_assign_trait, Target::Trait, GenericRequirement::Exact(1); + ShlAssign, sym::shl_assign, shl_assign_trait, Target::Trait, GenericRequirement::Exact(1); + ShrAssign, sym::shr_assign, shr_assign_trait, Target::Trait, GenericRequirement::Exact(1); + Index, sym::index, index_trait, Target::Trait, GenericRequirement::Exact(1); + IndexMut, sym::index_mut, index_mut_trait, Target::Trait, GenericRequirement::Exact(1); UnsafeCell, sym::unsafe_cell, unsafe_cell_type, Target::Struct, GenericRequirement::None; VaList, sym::va_list, va_list, Target::Struct, GenericRequirement::None; @@ -229,9 +209,9 @@ language_item_table! { DerefTarget, sym::deref_target, deref_target, Target::AssocTy, GenericRequirement::None; Receiver, sym::receiver, receiver_trait, Target::Trait, GenericRequirement::None; - Fn(Fn), kw::Fn, fn_trait, Target::Trait, GenericRequirement::Exact(1); - FnMut(Fn), sym::fn_mut, fn_mut_trait, Target::Trait, GenericRequirement::Exact(1); - FnOnce(Fn), sym::fn_once, fn_once_trait, Target::Trait, GenericRequirement::Exact(1); + Fn, kw::Fn, fn_trait, Target::Trait, GenericRequirement::Exact(1); + FnMut, sym::fn_mut, fn_mut_trait, Target::Trait, GenericRequirement::Exact(1); + FnOnce, sym::fn_once, fn_once_trait, Target::Trait, GenericRequirement::Exact(1); FnOnceOutput, sym::fn_once_output, fn_once_output, Target::AssocTy, GenericRequirement::None; @@ -241,8 +221,8 @@ language_item_table! { Unpin, sym::unpin, unpin_trait, Target::Trait, GenericRequirement::None; Pin, sym::pin, pin_type, Target::Struct, GenericRequirement::None; - PartialEq(Op), sym::eq, eq_trait, Target::Trait, GenericRequirement::Exact(1); - PartialOrd(Op), sym::partial_ord, partial_ord_trait, Target::Trait, GenericRequirement::Exact(1); + PartialEq, sym::eq, eq_trait, Target::Trait, GenericRequirement::Exact(1); + PartialOrd, sym::partial_ord, partial_ord_trait, Target::Trait, GenericRequirement::Exact(1); // A number of panic-related lang items. The `panic` item corresponds to divide-by-zero and // various panic cases with `match`. The `panic_bounds_check` item is for indexing arrays. @@ -266,7 +246,6 @@ language_item_table! { ExchangeMalloc, sym::exchange_malloc, exchange_malloc_fn, Target::Fn, GenericRequirement::None; BoxFree, sym::box_free, box_free_fn, Target::Fn, GenericRequirement::Minimum(1); DropInPlace, sym::drop_in_place, drop_in_place_fn, Target::Fn, GenericRequirement::Minimum(1); - Oom, sym::oom, oom, Target::Fn, GenericRequirement::None; AllocLayout, sym::alloc_layout, alloc_layout, Target::Struct, GenericRequirement::None; Start, sym::start, start_fn, Target::Fn, GenericRequirement::Exact(1); @@ -299,10 +278,16 @@ language_item_table! { TryTraitBranch, sym::branch, branch_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None; TryTraitFromYeet, sym::from_yeet, from_yeet_fn, Target::Fn, GenericRequirement::None; + PointerSized, sym::pointer_sized, pointer_sized, Target::Trait, GenericRequirement::Exact(0); + + Poll, sym::Poll, poll, Target::Enum, GenericRequirement::None; PollReady, sym::Ready, poll_ready_variant, Target::Variant, GenericRequirement::None; PollPending, sym::Pending, poll_pending_variant, Target::Variant, GenericRequirement::None; - FromGenerator, sym::from_generator, from_generator_fn, Target::Fn, GenericRequirement::None; + // FIXME(swatinem): the following lang items are used for async lowering and + // should become obsolete eventually. + ResumeTy, sym::ResumeTy, resume_ty, Target::Struct, GenericRequirement::None; + IdentityFuture, sym::identity_future, identity_future_fn, Target::Fn, GenericRequirement::None; GetContext, sym::get_context, get_context_fn, Target::Fn, GenericRequirement::None; FuturePoll, sym::poll, future_poll_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None; @@ -331,6 +316,8 @@ language_item_table! { Range, sym::Range, range_struct, Target::Struct, GenericRequirement::None; RangeToInclusive, sym::RangeToInclusive, range_to_inclusive_struct, Target::Struct, GenericRequirement::None; RangeTo, sym::RangeTo, range_to_struct, Target::Struct, GenericRequirement::None; + + String, sym::String, string, Target::Struct, GenericRequirement::None; } pub enum GenericRequirement { @@ -338,3 +325,34 @@ pub enum GenericRequirement { Minimum(usize), Exact(usize), } + +pub static FN_TRAITS: &'static [LangItem] = &[LangItem::Fn, LangItem::FnMut, LangItem::FnOnce]; + +pub static OPERATORS: &'static [LangItem] = &[ + LangItem::Add, + LangItem::Sub, + LangItem::Mul, + LangItem::Div, + LangItem::Rem, + LangItem::Neg, + LangItem::Not, + LangItem::BitXor, + LangItem::BitAnd, + LangItem::BitOr, + LangItem::Shl, + LangItem::Shr, + LangItem::AddAssign, + LangItem::SubAssign, + LangItem::MulAssign, + LangItem::DivAssign, + LangItem::RemAssign, + LangItem::BitXorAssign, + LangItem::BitAndAssign, + LangItem::BitOrAssign, + LangItem::ShlAssign, + LangItem::ShrAssign, + LangItem::Index, + LangItem::IndexMut, + LangItem::PartialEq, + LangItem::PartialOrd, +]; diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 1c4aa420c..98d967cc0 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -5,10 +5,11 @@ #![feature(associated_type_defaults)] #![feature(closure_track_caller)] #![feature(const_btree_len)] -#![feature(once_cell)] +#![feature(let_chains)] #![feature(min_specialization)] #![feature(never_type)] #![feature(rustc_attrs)] +#![feature(variant_count)] #![recursion_limit = "256"] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] diff --git a/compiler/rustc_hir/src/pat_util.rs b/compiler/rustc_hir/src/pat_util.rs index 0c1819bb0..6e2fbf96c 100644 --- a/compiler/rustc_hir/src/pat_util.rs +++ b/compiler/rustc_hir/src/pat_util.rs @@ -130,10 +130,7 @@ impl hir::Pat<'_> { pub fn contains_explicit_ref_binding(&self) -> Option<hir::Mutability> { let mut result = None; self.each_binding(|annotation, _, _, _| match annotation { - hir::BindingAnnotation::REF => match result { - None | Some(hir::Mutability::Not) => result = Some(hir::Mutability::Not), - _ => {} - }, + hir::BindingAnnotation::REF if result.is_none() => result = Some(hir::Mutability::Not), hir::BindingAnnotation::REF_MUT => result = Some(hir::Mutability::Mut), _ => {} }); diff --git a/compiler/rustc_hir/src/tests.rs b/compiler/rustc_hir/src/tests.rs index 4636d5152..d47911509 100644 --- a/compiler/rustc_hir/src/tests.rs +++ b/compiler/rustc_hir/src/tests.rs @@ -1,5 +1,7 @@ use crate::definitions::{DefKey, DefPathData, DisambiguatedDefPathData}; use rustc_span::def_id::{DefPathHash, StableCrateId}; +use rustc_span::edition::Edition; +use rustc_span::{create_session_if_not_set_then, Symbol}; #[test] fn def_path_hash_depends_on_crate_id() { @@ -11,26 +13,28 @@ fn def_path_hash_depends_on_crate_id() { // the crate by changing the crate disambiguator (e.g. via bumping the // crate's version number). - let id0 = StableCrateId::new("foo", false, vec!["1".to_string()]); - let id1 = StableCrateId::new("foo", false, vec!["2".to_string()]); + create_session_if_not_set_then(Edition::Edition2024, |_| { + let id0 = StableCrateId::new(Symbol::intern("foo"), false, vec!["1".to_string()]); + let id1 = StableCrateId::new(Symbol::intern("foo"), false, vec!["2".to_string()]); - let h0 = mk_test_hash(id0); - let h1 = mk_test_hash(id1); + let h0 = mk_test_hash(id0); + let h1 = mk_test_hash(id1); - assert_ne!(h0.stable_crate_id(), h1.stable_crate_id()); - assert_ne!(h0.local_hash(), h1.local_hash()); + assert_ne!(h0.stable_crate_id(), h1.stable_crate_id()); + assert_ne!(h0.local_hash(), h1.local_hash()); - fn mk_test_hash(stable_crate_id: StableCrateId) -> DefPathHash { - let parent_hash = DefPathHash::new(stable_crate_id, 0); + fn mk_test_hash(stable_crate_id: StableCrateId) -> DefPathHash { + let parent_hash = DefPathHash::new(stable_crate_id, 0); - let key = DefKey { - parent: None, - disambiguated_data: DisambiguatedDefPathData { - data: DefPathData::CrateRoot, - disambiguator: 0, - }, - }; + let key = DefKey { + parent: None, + disambiguated_data: DisambiguatedDefPathData { + data: DefPathData::CrateRoot, + disambiguator: 0, + }, + }; - key.compute_stable_hash(parent_hash) - } + key.compute_stable_hash(parent_hash) + } + }) } diff --git a/compiler/rustc_hir/src/weak_lang_items.rs b/compiler/rustc_hir/src/weak_lang_items.rs index da9c9c121..0cc50c6dd 100644 --- a/compiler/rustc_hir/src/weak_lang_items.rs +++ b/compiler/rustc_hir/src/weak_lang_items.rs @@ -1,53 +1,30 @@ //! Validity checking for weak lang items -use crate::def_id::DefId; -use crate::{lang_items, LangItem, LanguageItems}; +use crate::LangItem; -use rustc_ast as ast; -use rustc_data_structures::fx::FxIndexMap; use rustc_span::symbol::{sym, Symbol}; -use std::sync::LazyLock; - macro_rules! weak_lang_items { - ($($name:ident, $item:ident, $sym:ident;)*) => ( - -pub static WEAK_ITEMS_REFS: LazyLock<FxIndexMap<Symbol, LangItem>> = LazyLock::new(|| { - let mut map = FxIndexMap::default(); - $(map.insert(sym::$name, LangItem::$item);)* - map -}); - -pub static WEAK_ITEMS_SYMBOLS: LazyLock<FxIndexMap<LangItem, Symbol>> = LazyLock::new(|| { - let mut map = FxIndexMap::default(); - $(map.insert(LangItem::$item, sym::$sym);)* - map -}); - -pub fn link_name(attrs: &[ast::Attribute]) -> Option<Symbol> -{ - lang_items::extract(attrs).and_then(|(name, _)| { - $(if name == sym::$name { - Some(sym::$sym) - } else)* { - None + ($($item:ident, $sym:ident;)*) => { + pub static WEAK_LANG_ITEMS: &[LangItem] = &[$(LangItem::$item,)*]; + + impl LangItem { + pub fn is_weak(self) -> bool { + matches!(self, $(LangItem::$item)|*) + } + + pub fn link_name(self) -> Option<Symbol> { + match self { + $( LangItem::$item => Some(sym::$sym),)* + _ => None, + } + } } - }) -} - -impl LanguageItems { - pub fn is_weak_lang_item(&self, item_def_id: DefId) -> bool { - let did = Some(item_def_id); - - $(self.$name() == did)||* } } -) } - weak_lang_items! { - panic_impl, PanicImpl, rust_begin_unwind; - eh_personality, EhPersonality, rust_eh_personality; - eh_catch_typeinfo, EhCatchTypeinfo, rust_eh_catch_typeinfo; - oom, Oom, rust_oom; + PanicImpl, rust_begin_unwind; + EhPersonality, rust_eh_personality; + EhCatchTypeinfo, rust_eh_catch_typeinfo; } |