//! - [`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.
+//! - [`MetaItemLit`] and [`LitKind`]: Literal expressions.
//! - [`MacroDef`], [`MacStmtStyle`], [`MacCall`], [`MacDelimiter`]: Macro definition and invocation.
//! - [`Attribute`]: Metadata associated with item.
//! - [`UnOp`], [`BinOp`], and [`BinOpKind`]: Unary and binary operators.
use rustc_span::source_map::{respan, Spanned};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
-use std::convert::TryFrom;
use std::fmt;
use std::mem;
use thin_vec::{thin_vec, ThinVec};
}
impl Path {
- // Convert a span and an identifier to the corresponding
- // one-segment path.
+ /// Convert a span and an identifier to the corresponding
+ /// one-segment path.
pub fn from_ident(ident: Ident) -> Path {
Path { segments: thin_vec![PathSegment::from_ident(ident)], span: ident.span, tokens: None }
}
pub is_placeholder: bool,
}
-/// Possible values inside of compile-time attribute lists.
-///
-/// E.g., the '..' in `#[name(..)]`.
-#[derive(Clone, Encodable, Decodable, 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.
+/// A semantic representation of a meta item. A meta item is a slightly
+/// restricted form of an attribute -- it can only contain expressions in
+/// certain leaf positions, rather than arbitrary token streams -- that is used
+/// for most built-in attributes.
///
/// E.g., `#[test]`, `#[derive(..)]`, `#[rustfmt::skip]` or `#[feature = "foo"]`.
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
pub span: Span,
}
-/// A compile-time attribute item.
-///
-/// E.g., `#[test]`, `#[derive(..)]` or `#[feature = "foo"]`.
+/// The meta item kind, containing the data after the initial path.
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum MetaItemKind {
/// Word meta item.
///
- /// E.g., `test` as in `#[test]`.
+ /// E.g., `#[test]`, which lacks any arguments after `test`.
Word,
+
/// List meta item.
///
- /// E.g., `derive(..)` as in `#[derive(..)]`.
+ /// E.g., `#[derive(..)]`, where the field represents the `..`.
List(Vec<NestedMetaItem>),
+
/// Name value meta item.
///
- /// E.g., `feature = "foo"` as in `#[feature = "foo"]`.
- NameValue(Lit),
+ /// E.g., `#[feature = "foo"]`, where the field represents the `"foo"`.
+ NameValue(MetaItemLit),
+}
+
+/// Values inside meta item lists.
+///
+/// E.g., each of `Clone`, `Copy` in `#[derive(Clone, Copy)]`.
+#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
+pub enum NestedMetaItem {
+ /// A full MetaItem, for recursive meta items.
+ MetaItem(MetaItem),
+
+ /// A literal.
+ ///
+ /// E.g., `"foo"`, `64`, `true`.
+ Lit(MetaItemLit),
}
/// A block (`{ .. }`).
PatKind::MacCall(mac) => TyKind::MacCall(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 }))?
+ pat.to_ty().map(|ty| TyKind::Ref(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`.
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)]
#[derive(HashStable_Generic, Encodable, Decodable)]
pub enum Mutability {
- Mut,
+ // N.B. Order is deliberate, so that Not < Mut
Not,
+ Mut,
}
impl Mutability {
}
}
- pub fn prefix_str(&self) -> &'static str {
+ /// Returns `""` (empty string) or `"mut "` depending on the mutability.
+ pub fn prefix_str(self) -> &'static str {
match self {
Mutability::Mut => "mut ",
Mutability::Not => "",
}
}
+
+ /// Returns `"&"` or `"&mut "` depending on the mutability.
+ pub fn ref_prefix_str(self) -> &'static str {
+ match self {
+ Mutability::Not => "&",
+ Mutability::Mut => "&mut ",
+ }
+ }
+
+ /// Returns `""` (empty string) or `"mutably "` depending on the mutability.
+ pub fn mutably_str(self) -> &'static str {
+ match self {
+ Mutability::Not => "",
+ Mutability::Mut => "mutably ",
+ }
+ }
+
+ /// Return `true` if self is mutable
+ pub fn is_mut(self) -> bool {
+ matches!(self, Self::Mut)
+ }
+
+ /// Return `true` if self is **not** mutable
+ pub fn is_not(self) -> bool {
+ matches!(self, Self::Not)
+ }
}
/// The kind of borrow in an `AddrOf` expression,
pub fn peel_parens(&self) -> &Expr {
let mut expr = self;
while let ExprKind::Paren(inner) = &expr.kind {
- expr = &inner;
+ expr = inner;
}
expr
}
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 }))?
+ expr.to_ty().map(|ty| TyKind::Ref(None, MutTy { ty, mutbl: *mutbl }))?
}
ExprKind::Repeat(expr, expr_len) => {
)
}
- // 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.peel_parens().kind {
ExprKind::Box(_)
pub movability: Movability,
pub fn_decl: P<FnDecl>,
pub body: P<Expr>,
- /// The span of the argument block `|...|`.
+ /// The span of the declaration block: 'move |...| -> ...'
pub fn_decl_span: Span,
+ /// The span of the argument block `|...|`
+ pub fn_arg_span: Span,
}
/// Limit types of a range (inclusive or exclusive)
/// Conditionless loop (can be exited with `break`, `continue`, or `return`).
///
/// `'label: loop { block }`
- Loop(P<Block>, Option<Label>),
+ Loop(P<Block>, Option<Label>, Span),
/// A `match` block.
Match(P<Expr>, Vec<Arm>),
/// A closure (e.g., `move |a, b, c| a + b + c`).
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct MacCall {
pub path: Path,
- pub args: P<MacArgs>,
+ pub args: P<DelimArgs>,
pub prior_type_ascription: Option<(Span, bool)>,
}
impl MacCall {
pub fn span(&self) -> Span {
- self.path.span.to(self.args.span().unwrap_or(self.path.span))
+ self.path.span.to(self.args.dspan.entire())
}
}
-/// Arguments passed to an attribute or a function-like macro.
+/// Arguments passed to an attribute macro.
#[derive(Clone, Encodable, Decodable, Debug)]
-pub enum MacArgs {
- /// No arguments - `#[attr]`.
+pub enum AttrArgs {
+ /// No arguments: `#[attr]`.
Empty,
- /// Delimited arguments - `#[attr()/[]/{}]` or `mac!()/[]/{}`.
- Delimited(DelimSpan, MacDelimiter, TokenStream),
- /// Arguments of a key-value attribute - `#[attr = "value"]`.
+ /// Delimited arguments: `#[attr()/[]/{}]`.
+ Delimited(DelimArgs),
+ /// Arguments of a key-value attribute: `#[attr = "value"]`.
Eq(
/// Span of the `=` token.
Span,
/// The "value".
- MacArgsEq,
+ AttrArgsEq,
),
}
-// The RHS of a `MacArgs::Eq` starts out as an expression. Once macro expansion
-// is completed, all cases end up either as a literal, which is the form used
-// after lowering to HIR, or as an error.
+// The RHS of an `AttrArgs::Eq` starts out as an expression. Once macro
+// expansion is completed, all cases end up either as a meta item literal,
+// which is the form used after lowering to HIR, or as an error.
#[derive(Clone, Encodable, Decodable, Debug)]
-pub enum MacArgsEq {
+pub enum AttrArgsEq {
Ast(P<Expr>),
- Hir(Lit),
+ Hir(MetaItemLit),
}
-impl MacArgs {
- pub fn delim(&self) -> Option<Delimiter> {
- match self {
- MacArgs::Delimited(_, delim, _) => Some(delim.to_token()),
- MacArgs::Empty | MacArgs::Eq(..) => None,
- }
- }
-
+impl AttrArgs {
pub fn span(&self) -> Option<Span> {
match self {
- MacArgs::Empty => None,
- MacArgs::Delimited(dspan, ..) => Some(dspan.entire()),
- MacArgs::Eq(eq_span, MacArgsEq::Ast(expr)) => Some(eq_span.to(expr.span)),
- MacArgs::Eq(_, MacArgsEq::Hir(lit)) => {
+ AttrArgs::Empty => None,
+ AttrArgs::Delimited(args) => Some(args.dspan.entire()),
+ AttrArgs::Eq(eq_span, AttrArgsEq::Ast(expr)) => Some(eq_span.to(expr.span)),
+ AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => {
unreachable!("in literal form when getting span: {:?}", lit);
}
}
/// Proc macros see these tokens, for example.
pub fn inner_tokens(&self) -> TokenStream {
match self {
- MacArgs::Empty => TokenStream::default(),
- MacArgs::Delimited(.., tokens) => tokens.clone(),
- MacArgs::Eq(_, MacArgsEq::Ast(expr)) => TokenStream::from_ast(expr),
- MacArgs::Eq(_, MacArgsEq::Hir(lit)) => {
+ AttrArgs::Empty => TokenStream::default(),
+ AttrArgs::Delimited(args) => args.tokens.clone(),
+ AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => TokenStream::from_ast(expr),
+ AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => {
unreachable!("in literal form when getting inner tokens: {:?}", lit)
}
}
}
-
- /// Whether a macro with these arguments needs a semicolon
- /// when used as a standalone item or statement.
- pub fn need_semicolon(&self) -> bool {
- !matches!(self, MacArgs::Delimited(_, MacDelimiter::Brace, _))
- }
}
-impl<CTX> HashStable<CTX> for MacArgs
+impl<CTX> HashStable<CTX> for AttrArgs
where
CTX: crate::HashStableContext,
{
fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
mem::discriminant(self).hash_stable(ctx, hasher);
match self {
- MacArgs::Empty => {}
- MacArgs::Delimited(dspan, delim, tokens) => {
- dspan.hash_stable(ctx, hasher);
- delim.hash_stable(ctx, hasher);
- tokens.hash_stable(ctx, hasher);
- }
- MacArgs::Eq(_eq_span, MacArgsEq::Ast(expr)) => {
+ AttrArgs::Empty => {}
+ AttrArgs::Delimited(args) => args.hash_stable(ctx, hasher),
+ AttrArgs::Eq(_eq_span, AttrArgsEq::Ast(expr)) => {
unreachable!("hash_stable {:?}", expr);
}
- MacArgs::Eq(eq_span, MacArgsEq::Hir(lit)) => {
+ AttrArgs::Eq(eq_span, AttrArgsEq::Hir(lit)) => {
eq_span.hash_stable(ctx, hasher);
lit.hash_stable(ctx, hasher);
}
}
}
+/// Delimited arguments, as used in `#[attr()/[]/{}]` or `mac!()/[]/{}`.
+#[derive(Clone, Encodable, Decodable, Debug)]
+pub struct DelimArgs {
+ pub dspan: DelimSpan,
+ pub delim: MacDelimiter,
+ pub tokens: TokenStream,
+}
+
+impl DelimArgs {
+ /// Whether a macro with these arguments needs a semicolon
+ /// when used as a standalone item or statement.
+ pub fn need_semicolon(&self) -> bool {
+ !matches!(self, DelimArgs { delim: MacDelimiter::Brace, .. })
+ }
+}
+
+impl<CTX> HashStable<CTX> for DelimArgs
+where
+ CTX: crate::HashStableContext,
+{
+ fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
+ let DelimArgs { dspan, delim, tokens } = self;
+ dspan.hash_stable(ctx, hasher);
+ delim.hash_stable(ctx, hasher);
+ tokens.hash_stable(ctx, hasher);
+ }
+}
+
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum MacDelimiter {
Parenthesis,
/// Represents a macro definition.
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
pub struct MacroDef {
- pub body: P<MacArgs>,
+ pub body: P<DelimArgs>,
/// `true` if macro was defined with `macro_rules`.
pub macro_rules: bool,
}
Raw(u8),
}
-/// An AST literal.
+/// A literal in a meta item.
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
-pub struct Lit {
- /// The original literal token as written in source code.
- pub token_lit: token::Lit,
+pub struct MetaItemLit {
+ /// The original literal as written in the source code.
+ pub symbol: Symbol,
+ /// The original suffix as written in the source code.
+ pub suffix: Option<Symbol>,
/// The "semantic" representation of the literal lowered from the original tokens.
/// Strings are unescaped, hexadecimal forms are eliminated, etc.
- /// FIXME: Remove this and only create the semantic representation during lowering to HIR.
pub kind: LitKind,
pub span: Span,
}
-/// Same as `Lit`, but restricted to string literals.
+/// Similar to `MetaItemLit`, but restricted to string literals.
#[derive(Clone, Copy, Encodable, Decodable, Debug)]
pub struct StrLit {
- /// The original literal token as written in source code.
- pub style: StrStyle,
+ /// The original literal as written in source code.
pub symbol: Symbol,
+ /// The original suffix as written in source code.
pub suffix: Option<Symbol>,
- pub span: Span,
- /// The unescaped "semantic" representation of the literal lowered from the original token.
- /// FIXME: Remove this and only create the semantic representation during lowering to HIR.
+ /// The semantic (unescaped) representation of the literal.
pub symbol_unescaped: Symbol,
+ pub style: StrStyle,
+ pub span: Span,
}
impl StrLit {
Unsuffixed,
}
+/// This type is used within both `ast::MetaItemLit` and `hir::Lit`.
+///
/// Note that the entire literal (including the suffix) is considered when
/// deciding the `LitKind`. This means that float literals like `1f32` are
/// classified by this type as `Float`. This is different to `token::LitKind`
/// A string literal (`"foo"`). The symbol is unescaped, and so may differ
/// from the original token's symbol.
Str(Symbol, StrStyle),
- /// A byte string (`b"foo"`).
- ByteStr(Lrc<[u8]>),
+ /// A byte string (`b"foo"`). Not stored as a symbol because it might be
+ /// non-utf8, and symbols only allow utf8 strings.
+ ByteStr(Lrc<[u8]>, StrStyle),
/// A byte char (`b'f'`).
Byte(u8),
/// A character literal (`'a'`).
/// Returns `true` if this literal is byte literal string.
pub fn is_bytestr(&self) -> bool {
- matches!(self, LitKind::ByteStr(_))
+ matches!(self, LitKind::ByteStr(..))
}
/// Returns `true` if this is a numeric literal.
impl Ty {
pub fn peel_refs(&self) -> &Self {
let mut final_ty = self;
- while let TyKind::Rptr(_, MutTy { ty, .. }) = &final_ty.kind {
- final_ty = &ty;
+ while let TyKind::Ref(_, MutTy { ty, .. }) = &final_ty.kind {
+ final_ty = ty;
}
final_ty
}
/// A raw pointer (`*const T` or `*mut T`).
Ptr(MutTy),
/// A reference (`&'a T` or `&'a mut T`).
- Rptr(Option<Lifetime>, MutTy),
+ Ref(Option<Lifetime>, MutTy),
/// A bare function (e.g., `fn(usize) -> bool`).
BareFn(P<BareFnTy>),
/// The never type (`!`).
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() => {
+ TyKind::Ref(lt, MutTy { ref ty, mutbl }) if ty.kind.is_implicit_self() => {
Some(respan(self.pat.span, SelfKind::Region(lt, mutbl)))
}
_ => Some(respan(
Mutability::Not,
P(Ty {
id: DUMMY_NODE_ID,
- kind: TyKind::Rptr(lt, MutTy { ty: infer_ty, mutbl }),
+ kind: TyKind::Ref(lt, MutTy { ty: infer_ty, mutbl }),
span,
tokens: None,
}),
Unloaded,
}
-#[derive(Copy, Clone, Encodable, Decodable, Debug)]
+#[derive(Copy, Clone, Encodable, Decodable, Debug, Default)]
pub struct ModSpans {
/// `inner_span` covers the body of the module; for a file module, its the whole file.
/// For an inline module, its the span inside the `{ ... }`, not including the curly braces.
pub inject_use_span: Span,
}
-impl Default for ModSpans {
- fn default() -> ModSpans {
- ModSpans { inner_span: Default::default(), inject_use_span: Default::default() }
- }
-}
-
/// Foreign module declaration.
///
/// E.g., `extern { .. }` or `extern "C" { .. }`.
#[derive(Clone, Encodable, Decodable, 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<Ident>, NodeId, NodeId),
+ Simple(Option<Ident>),
/// `use prefix::{...}`
Nested(Vec<(UseTree, NodeId)>),
/// `use prefix::*`
impl UseTree {
pub fn ident(&self) -> Ident {
match self.kind {
- UseTreeKind::Simple(Some(rename), ..) => rename,
- UseTreeKind::Simple(None, ..) => {
+ 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"),
}
rustc_index::newtype_index! {
- pub struct AttrId {
- ENCODABLE = custom
- DEBUG_FORMAT = "AttrId({})"
- }
+ #[custom_encodable]
+ #[debug_format = "AttrId({})]"]
+ pub struct AttrId {}
}
impl<S: Encoder> Encodable<S> for AttrId {
}
}
-#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
-pub struct AttrItem {
- pub path: Path,
- pub args: MacArgs,
- pub tokens: Option<LazyAttrTokenStream>,
-}
-
/// A list of attributes.
pub type AttrVec = ThinVec<Attribute>;
-/// Metadata associated with an item.
+/// A syntax-level representation of an attribute.
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Attribute {
pub kind: AttrKind,
pub span: Span,
}
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct NormalAttr {
- pub item: AttrItem,
- pub tokens: Option<LazyAttrTokenStream>,
-}
-
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum AttrKind {
/// A normal attribute.
DocComment(CommentKind, Symbol),
}
+#[derive(Clone, Encodable, Decodable, Debug)]
+pub struct NormalAttr {
+ pub item: AttrItem,
+ pub tokens: Option<LazyAttrTokenStream>,
+}
+
+#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
+pub struct AttrItem {
+ pub path: Path,
+ pub args: AttrArgs,
+ pub tokens: Option<LazyAttrTokenStream>,
+}
+
/// `TraitRef`s appear in impls.
///
/// Resolution maps each `TraitRef`'s `ref_id` to its defining trait; that's all
}
/// Return the `NodeId` of this variant's constructor, if it has one.
- pub fn ctor_id(&self) -> Option<NodeId> {
+ pub fn ctor_node_id(&self) -> Option<NodeId> {
match *self {
VariantData::Struct(..) => None,
VariantData::Tuple(_, id) | VariantData::Unit(id) => Some(id),
static_assert_size!(Impl, 184);
static_assert_size!(Item, 184);
static_assert_size!(ItemKind, 112);
- static_assert_size!(Lit, 48);
static_assert_size!(LitKind, 24);
static_assert_size!(Local, 72);
+ static_assert_size!(MetaItemLit, 40);
static_assert_size!(Param, 40);
static_assert_size!(Pat, 88);
static_assert_size!(Path, 24);