//! The Rust abstract syntax tree module. //! //! This module contains common structures forming the language AST. //! Two main entities in the module are [`Item`] (which represents an AST element with //! additional metadata), and [`ItemKind`] (which represents a concrete type and contains //! information specific to the type of the item). //! //! Other module items that worth mentioning: //! - [`Ty`] and [`TyKind`]: A parsed Rust type. //! - [`Expr`] and [`ExprKind`]: A parsed Rust expression. //! - [`Pat`] and [`PatKind`]: A parsed Rust pattern. Patterns are often dual to expressions. //! - [`Stmt`] and [`StmtKind`]: An executable action that does not return a value. //! - [`FnDecl`], [`FnHeader`] and [`Param`]: Metadata associated with a function declaration. //! - [`Generics`], [`GenericParam`], [`WhereClause`]: Metadata associated with generic parameters. //! - [`EnumDef`] and [`Variant`]: Enum declaration. //! - [`Lit`] and [`LitKind`]: Literal expressions. //! - [`MacroDef`], [`MacStmtStyle`], [`Mac`], [`MacDelimeter`]: Macro definition and invocation. //! - [`Attribute`]: Metadata associated with item. //! - [`UnOp`], [`UnOpKind`], [`BinOp`], [`BinOpKind`]: Unary and binary operators. pub use crate::util::parser::ExprPrecedence; pub use GenericArgs::*; pub use UnsafeSource::*; pub use rustc_span::symbol::{Ident, Symbol as Name}; use crate::ptr::P; use crate::token::{self, DelimToken}; use crate::tokenstream::{DelimSpan, TokenStream, TokenTree}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; use rustc_data_structures::thin_vec::ThinVec; use rustc_index::vec::Idx; use rustc_macros::HashStable_Generic; use rustc_serialize::{self, Decoder, Encoder}; use rustc_span::source_map::{respan, Spanned}; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::{Span, DUMMY_SP}; use std::fmt; use std::iter; #[cfg(test)] mod tests; /// A "Label" is an identifier of some point in sources, /// e.g. in the following code: /// /// ```rust /// 'outer: loop { /// break 'outer; /// } /// ``` /// /// `'outer` is a label. #[derive(Clone, RustcEncodable, RustcDecodable, Copy, HashStable_Generic)] pub struct Label { pub ident: Ident, } impl fmt::Debug for Label { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "label({:?})", self.ident) } } /// A "Lifetime" is an annotation of the scope in which variable /// can be used, e.g. `'a` in `&'a i32`. #[derive(Clone, RustcEncodable, RustcDecodable, Copy)] pub struct Lifetime { pub id: NodeId, pub ident: Ident, } impl fmt::Debug for Lifetime { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "lifetime({}: {})", self.id, self) } } impl fmt::Display for Lifetime { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.ident.name) } } /// A "Path" is essentially Rust's notion of a name. /// /// It's represented as a sequence of identifiers, /// along with a bunch of supporting information. /// /// E.g., `std::cmp::PartialEq`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Path { pub span: Span, /// The segments in the path: the things separated by `::`. /// Global paths begin with `kw::PathRoot`. pub segments: Vec, } impl PartialEq for Path { fn eq(&self, symbol: &Symbol) -> bool { self.segments.len() == 1 && { self.segments[0].ident.name == *symbol } } } impl HashStable for Path { fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { self.segments.len().hash_stable(hcx, hasher); for segment in &self.segments { segment.ident.name.hash_stable(hcx, hasher); } } } impl Path { // Convert a span and an identifier to the corresponding // one-segment path. pub fn from_ident(ident: Ident) -> Path { Path { segments: vec![PathSegment::from_ident(ident)], span: ident.span } } pub fn is_global(&self) -> bool { !self.segments.is_empty() && self.segments[0].ident.name == kw::PathRoot } } /// A segment of a path: an identifier, an optional lifetime, and a set of types. /// /// E.g., `std`, `String` or `Box`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct PathSegment { /// The identifier portion of this path segment. pub ident: Ident, pub id: NodeId, /// Type/lifetime parameters attached to this path. They come in /// two flavors: `Path` and `Path(A,B) -> C`. /// `None` means that no parameter list is supplied (`Path`), /// `Some` means that parameter list is supplied (`Path`) /// but it can be empty (`Path<>`). /// `P` is used as a size optimization for the common case with no parameters. pub args: Option>, } impl PathSegment { pub fn from_ident(ident: Ident) -> Self { PathSegment { ident, id: DUMMY_NODE_ID, args: None } } pub fn path_root(span: Span) -> Self { PathSegment::from_ident(Ident::new(kw::PathRoot, span)) } } /// The arguments of a path segment. /// /// E.g., `` as in `Foo` or `(A, B)` as in `Foo(A, B)`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum GenericArgs { /// The `<'a, A, B, C>` in `foo::bar::baz::<'a, A, B, C>`. AngleBracketed(AngleBracketedArgs), /// The `(A, B)` and `C` in `Foo(A, B) -> C`. Parenthesized(ParenthesizedArgs), } impl GenericArgs { pub fn is_parenthesized(&self) -> bool { match *self { Parenthesized(..) => true, _ => false, } } pub fn is_angle_bracketed(&self) -> bool { match *self { AngleBracketed(..) => true, _ => false, } } pub fn span(&self) -> Span { match *self { AngleBracketed(ref data) => data.span, Parenthesized(ref data) => data.span, } } } /// Concrete argument in the sequence of generic args. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum GenericArg { /// `'a` in `Foo<'a>` Lifetime(Lifetime), /// `Bar` in `Foo` Type(P), /// `1` in `Foo<1>` Const(AnonConst), } impl GenericArg { pub fn span(&self) -> Span { match self { GenericArg::Lifetime(lt) => lt.ident.span, GenericArg::Type(ty) => ty.span, GenericArg::Const(ct) => ct.value.span, } } } /// A path like `Foo<'a, T>`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug, Default)] pub struct AngleBracketedArgs { /// The overall span. pub span: Span, /// The arguments for this path segment. pub args: Vec, /// Constraints on associated types, if any. /// E.g., `Foo`. pub constraints: Vec, } impl Into>> for AngleBracketedArgs { fn into(self) -> Option> { Some(P(GenericArgs::AngleBracketed(self))) } } impl Into>> for ParenthesizedArgs { fn into(self) -> Option> { Some(P(GenericArgs::Parenthesized(self))) } } /// A path like `Foo(A, B) -> C`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct ParenthesizedArgs { /// Overall span pub span: Span, /// `(A, B)` pub inputs: Vec>, /// `C` pub output: FnRetTy, } impl ParenthesizedArgs { pub fn as_angle_bracketed_args(&self) -> AngleBracketedArgs { AngleBracketedArgs { span: self.span, args: self.inputs.iter().cloned().map(|input| GenericArg::Type(input)).collect(), constraints: vec![], } } } pub use crate::node_id::{NodeId, CRATE_NODE_ID, DUMMY_NODE_ID}; /// A modifier on a bound, e.g., `?Sized` or `?const Trait`. /// /// Negative bounds should also be handled here. #[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)] pub enum TraitBoundModifier { /// No modifiers None, /// `?Trait` Maybe, /// `?const Trait` MaybeConst, /// `?const ?Trait` // // This parses but will be rejected during AST validation. MaybeConstMaybe, } /// The AST represents all type param bounds as types. /// `typeck::collect::compute_bounds` matches these against /// the "special" built-in traits (see `middle::lang_items`) and /// detects `Copy`, `Send` and `Sync`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum GenericBound { Trait(PolyTraitRef, TraitBoundModifier), Outlives(Lifetime), } impl GenericBound { pub fn span(&self) -> Span { match self { &GenericBound::Trait(ref t, ..) => t.span, &GenericBound::Outlives(ref l) => l.ident.span, } } } pub type GenericBounds = Vec; /// Specifies the enforced ordering for generic parameters. In the future, /// if we wanted to relax this order, we could override `PartialEq` and /// `PartialOrd`, to allow the kinds to be unordered. #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)] pub enum ParamKindOrd { Lifetime, Type, Const, } impl fmt::Display for ParamKindOrd { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { ParamKindOrd::Lifetime => "lifetime".fmt(f), ParamKindOrd::Type => "type".fmt(f), ParamKindOrd::Const => "const".fmt(f), } } } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum GenericParamKind { /// A lifetime definition (e.g., `'a: 'b + 'c + 'd`). Lifetime, Type { default: Option>, }, Const { ty: P, }, } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct GenericParam { pub id: NodeId, pub ident: Ident, pub attrs: AttrVec, pub bounds: GenericBounds, pub is_placeholder: bool, pub kind: GenericParamKind, } /// Represents lifetime, type and const parameters attached to a declaration of /// a function, enum, trait, etc. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Generics { pub params: Vec, pub where_clause: WhereClause, pub span: Span, } impl Default for Generics { /// Creates an instance of `Generics`. fn default() -> Generics { Generics { params: Vec::new(), where_clause: WhereClause { predicates: Vec::new(), span: DUMMY_SP }, span: DUMMY_SP, } } } /// A where-clause in a definition. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct WhereClause { pub predicates: Vec, pub span: Span, } /// A single predicate in a where-clause. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum WherePredicate { /// A type binding (e.g., `for<'c> Foo: Send + Clone + 'c`). BoundPredicate(WhereBoundPredicate), /// A lifetime predicate (e.g., `'a: 'b + 'c`). RegionPredicate(WhereRegionPredicate), /// An equality predicate (unsupported). EqPredicate(WhereEqPredicate), } impl WherePredicate { pub fn span(&self) -> Span { match self { &WherePredicate::BoundPredicate(ref p) => p.span, &WherePredicate::RegionPredicate(ref p) => p.span, &WherePredicate::EqPredicate(ref p) => p.span, } } } /// A type bound. /// /// E.g., `for<'c> Foo: Send + Clone + 'c`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct WhereBoundPredicate { pub span: Span, /// Any generics from a `for` binding. pub bound_generic_params: Vec, /// The type being bounded. pub bounded_ty: P, /// Trait and lifetime bounds (`Clone + Send + 'static`). pub bounds: GenericBounds, } /// A lifetime predicate. /// /// E.g., `'a: 'b + 'c`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct WhereRegionPredicate { pub span: Span, pub lifetime: Lifetime, pub bounds: GenericBounds, } /// An equality predicate (unsupported). /// /// E.g., `T = int`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct WhereEqPredicate { pub id: NodeId, pub span: Span, pub lhs_ty: P, pub rhs_ty: P, } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Crate { pub module: Mod, pub attrs: Vec, pub span: Span, /// The order of items in the HIR is unrelated to the order of /// items in the AST. However, we generate proc macro harnesses /// based on the AST order, and later refer to these harnesses /// from the HIR. This field keeps track of the order in which /// we generated proc macros harnesses, so that we can map /// HIR proc macros items back to their harness items. pub proc_macros: Vec, } /// Possible values inside of compile-time attribute lists. /// /// E.g., the '..' in `#[name(..)]`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)] pub enum NestedMetaItem { /// A full MetaItem, for recursive meta items. MetaItem(MetaItem), /// A literal. /// /// E.g., `"foo"`, `64`, `true`. Literal(Lit), } /// A spanned compile-time attribute item. /// /// E.g., `#[test]`, `#[derive(..)]`, `#[rustfmt::skip]` or `#[feature = "foo"]`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)] pub struct MetaItem { pub path: Path, pub kind: MetaItemKind, pub span: Span, } /// A compile-time attribute item. /// /// E.g., `#[test]`, `#[derive(..)]` or `#[feature = "foo"]`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)] pub enum MetaItemKind { /// Word meta item. /// /// E.g., `test` as in `#[test]`. Word, /// List meta item. /// /// E.g., `derive(..)` as in `#[derive(..)]`. List(Vec), /// Name value meta item. /// /// E.g., `feature = "foo"` as in `#[feature = "foo"]`. NameValue(Lit), } /// A block (`{ .. }`). /// /// E.g., `{ .. }` as in `fn foo() { .. }`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Block { /// The statements in the block. pub stmts: Vec, pub id: NodeId, /// Distinguishes between `unsafe { ... }` and `{ ... }`. pub rules: BlockCheckMode, pub span: Span, } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Pat { pub id: NodeId, pub kind: PatKind, pub span: Span, } impl Pat { /// Attempt reparsing the pattern as a type. /// This is intended for use by diagnostics. pub fn to_ty(&self) -> Option> { let kind = match &self.kind { // In a type expression `_` is an inference variable. PatKind::Wild => TyKind::Infer, // An IDENT pattern with no binding mode would be valid as path to a type. E.g. `u32`. PatKind::Ident(BindingMode::ByValue(Mutability::Not), ident, None) => { TyKind::Path(None, Path::from_ident(*ident)) } PatKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()), PatKind::Mac(mac) => TyKind::Mac(mac.clone()), // `&mut? P` can be reinterpreted as `&mut? T` where `T` is `P` reparsed as a type. PatKind::Ref(pat, mutbl) => { pat.to_ty().map(|ty| TyKind::Rptr(None, MutTy { ty, mutbl: *mutbl }))? } // A slice/array pattern `[P]` can be reparsed as `[T]`, an unsized array, // when `P` can be reparsed as a type `T`. PatKind::Slice(pats) if pats.len() == 1 => pats[0].to_ty().map(TyKind::Slice)?, // A tuple pattern `(P0, .., Pn)` can be reparsed as `(T0, .., Tn)` // assuming `T0` to `Tn` are all syntactically valid as types. PatKind::Tuple(pats) => { let mut tys = Vec::with_capacity(pats.len()); // FIXME(#48994) - could just be collected into an Option for pat in pats { tys.push(pat.to_ty()?); } TyKind::Tup(tys) } _ => return None, }; Some(P(Ty { kind, id: self.id, span: self.span })) } /// Walk top-down and call `it` in each place where a pattern occurs /// starting with the root pattern `walk` is called on. If `it` returns /// false then we will descend no further but siblings will be processed. pub fn walk(&self, it: &mut impl FnMut(&Pat) -> bool) { if !it(self) { return; } match &self.kind { // Walk into the pattern associated with `Ident` (if any). PatKind::Ident(_, _, Some(p)) => p.walk(it), // Walk into each field of struct. PatKind::Struct(_, fields, _) => fields.iter().for_each(|field| field.pat.walk(it)), // Sequence of patterns. PatKind::TupleStruct(_, s) | PatKind::Tuple(s) | PatKind::Slice(s) | PatKind::Or(s) => { s.iter().for_each(|p| p.walk(it)) } // Trivial wrappers over inner patterns. PatKind::Box(s) | PatKind::Ref(s, _) | PatKind::Paren(s) => s.walk(it), // These patterns do not contain subpatterns, skip. PatKind::Wild | PatKind::Rest | PatKind::Lit(_) | PatKind::Range(..) | PatKind::Ident(..) | PatKind::Path(..) | PatKind::Mac(_) => {} } } /// Is this a `..` pattern? pub fn is_rest(&self) -> bool { match self.kind { PatKind::Rest => true, _ => false, } } } /// A single field in a struct pattern /// /// Patterns like the fields of Foo `{ x, ref y, ref mut z }` /// are treated the same as` x: x, y: ref y, z: ref mut z`, /// except is_shorthand is true #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct FieldPat { /// The identifier for the field pub ident: Ident, /// The pattern the field is destructured to pub pat: P, pub is_shorthand: bool, pub attrs: AttrVec, pub id: NodeId, pub span: Span, pub is_placeholder: bool, } #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)] pub enum BindingMode { ByRef(Mutability), ByValue(Mutability), } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum RangeEnd { Included(RangeSyntax), Excluded, } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum RangeSyntax { /// `...` DotDotDot, /// `..=` DotDotEq, } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum PatKind { /// Represents a wildcard pattern (`_`). Wild, /// A `PatKind::Ident` may either be a new bound variable (`ref mut binding @ OPT_SUBPATTERN`), /// or a unit struct/variant pattern, or a const pattern (in the last two cases the third /// field must be `None`). Disambiguation cannot be done with parser alone, so it happens /// during name resolution. Ident(BindingMode, Ident, Option>), /// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`). /// The `bool` is `true` in the presence of a `..`. Struct(Path, Vec, /* recovered */ bool), /// A tuple struct/variant pattern (`Variant(x, y, .., z)`). TupleStruct(Path, Vec>), /// An or-pattern `A | B | C`. /// Invariant: `pats.len() >= 2`. Or(Vec>), /// A possibly qualified path pattern. /// Unqualified path patterns `A::B::C` can legally refer to variants, structs, constants /// or associated constants. Qualified path patterns `::B::C`/`::B::C` can /// only legally refer to associated constants. Path(Option, Path), /// A tuple pattern (`(a, b)`). Tuple(Vec>), /// A `box` pattern. Box(P), /// A reference pattern (e.g., `&mut (a, b)`). Ref(P, Mutability), /// A literal. Lit(P), /// A range pattern (e.g., `1...2`, `1..=2` or `1..2`). Range(Option>, Option>, Spanned), /// A slice pattern `[a, b, c]`. Slice(Vec>), /// A rest pattern `..`. /// /// Syntactically it is valid anywhere. /// /// Semantically however, it only has meaning immediately inside: /// - a slice pattern: `[a, .., b]`, /// - a binding pattern immediately inside a slice pattern: `[a, r @ ..]`, /// - a tuple pattern: `(a, .., b)`, /// - a tuple struct/variant pattern: `$path(a, .., b)`. /// /// In all of these cases, an additional restriction applies, /// only one rest pattern may occur in the pattern sequences. Rest, /// Parentheses in patterns used for grouping (i.e., `(PAT)`). Paren(P), /// A macro pattern; pre-expansion. Mac(Mac), } #[derive( Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug, Copy, HashStable_Generic )] pub enum Mutability { Mut, Not, } impl Mutability { /// Returns `MutMutable` only if both `self` and `other` are mutable. pub fn and(self, other: Self) -> Self { match self { Mutability::Mut => other, Mutability::Not => Mutability::Not, } } pub fn invert(self) -> Self { match self { Mutability::Mut => Mutability::Not, Mutability::Not => Mutability::Mut, } } pub fn prefix_str(&self) -> &'static str { match self { Mutability::Mut => "mut ", Mutability::Not => "", } } } /// The kind of borrow in an `AddrOf` expression, /// e.g., `&place` or `&raw const place`. #[derive(Clone, Copy, PartialEq, Eq, Debug)] #[derive(RustcEncodable, RustcDecodable, HashStable_Generic)] pub enum BorrowKind { /// A normal borrow, `&$expr` or `&mut $expr`. /// The resulting type is either `&'a T` or `&'a mut T` /// where `T = typeof($expr)` and `'a` is some lifetime. Ref, /// A raw borrow, `&raw const $expr` or `&raw mut $expr`. /// The resulting type is either `*const T` or `*mut T` /// where `T = typeof($expr)`. Raw, } #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)] pub enum BinOpKind { /// The `+` operator (addition) Add, /// The `-` operator (subtraction) Sub, /// The `*` operator (multiplication) Mul, /// The `/` operator (division) Div, /// The `%` operator (modulus) Rem, /// The `&&` operator (logical and) And, /// The `||` operator (logical or) Or, /// The `^` operator (bitwise xor) BitXor, /// The `&` operator (bitwise and) BitAnd, /// The `|` operator (bitwise or) BitOr, /// The `<<` operator (shift left) Shl, /// The `>>` operator (shift right) Shr, /// The `==` operator (equality) Eq, /// The `<` operator (less than) Lt, /// The `<=` operator (less than or equal to) Le, /// The `!=` operator (not equal to) Ne, /// The `>=` operator (greater than or equal to) Ge, /// The `>` operator (greater than) Gt, } impl BinOpKind { pub fn to_string(&self) -> &'static str { use BinOpKind::*; match *self { Add => "+", Sub => "-", Mul => "*", Div => "/", Rem => "%", And => "&&", Or => "||", BitXor => "^", BitAnd => "&", BitOr => "|", Shl => "<<", Shr => ">>", Eq => "==", Lt => "<", Le => "<=", Ne => "!=", Ge => ">=", Gt => ">", } } pub fn lazy(&self) -> bool { match *self { BinOpKind::And | BinOpKind::Or => true, _ => false, } } pub fn is_shift(&self) -> bool { match *self { BinOpKind::Shl | BinOpKind::Shr => true, _ => false, } } pub fn is_comparison(&self) -> bool { use BinOpKind::*; // Note for developers: please keep this as is; // we want compilation to fail if another variant is added. match *self { Eq | Lt | Le | Ne | Gt | Ge => true, And | Or | Add | Sub | Mul | Div | Rem | BitXor | BitAnd | BitOr | Shl | Shr => false, } } /// Returns `true` if the binary operator takes its arguments by value pub fn is_by_value(&self) -> bool { !self.is_comparison() } } pub type BinOp = Spanned; /// Unary operator. /// /// Note that `&data` is not an operator, it's an `AddrOf` expression. #[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy)] pub enum UnOp { /// The `*` operator for dereferencing Deref, /// The `!` operator for logical inversion Not, /// The `-` operator for negation Neg, } impl UnOp { /// Returns `true` if the unary operator takes its argument by value pub fn is_by_value(u: UnOp) -> bool { match u { UnOp::Neg | UnOp::Not => true, _ => false, } } pub fn to_string(op: UnOp) -> &'static str { match op { UnOp::Deref => "*", UnOp::Not => "!", UnOp::Neg => "-", } } } /// A statement #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Stmt { pub id: NodeId, pub kind: StmtKind, pub span: Span, } impl Stmt { pub fn add_trailing_semicolon(mut self) -> Self { self.kind = match self.kind { StmtKind::Expr(expr) => StmtKind::Semi(expr), StmtKind::Mac(mac) => { StmtKind::Mac(mac.map(|(mac, _style, attrs)| (mac, MacStmtStyle::Semicolon, attrs))) } kind => kind, }; self } pub fn is_item(&self) -> bool { match self.kind { StmtKind::Item(_) => true, _ => false, } } pub fn is_expr(&self) -> bool { match self.kind { StmtKind::Expr(_) => true, _ => false, } } } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum StmtKind { /// A local (let) binding. Local(P), /// An item definition. Item(P), /// Expr without trailing semi-colon. Expr(P), /// Expr with a trailing semi-colon. Semi(P), /// Macro. Mac(P<(Mac, MacStmtStyle, AttrVec)>), } #[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug)] pub enum MacStmtStyle { /// The macro statement had a trailing semicolon (e.g., `foo! { ... };` /// `foo!(...);`, `foo![...];`). Semicolon, /// The macro statement had braces (e.g., `foo! { ... }`). Braces, /// The macro statement had parentheses or brackets and no semicolon (e.g., /// `foo!(...)`). All of these will end up being converted into macro /// expressions. NoBraces, } /// Local represents a `let` statement, e.g., `let : = ;`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Local { pub id: NodeId, pub pat: P, pub ty: Option>, /// Initializer expression to set the value, if any. pub init: Option>, pub span: Span, pub attrs: AttrVec, } /// An arm of a 'match'. /// /// E.g., `0..=10 => { println!("match!") }` as in /// /// ``` /// match 123 { /// 0..=10 => { println!("match!") }, /// _ => { println!("no match!") }, /// } /// ``` #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Arm { pub attrs: Vec, /// Match arm pattern, e.g. `10` in `match foo { 10 => {}, _ => {} }` pub pat: P, /// Match arm guard, e.g. `n > 10` in `match foo { n if n > 10 => {}, _ => {} }` pub guard: Option>, /// Match arm body. pub body: P, pub span: Span, pub id: NodeId, pub is_placeholder: bool, } /// Access of a named (e.g., `obj.foo`) or unnamed (e.g., `obj.0`) struct field. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Field { pub attrs: AttrVec, pub id: NodeId, pub span: Span, pub ident: Ident, pub expr: P, pub is_shorthand: bool, pub is_placeholder: bool, } #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)] pub enum BlockCheckMode { Default, Unsafe(UnsafeSource), } #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)] pub enum UnsafeSource { CompilerGenerated, UserProvided, } /// 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) /// or expressions (e.g., repeat counts), and also used to define /// explicit discriminant values for enum variants. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct AnonConst { pub id: NodeId, pub value: P, } /// An expression. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Expr { pub id: NodeId, pub kind: ExprKind, pub span: Span, pub attrs: AttrVec, } // `Expr` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(target_arch = "x86_64")] rustc_data_structures::static_assert_size!(Expr, 96); impl Expr { /// Returns `true` if this expression would be valid somewhere that expects a value; /// for example, an `if` condition. pub fn returns(&self) -> bool { if let ExprKind::Block(ref block, _) = self.kind { match block.stmts.last().map(|last_stmt| &last_stmt.kind) { // Implicit return Some(&StmtKind::Expr(_)) => true, Some(&StmtKind::Semi(ref expr)) => { if let ExprKind::Ret(_) = expr.kind { // Last statement is explicit return. true } else { false } } // This is a block that doesn't end in either an implicit or explicit return. _ => false, } } else { // This is not a block, it is a value. true } } pub fn to_bound(&self) -> Option { match &self.kind { ExprKind::Path(None, path) => Some(GenericBound::Trait( PolyTraitRef::new(Vec::new(), path.clone(), self.span), TraitBoundModifier::None, )), _ => None, } } /// Attempts to reparse as `Ty` (for diagnostic purposes). pub fn to_ty(&self) -> Option> { let kind = match &self.kind { // Trivial conversions. ExprKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()), ExprKind::Mac(mac) => TyKind::Mac(mac.clone()), ExprKind::Paren(expr) => expr.to_ty().map(TyKind::Paren)?, ExprKind::AddrOf(BorrowKind::Ref, mutbl, expr) => { expr.to_ty().map(|ty| TyKind::Rptr(None, MutTy { ty, mutbl: *mutbl }))? } ExprKind::Repeat(expr, expr_len) => { expr.to_ty().map(|ty| TyKind::Array(ty, expr_len.clone()))? } ExprKind::Array(exprs) if exprs.len() == 1 => exprs[0].to_ty().map(TyKind::Slice)?, ExprKind::Tup(exprs) => { let tys = exprs.iter().map(|expr| expr.to_ty()).collect::>>()?; TyKind::Tup(tys) } // If binary operator is `Add` and both `lhs` and `rhs` are trait bounds, // then type of result is trait object. // Othewise we don't assume the result type. ExprKind::Binary(binop, lhs, rhs) if binop.node == BinOpKind::Add => { if let (Some(lhs), Some(rhs)) = (lhs.to_bound(), rhs.to_bound()) { TyKind::TraitObject(vec![lhs, rhs], TraitObjectSyntax::None) } else { return None; } } // This expression doesn't look like a type syntactically. _ => return None, }; Some(P(Ty { kind, id: self.id, span: self.span })) } pub fn precedence(&self) -> ExprPrecedence { match self.kind { ExprKind::Box(_) => ExprPrecedence::Box, ExprKind::Array(_) => ExprPrecedence::Array, ExprKind::Call(..) => ExprPrecedence::Call, ExprKind::MethodCall(..) => ExprPrecedence::MethodCall, ExprKind::Tup(_) => ExprPrecedence::Tup, ExprKind::Binary(op, ..) => ExprPrecedence::Binary(op.node), ExprKind::Unary(..) => ExprPrecedence::Unary, ExprKind::Lit(_) => ExprPrecedence::Lit, ExprKind::Type(..) | ExprKind::Cast(..) => ExprPrecedence::Cast, ExprKind::Let(..) => ExprPrecedence::Let, ExprKind::If(..) => ExprPrecedence::If, ExprKind::While(..) => ExprPrecedence::While, ExprKind::ForLoop(..) => ExprPrecedence::ForLoop, ExprKind::Loop(..) => ExprPrecedence::Loop, ExprKind::Match(..) => ExprPrecedence::Match, ExprKind::Closure(..) => ExprPrecedence::Closure, ExprKind::Block(..) => ExprPrecedence::Block, ExprKind::TryBlock(..) => ExprPrecedence::TryBlock, ExprKind::Async(..) => ExprPrecedence::Async, ExprKind::Await(..) => ExprPrecedence::Await, ExprKind::Assign(..) => ExprPrecedence::Assign, ExprKind::AssignOp(..) => ExprPrecedence::AssignOp, ExprKind::Field(..) => ExprPrecedence::Field, ExprKind::Index(..) => ExprPrecedence::Index, ExprKind::Range(..) => ExprPrecedence::Range, ExprKind::Path(..) => ExprPrecedence::Path, ExprKind::AddrOf(..) => ExprPrecedence::AddrOf, ExprKind::Break(..) => ExprPrecedence::Break, ExprKind::Continue(..) => ExprPrecedence::Continue, ExprKind::Ret(..) => ExprPrecedence::Ret, ExprKind::InlineAsm(..) => ExprPrecedence::InlineAsm, ExprKind::Mac(..) => ExprPrecedence::Mac, ExprKind::Struct(..) => ExprPrecedence::Struct, ExprKind::Repeat(..) => ExprPrecedence::Repeat, ExprKind::Paren(..) => ExprPrecedence::Paren, ExprKind::Try(..) => ExprPrecedence::Try, ExprKind::Yield(..) => ExprPrecedence::Yield, ExprKind::Err => ExprPrecedence::Err, } } } /// Limit types of a range (inclusive or exclusive) #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)] pub enum RangeLimits { /// Inclusive at the beginning, exclusive at the end HalfOpen, /// Inclusive at the beginning and end Closed, } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum ExprKind { /// A `box x` expression. Box(P), /// An array (`[a, b, c, d]`) Array(Vec>), /// A function call /// /// The first field resolves to the function itself, /// and the second field is the list of arguments. /// This also represents calling the constructor of /// tuple-like ADTs such as tuple structs and enum variants. Call(P, Vec>), /// A method call (`x.foo::<'static, Bar, Baz>(a, b, c, d)`) /// /// The `PathSegment` represents the method name and its generic arguments /// (within the angle brackets). /// The first element of the vector of an `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::(a, b, c, d)` is represented as /// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d])`. MethodCall(PathSegment, Vec>), /// A tuple (e.g., `(a, b, c, d)`). Tup(Vec>), /// A binary operation (e.g., `a + b`, `a * b`). Binary(BinOp, P, P), /// A unary operation (e.g., `!x`, `*x`). Unary(UnOp, P), /// A literal (e.g., `1`, `"foo"`). Lit(Lit), /// A cast (e.g., `foo as f64`). Cast(P, P), /// A type ascription (e.g., `42: usize`). Type(P, P), /// A `let pat = expr` expression that is only semantically allowed in the condition /// of `if` / `while` expressions. (e.g., `if let 0 = x { .. }`). Let(P, P), /// An `if` block, with an optional `else` block. /// /// `if expr { block } else { expr }` If(P, P, Option>), /// A while loop, with an optional label. /// /// `'label: while expr { block }` While(P, P, Option` or /// `A: TraitA + TraitB` in `Foo`). #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct AssocTyConstraint { pub id: NodeId, pub ident: Ident, pub kind: AssocTyConstraintKind, pub span: Span, } /// The kinds of an `AssocTyConstraint`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum AssocTyConstraintKind { /// E.g., `A = Bar` in `Foo`. Equality { ty: P }, /// E.g. `A: TraitA + TraitB` in `Foo`. Bound { bounds: GenericBounds }, } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Ty { pub id: NodeId, pub kind: TyKind, pub span: Span, } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct BareFnTy { pub unsafety: Unsafe, pub ext: Extern, pub generic_params: Vec, pub decl: P, } /// The various kinds of type recognized by the compiler. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum TyKind { /// A variable-length slice (`[T]`). Slice(P), /// A fixed length array (`[T; n]`). Array(P, AnonConst), /// A raw pointer (`*const T` or `*mut T`). Ptr(MutTy), /// A reference (`&'a T` or `&'a mut T`). Rptr(Option, MutTy), /// A bare function (e.g., `fn(usize) -> bool`). BareFn(P), /// The never type (`!`). Never, /// A tuple (`(A, B, C, D,...)`). Tup(Vec>), /// A path (`module::module::...::Type`), optionally /// "qualified", e.g., ` as SomeTrait>::SomeType`. /// /// Type parameters are stored in the `Path` itself. Path(Option, Path), /// A trait object type `Bound1 + Bound2 + Bound3` /// where `Bound` is a trait or a lifetime. TraitObject(GenericBounds, TraitObjectSyntax), /// An `impl Bound1 + Bound2 + Bound3` type /// where `Bound` is a trait or a lifetime. /// /// The `NodeId` exists to prevent lowering from having to /// generate `NodeId`s on the fly, which would complicate /// the generation of opaque `type Foo = impl Trait` items significantly. ImplTrait(NodeId, GenericBounds), /// No-op; kept solely so that we can pretty-print faithfully. Paren(P), /// Unused for now. Typeof(AnonConst), /// This means the type should be inferred instead of it having been /// specified. This can appear anywhere in a type. Infer, /// Inferred type of a `self` or `&self` argument in a method. ImplicitSelf, /// A macro in the type position. Mac(Mac), /// Placeholder for a kind that has failed to be defined. Err, /// Placeholder for a `va_list`. CVarArgs, } impl TyKind { pub fn is_implicit_self(&self) -> bool { if let TyKind::ImplicitSelf = *self { true } else { false } } pub fn is_unit(&self) -> bool { if let TyKind::Tup(ref tys) = *self { tys.is_empty() } else { false } } /// HACK(type_alias_impl_trait, Centril): A temporary crutch used /// in lowering to avoid making larger changes there and beyond. pub fn opaque_top_hack(&self) -> Option<&GenericBounds> { match self { Self::ImplTrait(_, bounds) => Some(bounds), _ => None, } } } /// Syntax used to declare a trait object. #[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug)] pub enum TraitObjectSyntax { Dyn, None, } /// Inline assembly dialect. /// /// E.g., `"intel"` as in `asm!("mov eax, 2" : "={eax}"(result) : : : "intel")`. #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy, HashStable_Generic)] pub enum AsmDialect { Att, Intel, } /// Inline assembly. /// /// E.g., `"={eax}"(result)` as in `asm!("mov eax, 2" : "={eax}"(result) : : : "intel")`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct InlineAsmOutput { pub constraint: Symbol, pub expr: P, pub is_rw: bool, pub is_indirect: bool, } /// Inline assembly. /// /// E.g., `asm!("NOP");`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct InlineAsm { pub asm: Symbol, pub asm_str_style: StrStyle, pub outputs: Vec, pub inputs: Vec<(Symbol, P)>, pub clobbers: Vec, pub volatile: bool, pub alignstack: bool, pub dialect: AsmDialect, } /// A parameter in a function header. /// /// E.g., `bar: usize` as in `fn foo(bar: usize)`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Param { pub attrs: AttrVec, pub ty: P, pub pat: P, pub id: NodeId, pub span: Span, pub is_placeholder: bool, } /// Alternative representation for `Arg`s describing `self` parameter of methods. /// /// E.g., `&mut self` as in `fn foo(&mut self)`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum SelfKind { /// `self`, `mut self` Value(Mutability), /// `&'lt self`, `&'lt mut self` Region(Option, Mutability), /// `self: TYPE`, `mut self: TYPE` Explicit(P, Mutability), } pub type ExplicitSelf = Spanned; impl Param { /// Attempts to cast parameter to `ExplicitSelf`. pub fn to_self(&self) -> Option { if let PatKind::Ident(BindingMode::ByValue(mutbl), ident, _) = self.pat.kind { if ident.name == kw::SelfLower { return match self.ty.kind { TyKind::ImplicitSelf => Some(respan(self.pat.span, SelfKind::Value(mutbl))), TyKind::Rptr(lt, MutTy { ref ty, mutbl }) if ty.kind.is_implicit_self() => { Some(respan(self.pat.span, SelfKind::Region(lt, mutbl))) } _ => Some(respan( self.pat.span.to(self.ty.span), SelfKind::Explicit(self.ty.clone(), mutbl), )), }; } } None } /// Returns `true` if parameter is `self`. pub fn is_self(&self) -> bool { if let PatKind::Ident(_, ident, _) = self.pat.kind { ident.name == kw::SelfLower } else { false } } /// Builds a `Param` object from `ExplicitSelf`. pub fn from_self(attrs: AttrVec, eself: ExplicitSelf, eself_ident: Ident) -> Param { let span = eself.span.to(eself_ident.span); let infer_ty = P(Ty { id: DUMMY_NODE_ID, kind: TyKind::ImplicitSelf, span }); let param = |mutbl, ty| Param { attrs, pat: P(Pat { id: DUMMY_NODE_ID, kind: PatKind::Ident(BindingMode::ByValue(mutbl), eself_ident, None), span, }), span, ty, id: DUMMY_NODE_ID, is_placeholder: false, }; match eself.node { SelfKind::Explicit(ty, mutbl) => param(mutbl, ty), SelfKind::Value(mutbl) => param(mutbl, infer_ty), SelfKind::Region(lt, mutbl) => param( Mutability::Not, P(Ty { id: DUMMY_NODE_ID, kind: TyKind::Rptr(lt, MutTy { ty: infer_ty, mutbl }), span, }), ), } } } /// A signature (not the body) of a function declaration. /// /// E.g., `fn foo(bar: baz)`. /// /// Please note that it's different from `FnHeader` structure /// which contains metadata about function safety, asyncness, constness and ABI. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct FnDecl { pub inputs: Vec, pub output: FnRetTy, } impl FnDecl { pub fn get_self(&self) -> Option { self.inputs.get(0).and_then(Param::to_self) } pub fn has_self(&self) -> bool { self.inputs.get(0).map_or(false, Param::is_self) } pub fn c_variadic(&self) -> bool { self.inputs.last().map_or(false, |arg| match arg.ty.kind { TyKind::CVarArgs => true, _ => false, }) } } /// Is the trait definition an auto trait? #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)] pub enum IsAuto { Yes, No, } #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug)] #[derive(HashStable_Generic)] pub enum Unsafe { Yes(Span), No, } #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)] pub enum Async { Yes { span: Span, closure_id: NodeId, return_impl_trait_id: NodeId }, No, } impl Async { pub fn is_async(self) -> bool { if let Async::Yes { .. } = self { true } else { false } } /// In ths case this is an `async` return, the `NodeId` for the generated `impl Trait` item. pub fn opt_return_id(self) -> Option { match self { Async::Yes { return_impl_trait_id, .. } => Some(return_impl_trait_id), Async::No => None, } } } #[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)] #[derive(HashStable_Generic)] pub enum Const { Yes(Span), No, } /// Item defaultness. /// For details see the [RFC #2532](https://github.com/rust-lang/rfcs/pull/2532). #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)] pub enum Defaultness { Default(Span), Final, } #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable_Generic)] pub enum ImplPolarity { /// `impl Trait for Type` Positive, /// `impl !Trait for Type` Negative, } impl fmt::Debug for ImplPolarity { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { ImplPolarity::Positive => "positive".fmt(f), ImplPolarity::Negative => "negative".fmt(f), } } } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum FnRetTy { /// Returns type is not specified. /// /// Functions default to `()` and closures default to inference. /// Span points to where return type would be inserted. Default(Span), /// Everything else. Ty(P), } impl FnRetTy { pub fn span(&self) -> Span { match *self { FnRetTy::Default(span) => span, FnRetTy::Ty(ref ty) => ty.span, } } } /// Module declaration. /// /// E.g., `mod foo;` or `mod foo { .. }`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Mod { /// A span from the first token past `{` to the last token until `}`. /// For `mod foo;`, the inner span ranges from the first token /// to the last token in the external file. pub inner: Span, pub items: Vec>, /// `true` for `mod foo { .. }`; `false` for `mod foo;`. pub inline: bool, } /// Foreign module declaration. /// /// E.g., `extern { .. }` or `extern C { .. }`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct ForeignMod { pub abi: Option, pub items: Vec>, } /// Global inline assembly. /// /// Also known as "module-level assembly" or "file-scoped assembly". #[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy)] pub struct GlobalAsm { pub asm: Symbol, } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct EnumDef { pub variants: Vec, } /// Enum variant. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Variant { /// Attributes of the variant. pub attrs: Vec, /// Id of the variant (not the constructor, see `VariantData::ctor_id()`). pub id: NodeId, /// Span pub span: Span, /// The visibility of the variant. Syntactically accepted but not semantically. pub vis: Visibility, /// Name of the variant. pub ident: Ident, /// Fields and constructor id of the variant. pub data: VariantData, /// Explicit discriminant, e.g., `Foo = 1`. pub disr_expr: Option, /// Is a macro placeholder pub is_placeholder: bool, } /// Part of `use` item to the right of its prefix. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum UseTreeKind { /// `use prefix` or `use prefix as rename` /// /// The extra `NodeId`s are for HIR lowering, when additional statements are created for each /// namespace. Simple(Option, NodeId, NodeId), /// `use prefix::{...}` Nested(Vec<(UseTree, NodeId)>), /// `use prefix::*` Glob, } /// A tree of paths sharing common prefixes. /// Used in `use` items both at top-level and inside of braces in import groups. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct UseTree { pub prefix: Path, pub kind: UseTreeKind, pub span: Span, } impl UseTree { pub fn ident(&self) -> Ident { match self.kind { UseTreeKind::Simple(Some(rename), ..) => rename, UseTreeKind::Simple(None, ..) => { self.prefix.segments.last().expect("empty prefix in a simple import").ident } _ => panic!("`UseTree::ident` can only be used on a simple import"), } } } /// Distinguishes between `Attribute`s that decorate items and Attributes that /// are contained as statements within items. These two cases need to be /// distinguished for pretty-printing. #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy, HashStable_Generic)] pub enum AttrStyle { Outer, Inner, } #[derive(Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord, Copy)] pub struct AttrId(pub usize); impl Idx for AttrId { fn new(idx: usize) -> Self { AttrId(idx) } fn index(self) -> usize { self.0 } } impl rustc_serialize::Encodable for AttrId { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_unit() } } impl rustc_serialize::Decodable for AttrId { fn decode(d: &mut D) -> Result { d.read_nil().map(|_| crate::attr::mk_attr_id()) } } #[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)] pub struct AttrItem { pub path: Path, pub args: MacArgs, } /// A list of attributes. pub type AttrVec = ThinVec; /// Metadata associated with an item. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Attribute { pub kind: AttrKind, pub id: AttrId, /// Denotes if the attribute decorates the following construct (outer) /// or the construct this attribute is contained within (inner). pub style: AttrStyle, pub span: Span, } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum AttrKind { /// A normal attribute. Normal(AttrItem), /// A doc comment (e.g. `/// ...`, `//! ...`, `/** ... */`, `/*! ... */`). /// Doc attributes (e.g. `#[doc="..."]`) are represented with the `Normal` /// variant (which is much less compact and thus more expensive). DocComment(Symbol), } /// `TraitRef`s appear in impls. /// /// Resolution maps each `TraitRef`'s `ref_id` to its defining trait; that's all /// that the `ref_id` is for. The `impl_id` maps to the "self type" of this impl. /// If this impl is an `ItemKind::Impl`, the `impl_id` is redundant (it could be the /// same as the impl's `NodeId`). #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct TraitRef { pub path: Path, pub ref_id: NodeId, } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct PolyTraitRef { /// The `'a` in `<'a> Foo<&'a T>`. pub bound_generic_params: Vec, /// The `Foo<&'a T>` in `<'a> Foo<&'a T>`. pub trait_ref: TraitRef, pub span: Span, } impl PolyTraitRef { pub fn new(generic_params: Vec, path: Path, span: Span) -> Self { PolyTraitRef { bound_generic_params: generic_params, trait_ref: TraitRef { path, ref_id: DUMMY_NODE_ID }, span, } } } #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)] pub enum CrateSugar { /// Source is `pub(crate)`. PubCrate, /// Source is (just) `crate`. JustCrate, } pub type Visibility = Spanned; #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum VisibilityKind { Public, Crate(CrateSugar), Restricted { path: P, id: NodeId }, Inherited, } impl VisibilityKind { pub fn is_pub(&self) -> bool { if let VisibilityKind::Public = *self { true } else { false } } } /// Field of a struct. /// /// E.g., `bar: usize` as in `struct Foo { bar: usize }`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct StructField { pub attrs: Vec, pub id: NodeId, pub span: Span, pub vis: Visibility, pub ident: Option, pub ty: P, pub is_placeholder: bool, } /// Fields and constructor ids of enum variants and structs. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum VariantData { /// Struct variant. /// /// E.g., `Bar { .. }` as in `enum Foo { Bar { .. } }`. Struct(Vec, bool), /// Tuple variant. /// /// E.g., `Bar(..)` as in `enum Foo { Bar(..) }`. Tuple(Vec, NodeId), /// Unit variant. /// /// E.g., `Bar = ..` as in `enum Foo { Bar = .. }`. Unit(NodeId), } impl VariantData { /// Return the fields of this variant. pub fn fields(&self) -> &[StructField] { match *self { VariantData::Struct(ref fields, ..) | VariantData::Tuple(ref fields, _) => fields, _ => &[], } } /// Return the `NodeId` of this variant's constructor, if it has one. pub fn ctor_id(&self) -> Option { match *self { VariantData::Struct(..) => None, VariantData::Tuple(_, id) | VariantData::Unit(id) => Some(id), } } } /// An item definition. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Item { pub attrs: Vec, pub id: NodeId, pub span: Span, pub vis: Visibility, /// The name of the item. /// It might be a dummy name in case of anonymous items. pub ident: Ident, pub kind: K, /// Original tokens this item was parsed from. This isn't necessarily /// available for all items, although over time more and more items should /// have this be `Some`. Right now this is primarily used for procedural /// macros, notably custom attributes. /// /// Note that the tokens here do not include the outer attributes, but will /// include inner attributes. pub tokens: Option, } impl Item { /// Return the span that encompasses the attributes. pub fn span_with_attributes(&self) -> Span { self.attrs.iter().fold(self.span, |acc, attr| acc.to(attr.span)) } } /// `extern` qualifier on a function item or function type. #[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)] pub enum Extern { None, Implicit, Explicit(StrLit), } impl Extern { pub fn from_abi(abi: Option) -> Extern { abi.map_or(Extern::Implicit, Extern::Explicit) } } /// A function header. /// /// All the information between the visibility and the name of the function is /// included in this struct (e.g., `async unsafe fn` or `const extern "C" fn`). #[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)] pub struct FnHeader { pub unsafety: Unsafe, pub asyncness: Async, pub constness: Const, pub ext: Extern, } impl FnHeader { /// Does this function header have any qualifiers or is it empty? pub fn has_qualifiers(&self) -> bool { let Self { unsafety, asyncness, constness, ext } = self; matches!(unsafety, Unsafe::Yes(_)) || asyncness.is_async() || matches!(constness, Const::Yes(_)) || !matches!(ext, Extern::None) } } impl Default for FnHeader { fn default() -> FnHeader { FnHeader { unsafety: Unsafe::No, asyncness: Async::No, constness: Const::No, ext: Extern::None, } } } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum ItemKind { /// An `extern crate` item, with the optional *original* crate name if the crate was renamed. /// /// E.g., `extern crate foo` or `extern crate foo_bar as foo`. ExternCrate(Option), /// A use declaration item (`use`). /// /// E.g., `use foo;`, `use foo::bar;` or `use foo::bar as FooBar;`. Use(P), /// A static item (`static`). /// /// E.g., `static FOO: i32 = 42;` or `static FOO: &'static str = "bar";`. Static(P, Mutability, Option>), /// A constant item (`const`). /// /// E.g., `const FOO: i32 = 42;`. Const(Defaultness, P, Option>), /// A function declaration (`fn`). /// /// E.g., `fn foo(bar: usize) -> usize { .. }`. Fn(Defaultness, FnSig, Generics, Option>), /// A module declaration (`mod`). /// /// E.g., `mod foo;` or `mod foo { .. }`. Mod(Mod), /// An external module (`extern`). /// /// E.g., `extern {}` or `extern "C" {}`. ForeignMod(ForeignMod), /// Module-level inline assembly (from `global_asm!()`). GlobalAsm(P), /// A type alias (`type`). /// /// E.g., `type Foo = Bar;`. TyAlias(Defaultness, Generics, GenericBounds, Option>), /// An enum definition (`enum`). /// /// E.g., `enum Foo { C, D }`. Enum(EnumDef, Generics), /// A struct definition (`struct`). /// /// E.g., `struct Foo { x: A }`. Struct(VariantData, Generics), /// A union definition (`union`). /// /// E.g., `union Foo { x: A, y: B }`. Union(VariantData, Generics), /// A trait declaration (`trait`). /// /// E.g., `trait Foo { .. }`, `trait Foo { .. }` or `auto trait Foo {}`. Trait(IsAuto, Unsafe, Generics, GenericBounds, Vec>), /// Trait alias /// /// E.g., `trait Foo = Bar + Quux;`. TraitAlias(Generics, GenericBounds), /// An implementation. /// /// E.g., `impl Foo { .. }` or `impl Trait for Foo { .. }`. Impl { unsafety: Unsafe, polarity: ImplPolarity, defaultness: Defaultness, constness: Const, generics: Generics, /// The trait being implemented, if any. of_trait: Option, self_ty: P, items: Vec>, }, /// A macro invocation. /// /// E.g., `foo!(..)`. Mac(Mac), /// A macro definition. MacroDef(MacroDef), } impl ItemKind { pub fn article(&self) -> &str { use ItemKind::*; match self { Use(..) | Static(..) | Const(..) | Fn(..) | Mod(..) | GlobalAsm(..) | TyAlias(..) | Struct(..) | Union(..) | Trait(..) | TraitAlias(..) | MacroDef(..) => "a", ExternCrate(..) | ForeignMod(..) | Mac(..) | Enum(..) | Impl { .. } => "an", } } pub fn descr(&self) -> &str { match self { ItemKind::ExternCrate(..) => "extern crate", ItemKind::Use(..) => "`use` import", ItemKind::Static(..) => "static item", ItemKind::Const(..) => "constant item", ItemKind::Fn(..) => "function", ItemKind::Mod(..) => "module", ItemKind::ForeignMod(..) => "extern block", ItemKind::GlobalAsm(..) => "global asm item", ItemKind::TyAlias(..) => "type alias", ItemKind::Enum(..) => "enum", ItemKind::Struct(..) => "struct", ItemKind::Union(..) => "union", ItemKind::Trait(..) => "trait", ItemKind::TraitAlias(..) => "trait alias", ItemKind::Mac(..) => "item macro invocation", ItemKind::MacroDef(..) => "macro definition", ItemKind::Impl { .. } => "implementation", } } pub fn generics(&self) -> Option<&Generics> { match self { Self::Fn(_, _, generics, _) | Self::TyAlias(_, generics, ..) | Self::Enum(_, generics) | Self::Struct(_, generics) | Self::Union(_, generics) | Self::Trait(_, _, generics, ..) | Self::TraitAlias(generics, _) | Self::Impl { generics, .. } => Some(generics), _ => None, } } } // FIXME(Centril): These definitions should be unmerged; // see https://github.com/rust-lang/rust/pull/69194#discussion_r379899975 pub type ForeignItem = Item; pub type ForeignItemKind = AssocItemKind; /// Represents associated items. /// These include items in `impl` and `trait` definitions. pub type AssocItem = Item; /// Represents non-free item kinds. /// /// The term "provided" in the variants below refers to the item having a default /// definition / body. Meanwhile, a "required" item lacks a definition / body. /// In an implementation, all items must be provided. /// The `Option`s below denote the bodies, where `Some(_)` /// means "provided" and conversely `None` means "required". #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum AssocItemKind { /// A constant, `const $ident: $ty $def?;` where `def ::= "=" $expr? ;`. /// If `def` is parsed, then the constant is provided, and otherwise required. Const(Defaultness, P, Option>), /// A static item (`static FOO: u8`). Static(P, Mutability, Option>), /// A function. Fn(Defaultness, FnSig, Generics, Option>), /// A type. TyAlias(Defaultness, Generics, GenericBounds, Option>), /// A macro expanding to items. Macro(Mac), } impl AssocItemKind { pub fn defaultness(&self) -> Defaultness { match *self { Self::Const(def, ..) | Self::Fn(def, ..) | Self::TyAlias(def, ..) => def, Self::Macro(..) | Self::Static(..) => Defaultness::Final, } } }