use alloc::boxed::Box;
use alloc::vec::Vec;
use alloc::string::String;
use alloc::string::ToString;
use alloc::borrow::Cow;
use core::borrow::Borrow;
use core::{cmp, fmt};
pub use GenericArgs::*;
pub use UnsafeSource::*;
pub use crate::rustc_ast_ir::{FloatTy, IntTy, Movability, Mutability, Pinnedness, UintTy};
use crate::rustc_data_structures::packed::Pu128;
use crate::rustc_data_structures::stable_hash::{StableHash, StableHashCtxt, StableHasher};
use crate::rustc_data_structures::tagged_ptr::Tag;
use rustc_macros::{Decodable, Encodable, StableHash, Walkable};
pub use crate::rustc_span::AttrId;
use crate::rustc_span::def_id::LocalDefId;
use crate::rustc_span::{
ByteSymbol, DUMMY_SP, ErrorGuaranteed, Ident, LocalExpnId, Span, Spanned, Symbol, kw, respan,
sym,
};
use thin_vec::{ThinVec, thin_vec};
use crate::rustc_ast::attr::data_structures::CfgEntry;
pub use crate::rustc_ast::format::*;
use crate::rustc_ast::token::{self, CommentKind, Delimiter};
use crate::rustc_ast::tokenstream::{DelimSpan, LazyAttrTokenStream, TokenStream};
use crate::rustc_ast::util::parser::{ExprPrecedence, Fixity};
use crate::rustc_ast::visit::{AssocCtxt, BoundKind, LifetimeCtxt};
#[derive(Clone, Encodable, Decodable, Copy, StableHash, Eq, PartialEq, Walkable)]
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)
}
}
#[derive(Clone, Encodable, Decodable, Copy, PartialEq, Eq, Hash, Walkable)]
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)
}
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct Path {
pub span: Span,
pub segments: ThinVec<PathSegment>,
}
impl PartialEq<Symbol> for Path {
#[inline]
fn eq(&self, name: &Symbol) -> bool {
if let [segment] = self.segments.as_ref()
&& segment == name
{
true
} else {
false
}
}
}
impl PartialEq<&[Symbol]> for Path {
#[inline]
fn eq(&self, names: &&[Symbol]) -> bool {
self.segments.iter().eq(*names)
}
}
impl StableHash for Path {
fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
self.segments.len().stable_hash(hcx, hasher);
for segment in &self.segments {
segment.ident.stable_hash(hcx, hasher);
}
}
}
impl Path {
pub fn from_ident(ident: Ident) -> Path {
Path { segments: thin_vec![PathSegment::from_ident(ident)], span: ident.span }
}
pub fn is_global(&self) -> bool {
self.segments.first().is_some_and(|segment| segment.ident.name == kw::PathRoot)
}
pub fn is_single_argless_ident(&self) -> bool {
self.segments.len() == 1 && self.segments[0].args.is_none()
}
pub fn as_single_argless_ident(&self) -> Option<Ident> {
self.is_single_argless_ident().then(|| self.segments[0].ident)
}
}
pub fn join_path_syms(path: impl IntoIterator<Item = impl Borrow<Symbol>>) -> String {
let mut iter = path.into_iter();
let len_hint = iter.size_hint().1.unwrap_or(1);
let mut s = String::with_capacity(len_hint * 8);
let first_sym = *iter.next().unwrap().borrow();
if first_sym != kw::PathRoot {
s.push_str(first_sym.as_str());
}
for sym in iter {
let sym = *sym.borrow();
debug_assert_ne!(sym, kw::PathRoot);
s.push_str("::");
s.push_str(sym.as_str());
}
s
}
pub fn join_path_idents(path: impl IntoIterator<Item = impl Borrow<Ident>>) -> String {
let mut iter = path.into_iter();
let len_hint = iter.size_hint().1.unwrap_or(1);
let mut s = String::with_capacity(len_hint * 8);
let first_ident = *iter.next().unwrap().borrow();
if first_ident.name != kw::PathRoot {
s.push_str(&first_ident.to_string());
}
for ident in iter {
let ident = *ident.borrow();
debug_assert_ne!(ident.name, kw::PathRoot);
s.push_str("::");
s.push_str(&ident.to_string());
}
s
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct PathSegment {
pub ident: Ident,
pub id: NodeId,
pub args: Option<Box<GenericArgs>>,
}
impl PartialEq<Symbol> for PathSegment {
#[inline]
fn eq(&self, name: &Symbol) -> bool {
self.args.is_none() && self.ident.name == *name
}
}
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))
}
pub fn span(&self) -> Span {
match &self.args {
Some(args) => self.ident.span.to(args.span()),
None => self.ident.span,
}
}
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub enum GenericArgs {
AngleBracketed(AngleBracketedArgs),
Parenthesized(ParenthesizedArgs),
ParenthesizedElided(Span),
}
impl GenericArgs {
pub fn is_angle_bracketed(&self) -> bool {
matches!(self, AngleBracketed(..))
}
pub fn span(&self) -> Span {
match self {
AngleBracketed(data) => data.span,
Parenthesized(data) => data.span,
ParenthesizedElided(span) => *span,
}
}
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub enum GenericArg {
Lifetime(#[visitable(extra = LifetimeCtxt::GenericArg)] Lifetime),
Type(Box<Ty>),
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,
}
}
}
#[derive(Clone, Encodable, Decodable, Debug, Default, Walkable)]
pub struct AngleBracketedArgs {
pub span: Span,
pub args: ThinVec<AngleBracketedArg>,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub enum AngleBracketedArg {
Arg(GenericArg),
Constraint(AssocItemConstraint),
}
impl AngleBracketedArg {
pub fn span(&self) -> Span {
match self {
AngleBracketedArg::Arg(arg) => arg.span(),
AngleBracketedArg::Constraint(constraint) => constraint.span,
}
}
}
impl From<AngleBracketedArgs> for Box<GenericArgs> {
fn from(val: AngleBracketedArgs) -> Self {
Box::new(GenericArgs::AngleBracketed(val))
}
}
impl From<ParenthesizedArgs> for Box<GenericArgs> {
fn from(val: ParenthesizedArgs) -> Self {
Box::new(GenericArgs::Parenthesized(val))
}
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct ParenthesizedArgs {
pub span: Span,
pub inputs: ThinVec<Param>,
pub inputs_span: Span,
pub output: FnRetTy,
}
impl ParenthesizedArgs {
pub fn as_angle_bracketed_args(&self) -> AngleBracketedArgs {
let args = self
.inputs
.iter()
.cloned()
.map(|input| AngleBracketedArg::Arg(GenericArg::Type(input.ty)))
.collect();
AngleBracketedArgs { span: self.inputs_span, args }
}
}
pub use crate::rustc_ast::node_id::{CRATE_NODE_ID, DUMMY_NODE_ID, NodeId};
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, Walkable)]
pub struct TraitBoundModifiers {
pub constness: BoundConstness,
pub asyncness: BoundAsyncness,
pub polarity: BoundPolarity,
}
impl TraitBoundModifiers {
pub const NONE: Self = Self {
constness: BoundConstness::Never,
asyncness: BoundAsyncness::Normal,
polarity: BoundPolarity::Positive,
};
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub enum GenericBound {
Trait(PolyTraitRef),
Outlives(#[visitable(extra = LifetimeCtxt::Bound)] Lifetime),
Use(ThinVec<PreciseCapturingArg>, Span),
}
impl GenericBound {
pub fn span(&self) -> Span {
match self {
GenericBound::Trait(t, ..) => t.span,
GenericBound::Outlives(l) => l.ident.span,
GenericBound::Use(_, span) => *span,
}
}
}
pub type GenericBounds = ThinVec<GenericBound>;
#[derive(Hash, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum ParamKindOrd {
Lifetime,
TypeOrConst,
}
impl fmt::Display for ParamKindOrd {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ParamKindOrd::Lifetime => "lifetime".fmt(f),
ParamKindOrd::TypeOrConst => "type and const".fmt(f),
}
}
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub enum GenericParamKind {
Lifetime,
Type {
default: Option<Box<Ty>>,
},
Const {
ty: Box<Ty>,
span: Span,
default: Option<AnonConst>,
},
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct GenericParam {
pub id: NodeId,
pub ident: Ident,
pub attrs: AttrVec,
#[visitable(extra = BoundKind::Bound)]
pub bounds: GenericBounds,
pub is_placeholder: bool,
pub kind: GenericParamKind,
pub colon_span: Option<Span>,
}
impl GenericParam {
pub fn span(&self) -> Span {
match &self.kind {
GenericParamKind::Lifetime | GenericParamKind::Type { default: None } => {
self.ident.span
}
GenericParamKind::Type { default: Some(ty) } => self.ident.span.to(ty.span),
GenericParamKind::Const { span, .. } => *span,
}
}
}
#[derive(Clone, Encodable, Decodable, Debug, Default, Walkable)]
pub struct Generics {
pub params: ThinVec<GenericParam>,
pub where_clause: WhereClause,
pub span: Span,
}
#[derive(Clone, Encodable, Decodable, Debug, Default, Walkable)]
pub struct WhereClause {
pub has_where_token: bool,
pub predicates: ThinVec<WherePredicate>,
pub span: Span,
}
impl WhereClause {
pub fn is_empty(&self) -> bool {
!self.has_where_token && self.predicates.is_empty()
}
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct WherePredicate {
pub attrs: AttrVec,
pub kind: WherePredicateKind,
pub id: NodeId,
pub span: Span,
pub is_placeholder: bool,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub enum WherePredicateKind {
BoundPredicate(WhereBoundPredicate),
RegionPredicate(WhereRegionPredicate),
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct WhereBoundPredicate {
pub bound_generic_params: ThinVec<GenericParam>,
pub bounded_ty: Box<Ty>,
#[visitable(extra = BoundKind::Bound)]
pub bounds: GenericBounds,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct WhereRegionPredicate {
#[visitable(extra = LifetimeCtxt::Bound)]
pub lifetime: Lifetime,
#[visitable(extra = BoundKind::Bound)]
pub bounds: GenericBounds,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct WhereEqPredicate {
pub lhs_ty: Box<Ty>,
pub rhs_ty: Box<Ty>,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct Crate {
pub id: NodeId,
pub attrs: AttrVec,
pub items: ThinVec<Box<Item>>,
pub spans: ModSpans,
pub is_placeholder: bool,
}
#[derive(Clone, Encodable, Decodable, Debug, StableHash)]
pub struct MetaItem {
pub unsafety: Safety,
pub path: Path,
pub kind: MetaItemKind,
pub span: Span,
}
#[derive(Clone, Encodable, Decodable, Debug, StableHash)]
pub enum MetaItemKind {
Word,
List(ThinVec<MetaItemInner>),
NameValue(MetaItemLit),
}
#[derive(Clone, Encodable, Decodable, Debug, StableHash)]
pub enum MetaItemInner {
MetaItem(MetaItem),
Lit(MetaItemLit),
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct Block {
pub stmts: ThinVec<Stmt>,
pub id: NodeId,
pub rules: BlockCheckMode,
pub span: Span,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct Pat {
pub id: NodeId,
pub kind: PatKind,
pub span: Span,
}
impl Pat {
pub fn to_ty(&self) -> Option<Box<Ty>> {
let kind = match &self.kind {
PatKind::Missing => unreachable!(),
PatKind::Wild => TyKind::Infer,
PatKind::Ident(BindingMode::NONE, ident, None) => {
TyKind::Path(None, Path::from_ident(*ident))
}
PatKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()),
PatKind::MacCall(mac) => TyKind::MacCall(mac.clone()),
PatKind::Ref(pat, pinned, mutbl) => pat.to_ty().map(|ty| match pinned {
Pinnedness::Not => TyKind::Ref(None, MutTy { ty, mutbl: *mutbl }),
Pinnedness::Pinned => TyKind::PinnedRef(None, MutTy { ty, mutbl: *mutbl }),
})?,
PatKind::Slice(pats) if let [pat] = pats.as_slice() => {
pat.to_ty().map(TyKind::Slice)?
}
PatKind::Tuple(pats) => {
let tys = pats.iter().map(|pat| pat.to_ty()).collect::<Option<ThinVec<_>>>()?;
TyKind::Tup(tys)
}
_ => return None,
};
Some(Box::new(Ty { kind, id: self.id, span: self.span }))
}
pub fn walk<'ast>(&'ast self, it: &mut impl FnMut(&'ast Pat) -> bool) {
if !it(self) {
return;
}
match &self.kind {
PatKind::Ident(_, _, Some(p)) => p.walk(it),
PatKind::Struct(_, _, fields, _) => fields.iter().for_each(|field| field.pat.walk(it)),
PatKind::TupleStruct(_, _, s)
| PatKind::Tuple(s)
| PatKind::Slice(s)
| PatKind::Or(s) => s.iter().for_each(|p| p.walk(it)),
PatKind::Deref(s)
| PatKind::Ref(s, _, _)
| PatKind::Paren(s)
| PatKind::Guard(s, _) => s.walk(it),
PatKind::Missing
| PatKind::Wild
| PatKind::Rest
| PatKind::Never
| PatKind::Expr(_)
| PatKind::Range(..)
| PatKind::Ident(..)
| PatKind::Path(..)
| PatKind::MacCall(_)
| PatKind::Err(_) => {}
}
}
pub fn peel_refs(&self) -> &Pat {
let mut current = self;
while let PatKind::Ref(inner, _, _) = ¤t.kind {
current = inner;
}
current
}
pub fn is_rest(&self) -> bool {
matches!(self.kind, PatKind::Rest)
}
pub fn could_be_never_pattern(&self) -> bool {
let mut could_be_never_pattern = false;
self.walk(&mut |pat| match &pat.kind {
PatKind::Never | PatKind::MacCall(_) => {
could_be_never_pattern = true;
false
}
PatKind::Or(s) => {
could_be_never_pattern = s.iter().all(|p| p.could_be_never_pattern());
false
}
_ => true,
});
could_be_never_pattern
}
pub fn contains_never_pattern(&self) -> bool {
let mut contains_never_pattern = false;
self.walk(&mut |pat| {
if matches!(pat.kind, PatKind::Never) {
contains_never_pattern = true;
}
true
});
contains_never_pattern
}
pub fn descr(&self) -> Option<String> {
match &self.kind {
PatKind::Missing => unreachable!(),
PatKind::Wild => Some("_".to_string()),
PatKind::Ident(BindingMode::NONE, ident, None) => Some(format!("{ident}")),
PatKind::Ref(pat, pinned, mutbl) => {
pat.descr().map(|d| format!("&{}{d}", pinned.prefix_str(*mutbl)))
}
_ => None,
}
}
}
impl From<Box<Pat>> for Pat {
fn from(value: Box<Pat>) -> Self {
*value
}
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct PatField {
pub ident: Ident,
pub pat: Box<Pat>,
pub is_shorthand: bool,
pub attrs: AttrVec,
pub id: NodeId,
pub span: Span,
pub is_placeholder: bool,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[derive(Encodable, Decodable, StableHash, Walkable)]
pub enum ByRef {
Yes(Pinnedness, Mutability),
No,
}
impl ByRef {
#[must_use]
pub fn cap_ref_mutability(mut self, mutbl: Mutability) -> Self {
if let ByRef::Yes(_, old_mutbl) = &mut self {
*old_mutbl = cmp::min(*old_mutbl, mutbl);
}
self
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[derive(Encodable, Decodable, StableHash, Walkable)]
pub struct BindingMode(pub ByRef, pub Mutability);
impl BindingMode {
pub const NONE: Self = Self(ByRef::No, Mutability::Not);
pub const REF: Self = Self(ByRef::Yes(Pinnedness::Not, Mutability::Not), Mutability::Not);
pub const REF_PIN: Self =
Self(ByRef::Yes(Pinnedness::Pinned, Mutability::Not), Mutability::Not);
pub const MUT: Self = Self(ByRef::No, Mutability::Mut);
pub const REF_MUT: Self = Self(ByRef::Yes(Pinnedness::Not, Mutability::Mut), Mutability::Not);
pub const REF_PIN_MUT: Self =
Self(ByRef::Yes(Pinnedness::Pinned, Mutability::Mut), Mutability::Not);
pub const MUT_REF: Self = Self(ByRef::Yes(Pinnedness::Not, Mutability::Not), Mutability::Mut);
pub const MUT_REF_PIN: Self =
Self(ByRef::Yes(Pinnedness::Pinned, Mutability::Not), Mutability::Mut);
pub const MUT_REF_MUT: Self =
Self(ByRef::Yes(Pinnedness::Not, Mutability::Mut), Mutability::Mut);
pub const MUT_REF_PIN_MUT: Self =
Self(ByRef::Yes(Pinnedness::Pinned, Mutability::Mut), Mutability::Mut);
pub fn prefix_str(self) -> &'static str {
match self {
Self::NONE => "",
Self::REF => "ref ",
Self::REF_PIN => "ref pin const ",
Self::MUT => "mut ",
Self::REF_MUT => "ref mut ",
Self::REF_PIN_MUT => "ref pin mut ",
Self::MUT_REF => "mut ref ",
Self::MUT_REF_PIN => "mut ref pin ",
Self::MUT_REF_MUT => "mut ref mut ",
Self::MUT_REF_PIN_MUT => "mut ref pin mut ",
}
}
}
#[derive(Clone, Copy, Encodable, Decodable, Debug, Walkable)]
pub enum RangeEnd {
Included(RangeSyntax),
Excluded,
}
#[derive(Clone, Copy, Encodable, Decodable, Debug, Walkable)]
pub enum RangeSyntax {
DotDotDot,
DotDotEq,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub enum PatKind {
Missing,
Wild,
Ident(BindingMode, Ident, Option<Box<Pat>>),
Struct(Option<Box<QSelf>>, Path, ThinVec<PatField>, PatFieldsRest),
TupleStruct(Option<Box<QSelf>>, Path, ThinVec<Pat>),
Or(ThinVec<Pat>),
Path(Option<Box<QSelf>>, Path),
Tuple(ThinVec<Pat>),
Deref(Box<Pat>),
Ref(Box<Pat>, Pinnedness, Mutability),
Expr(Box<Expr>),
Range(Option<Box<Expr>>, Option<Box<Expr>>, Spanned<RangeEnd>),
Slice(ThinVec<Pat>),
Rest,
Never,
Guard(Box<Pat>, Box<Guard>),
Paren(Box<Pat>),
MacCall(Box<MacCall>),
Err(ErrorGuaranteed),
}
#[derive(Clone, Copy, Encodable, Decodable, Debug, PartialEq, Walkable)]
pub enum PatFieldsRest {
Rest(Span),
Recovered(ErrorGuaranteed),
None,
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
#[derive(Encodable, Decodable, StableHash, Walkable)]
pub enum BorrowKind {
Ref,
Raw,
Pin,
}
#[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable, StableHash, Walkable)]
pub enum BinOpKind {
Add,
Sub,
Mul,
Div,
Rem,
And,
Or,
BitXor,
BitAnd,
BitOr,
Shl,
Shr,
Eq,
Lt,
Le,
Ne,
Ge,
Gt,
}
impl BinOpKind {
pub fn as_str(&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 is_lazy(&self) -> bool {
matches!(self, BinOpKind::And | BinOpKind::Or)
}
pub fn precedence(&self) -> ExprPrecedence {
use BinOpKind::*;
match *self {
Mul | Div | Rem => ExprPrecedence::Product,
Add | Sub => ExprPrecedence::Sum,
Shl | Shr => ExprPrecedence::Shift,
BitAnd => ExprPrecedence::BitAnd,
BitXor => ExprPrecedence::BitXor,
BitOr => ExprPrecedence::BitOr,
Lt | Gt | Le | Ge | Eq | Ne => ExprPrecedence::Compare,
And => ExprPrecedence::LAnd,
Or => ExprPrecedence::LOr,
}
}
pub fn fixity(&self) -> Fixity {
use BinOpKind::*;
match self {
Eq | Ne | Lt | Le | Gt | Ge => Fixity::None,
Add | Sub | Mul | Div | Rem | And | Or | BitXor | BitAnd | BitOr | Shl | Shr => {
Fixity::Left
}
}
}
pub fn is_comparison(self) -> bool {
use BinOpKind::*;
match self {
Eq | Ne | Lt | Le | Gt | Ge => true,
Add | Sub | Mul | Div | Rem | And | Or | BitXor | BitAnd | BitOr | Shl | Shr => false,
}
}
pub fn is_by_value(self) -> bool {
!self.is_comparison()
}
}
pub type BinOp = Spanned<BinOpKind>;
impl From<AssignOpKind> for BinOpKind {
fn from(op: AssignOpKind) -> BinOpKind {
match op {
AssignOpKind::AddAssign => BinOpKind::Add,
AssignOpKind::SubAssign => BinOpKind::Sub,
AssignOpKind::MulAssign => BinOpKind::Mul,
AssignOpKind::DivAssign => BinOpKind::Div,
AssignOpKind::RemAssign => BinOpKind::Rem,
AssignOpKind::BitXorAssign => BinOpKind::BitXor,
AssignOpKind::BitAndAssign => BinOpKind::BitAnd,
AssignOpKind::BitOrAssign => BinOpKind::BitOr,
AssignOpKind::ShlAssign => BinOpKind::Shl,
AssignOpKind::ShrAssign => BinOpKind::Shr,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable, StableHash, Walkable)]
pub enum AssignOpKind {
AddAssign,
SubAssign,
MulAssign,
DivAssign,
RemAssign,
BitXorAssign,
BitAndAssign,
BitOrAssign,
ShlAssign,
ShrAssign,
}
impl AssignOpKind {
pub fn as_str(&self) -> &'static str {
use AssignOpKind::*;
match self {
AddAssign => "+=",
SubAssign => "-=",
MulAssign => "*=",
DivAssign => "/=",
RemAssign => "%=",
BitXorAssign => "^=",
BitAndAssign => "&=",
BitOrAssign => "|=",
ShlAssign => "<<=",
ShrAssign => ">>=",
}
}
pub fn is_by_value(self) -> bool {
true
}
}
pub type AssignOp = Spanned<AssignOpKind>;
#[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable, StableHash, Walkable)]
pub enum UnOp {
Deref,
Not,
Neg,
}
impl UnOp {
pub fn as_str(&self) -> &'static str {
match self {
UnOp::Deref => "*",
UnOp::Not => "!",
UnOp::Neg => "-",
}
}
pub fn is_by_value(self) -> bool {
matches!(self, Self::Neg | Self::Not)
}
}
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Stmt {
pub id: NodeId,
pub kind: StmtKind,
pub span: Span,
}
impl Stmt {
pub fn has_trailing_semicolon(&self) -> bool {
match &self.kind {
StmtKind::Semi(_) => true,
StmtKind::MacCall(mac) => matches!(mac.style, MacStmtStyle::Semicolon),
_ => false,
}
}
pub fn add_trailing_semicolon(mut self) -> Self {
self.kind = match self.kind {
StmtKind::Expr(expr) => StmtKind::Semi(expr),
StmtKind::MacCall(mut mac) => {
mac.style = MacStmtStyle::Semicolon;
StmtKind::MacCall(mac)
}
kind => kind,
};
self
}
pub fn is_item(&self) -> bool {
matches!(self.kind, StmtKind::Item(_))
}
pub fn is_expr(&self) -> bool {
matches!(self.kind, StmtKind::Expr(_))
}
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub enum StmtKind {
Let(Box<Local>),
Item(Box<Item>),
Expr(Box<Expr>),
Semi(Box<Expr>),
Empty,
MacCall(Box<MacCallStmt>),
}
impl StmtKind {
pub fn descr(&self) -> &'static str {
match self {
StmtKind::Let(_) => "local",
StmtKind::Item(_) => "item",
StmtKind::Expr(_) => "expression",
StmtKind::Semi(_) => "statement",
StmtKind::Empty => "semicolon",
StmtKind::MacCall(_) => "macro call",
}
}
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct MacCallStmt {
pub mac: Box<MacCall>,
pub style: MacStmtStyle,
pub attrs: AttrVec,
pub tokens: Option<LazyAttrTokenStream>,
}
#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, Walkable)]
pub enum MacStmtStyle {
Semicolon,
Braces,
NoBraces,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct Local {
pub id: NodeId,
pub super_: Option<Span>,
pub pat: Box<Pat>,
pub ty: Option<Box<Ty>>,
pub kind: LocalKind,
pub span: Span,
pub colon_sp: Option<Span>,
pub attrs: AttrVec,
pub tokens: Option<LazyAttrTokenStream>,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub enum LocalKind {
Decl,
Init(Box<Expr>),
InitElse(Box<Expr>, Box<Block>),
}
impl LocalKind {
pub fn init(&self) -> Option<&Expr> {
match self {
Self::Decl => None,
Self::Init(i) | Self::InitElse(i, _) => Some(i),
}
}
pub fn init_else_opt(&self) -> Option<(&Expr, Option<&Block>)> {
match self {
Self::Decl => None,
Self::Init(init) => Some((init, None)),
Self::InitElse(init, els) => Some((init, Some(els))),
}
}
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct Arm {
pub attrs: AttrVec,
pub pat: Box<Pat>,
pub guard: Option<Box<Guard>>,
pub body: Option<Box<Expr>>,
pub span: Span,
pub id: NodeId,
pub is_placeholder: bool,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct ExprField {
pub attrs: AttrVec,
pub id: NodeId,
pub span: Span,
pub ident: Ident,
pub expr: Box<Expr>,
pub is_shorthand: bool,
pub is_placeholder: bool,
}
#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy, Walkable)]
pub enum BlockCheckMode {
Default,
Unsafe(UnsafeSource),
}
#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy, Walkable)]
pub enum UnsafeSource {
CompilerGenerated,
UserProvided,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct AnonConst {
pub id: NodeId,
pub value: Box<Expr>,
}
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Expr {
pub id: NodeId,
pub kind: ExprKind,
pub span: Span,
pub attrs: AttrVec,
pub tokens: Option<LazyAttrTokenStream>,
}
impl Expr {
pub fn is_potential_trivial_const_arg(&self) -> bool {
let this = self.maybe_unwrap_block();
if let ExprKind::Path(None, path) = &this.kind
&& path.is_single_argless_ident()
{
true
} else {
false
}
}
pub fn maybe_unwrap_block(&self) -> &Expr {
if let ExprKind::Block(block, None) = &self.kind
&& let [stmt] = block.stmts.as_slice()
&& let StmtKind::Expr(expr) = &stmt.kind
{
expr
} else {
self
}
}
pub fn optionally_braced_mac_call(
&self,
already_stripped_block: bool,
) -> Option<(bool, NodeId)> {
match &self.kind {
ExprKind::Block(block, None)
if let [stmt] = &*block.stmts
&& !already_stripped_block =>
{
match &stmt.kind {
StmtKind::MacCall(_) => Some((true, stmt.id)),
StmtKind::Expr(expr) if let ExprKind::MacCall(_) = &expr.kind => {
Some((true, expr.id))
}
_ => None,
}
}
ExprKind::MacCall(_) => Some((already_stripped_block, self.id)),
_ => None,
}
}
pub fn to_bound(&self) -> Option<GenericBound> {
match &self.kind {
ExprKind::Path(None, path) => Some(GenericBound::Trait(PolyTraitRef::new(
ThinVec::new(),
path.clone(),
TraitBoundModifiers::NONE,
self.span,
Parens::No,
))),
_ => None,
}
}
pub fn peel_parens(&self) -> &Expr {
let mut expr = self;
while let ExprKind::Paren(inner) = &expr.kind {
expr = inner;
}
expr
}
pub fn peel_parens_and_refs(&self) -> &Expr {
let mut expr = self;
while let ExprKind::Paren(inner) | ExprKind::AddrOf(BorrowKind::Ref, _, inner) = &expr.kind
{
expr = inner;
}
expr
}
pub fn to_ty(&self) -> Option<Box<Ty>> {
let kind = match &self.kind {
ExprKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()),
ExprKind::MacCall(mac) => TyKind::MacCall(mac.clone()),
ExprKind::Paren(expr) => expr.to_ty().map(TyKind::Paren)?,
ExprKind::AddrOf(BorrowKind::Ref, mutbl, expr) => {
expr.to_ty().map(|ty| TyKind::Ref(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 let [expr] = exprs.as_slice() => {
expr.to_ty().map(TyKind::Slice)?
}
ExprKind::Tup(exprs) => {
let tys = exprs.iter().map(|expr| expr.to_ty()).collect::<Option<ThinVec<_>>>()?;
TyKind::Tup(tys)
}
ExprKind::Binary(binop, lhs, rhs) if binop.node == BinOpKind::Add => {
let (Some(lhs), Some(rhs)) = (lhs.to_bound(), rhs.to_bound()) else {
return None;
};
TyKind::TraitObject(thin_vec![lhs, rhs], TraitObjectSyntax::None)
}
ExprKind::Underscore => TyKind::Infer,
_ => return None,
};
Some(Box::new(Ty { kind, id: self.id, span: self.span }))
}
pub fn precedence(&self) -> ExprPrecedence {
fn prefix_attrs_precedence(attrs: &AttrVec) -> ExprPrecedence {
for attr in attrs {
if let AttrStyle::Outer = attr.style {
return ExprPrecedence::Prefix;
}
}
ExprPrecedence::Unambiguous
}
match &self.kind {
ExprKind::Closure(closure) => match closure.fn_decl.output {
FnRetTy::Default(_) => ExprPrecedence::Jump,
FnRetTy::Ty(_) => prefix_attrs_precedence(&self.attrs),
},
ExprKind::Break(_ , value)
| ExprKind::Ret(value)
| ExprKind::Yield(YieldKind::Prefix(value))
| ExprKind::Yeet(value) => match value {
Some(_) => ExprPrecedence::Jump,
None => prefix_attrs_precedence(&self.attrs),
},
ExprKind::Become(_) => ExprPrecedence::Jump,
ExprKind::Range(..) => ExprPrecedence::Range,
ExprKind::Binary(op, ..) => op.node.precedence(),
ExprKind::Cast(..) => ExprPrecedence::Cast,
ExprKind::Assign(..) | ExprKind::AssignOp(..) => ExprPrecedence::Assign,
ExprKind::AddrOf(..) => ExprPrecedence::Prefix,
ExprKind::Let(..) | ExprKind::Move(..) | ExprKind::Unary(..) => ExprPrecedence::Prefix,
ExprKind::Array(_)
| ExprKind::Await(..)
| ExprKind::Use(..)
| ExprKind::Block(..)
| ExprKind::Call(..)
| ExprKind::ConstBlock(_)
| ExprKind::Continue(..)
| ExprKind::Field(..)
| ExprKind::ForLoop { .. }
| ExprKind::FormatArgs(..)
| ExprKind::Gen(..)
| ExprKind::If(..)
| ExprKind::IncludedBytes(..)
| ExprKind::Index(..)
| ExprKind::InlineAsm(..)
| ExprKind::Lit(_)
| ExprKind::Loop(..)
| ExprKind::MacCall(..)
| ExprKind::Match(..)
| ExprKind::MethodCall(..)
| ExprKind::OffsetOf(..)
| ExprKind::Paren(..)
| ExprKind::Path(..)
| ExprKind::Repeat(..)
| ExprKind::Struct(..)
| ExprKind::Try(..)
| ExprKind::TryBlock(..)
| ExprKind::Tup(_)
| ExprKind::Type(..)
| ExprKind::Underscore
| ExprKind::UnsafeBinderCast(..)
| ExprKind::While(..)
| ExprKind::Yield(YieldKind::Postfix(..))
| ExprKind::DirectConstArg(..)
| ExprKind::Err(_)
| ExprKind::Dummy => prefix_attrs_precedence(&self.attrs),
}
}
pub fn is_approximately_pattern(&self) -> bool {
matches!(
&self.peel_parens().kind,
ExprKind::Array(_)
| ExprKind::Call(_, _)
| ExprKind::Tup(_)
| ExprKind::Lit(_)
| ExprKind::Range(_, _, _)
| ExprKind::Underscore
| ExprKind::Path(_, _)
| ExprKind::Struct(_)
)
}
pub fn dummy() -> Expr {
Expr {
id: DUMMY_NODE_ID,
kind: ExprKind::Dummy,
span: DUMMY_SP,
attrs: ThinVec::new(),
tokens: None,
}
}
}
impl From<Box<Expr>> for Expr {
fn from(value: Box<Expr>) -> Self {
*value
}
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct ForLoop {
pub pat: Box<Pat>,
pub iter: Box<Expr>,
pub body: Box<Block>,
pub label: Option<Label>,
pub kind: ForLoopKind,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct Closure {
pub binder: ClosureBinder,
pub capture_clause: CaptureBy,
pub constness: Const,
pub coroutine_marker: Option<CoroutineMarker>,
pub movability: Movability,
pub fn_decl: Box<FnDecl>,
pub body: Box<Expr>,
pub fn_decl_span: Span,
pub fn_arg_span: Span,
}
#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, Walkable)]
pub enum RangeLimits {
HalfOpen,
Closed,
}
impl RangeLimits {
pub fn as_str(&self) -> &'static str {
match self {
RangeLimits::HalfOpen => "..",
RangeLimits::Closed => "..=",
}
}
}
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct MethodCall {
pub seg: PathSegment,
pub receiver: Box<Expr>,
pub args: ThinVec<Box<Expr>>,
pub span: Span,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub enum StructRest {
Base(Box<Expr>),
Rest(Span),
None,
NoneWithError(ErrorGuaranteed),
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct StructExpr {
pub qself: Option<Box<QSelf>>,
pub path: Path,
pub fields: ThinVec<ExprField>,
pub rest: StructRest,
}
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum ExprKind {
Array(ThinVec<Box<Expr>>),
ConstBlock(AnonConst),
Call(Box<Expr>, ThinVec<Box<Expr>>),
MethodCall(Box<MethodCall>),
Tup(ThinVec<Box<Expr>>),
Binary(BinOp, Box<Expr>, Box<Expr>),
Unary(UnOp, Box<Expr>),
Move(Box<Expr>, Span),
Lit(token::Lit),
Cast(Box<Expr>, Box<Ty>),
Type(Box<Expr>, Box<Ty>),
Let(Box<Pat>, Box<Expr>, Span, Recovered),
If(Box<Expr>, Box<Block>, Option<Box<Expr>>),
While(Box<Expr>, Box<Block>, Option<Label>),
ForLoop(Box<ForLoop>),
Loop(Box<Block>, Option<Label>, Span),
Match(Box<Expr>, ThinVec<Arm>, MatchKind),
Closure(Box<Closure>),
Block(Box<Block>, Option<Label>),
Gen(CaptureBy, Box<Block>, CoroutineKind, Span),
Await(Box<Expr>, Span),
Use(Box<Expr>, Span),
TryBlock(Box<Block>, Option<Box<Ty>>),
Assign(Box<Expr>, Box<Expr>, Span),
AssignOp(AssignOp, Box<Expr>, Box<Expr>),
Field(Box<Expr>, Ident),
Index(Box<Expr>, Box<Expr>, Span),
Range(Option<Box<Expr>>, Option<Box<Expr>>, RangeLimits),
Underscore,
Path(Option<Box<QSelf>>, Path),
AddrOf(BorrowKind, Mutability, Box<Expr>),
Break(Option<Label>, Option<Box<Expr>>),
Continue(Option<Label>),
Ret(Option<Box<Expr>>),
InlineAsm(Box<InlineAsm>),
OffsetOf(Box<Ty>, ThinVec<Ident>),
MacCall(Box<MacCall>),
Struct(Box<StructExpr>),
Repeat(Box<Expr>, AnonConst),
Paren(Box<Expr>),
Try(Box<Expr>),
Yield(YieldKind),
Yeet(Option<Box<Expr>>),
Become(Box<Expr>),
IncludedBytes(ByteSymbol),
FormatArgs(Box<FormatArgs>),
UnsafeBinderCast(UnsafeBinderCastKind, Box<Expr>, Option<Box<Ty>>),
DirectConstArg(Box<Expr>),
Err(ErrorGuaranteed),
Dummy,
}
#[derive(Clone, Copy, Encodable, Decodable, Debug, PartialEq, Eq, Walkable)]
pub enum ForLoopKind {
For,
ForAwait,
}
#[derive(Clone, Copy, Encodable, Decodable, Debug, PartialEq, Eq, Walkable)]
pub enum CoroutineKind {
Async,
Gen,
AsyncGen,
}
impl fmt::Display for CoroutineKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.as_str().fmt(f)
}
}
impl CoroutineKind {
pub fn is_gen(&self) -> bool {
match self {
CoroutineKind::Async => false,
CoroutineKind::Gen | CoroutineKind::AsyncGen => true,
}
}
pub fn as_str(&self) -> &'static str {
match self {
CoroutineKind::Async => "async",
CoroutineKind::Gen => "gen",
CoroutineKind::AsyncGen => "async gen",
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[derive(Encodable, Decodable, StableHash, Walkable)]
pub enum UnsafeBinderCastKind {
Wrap,
Unwrap,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct QSelf {
pub ty: Box<Ty>,
pub path_span: Span,
pub position: usize,
}
#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, StableHash, Walkable)]
pub enum CaptureBy {
Value {
move_kw: Span,
},
Ref,
Use {
use_kw: Span,
},
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub enum ClosureBinder {
NotPresent,
For {
span: Span,
generic_params: ThinVec<GenericParam>,
},
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct MacCall {
pub path: Path,
pub args: Box<DelimArgs>,
}
impl MacCall {
pub fn span(&self) -> Span {
self.path.span.to(self.args.dspan.entire())
}
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub enum AttrArgs {
Empty,
Delimited(DelimArgs),
Eq {
eq_span: Span,
expr: Box<Expr>,
},
}
impl AttrArgs {
pub fn span(&self) -> Option<Span> {
match self {
AttrArgs::Empty => None,
AttrArgs::Delimited(args) => Some(args.dspan.entire()),
AttrArgs::Eq { eq_span, expr } => Some(eq_span.to(expr.span)),
}
}
pub fn inner_tokens(&self) -> TokenStream {
match self {
AttrArgs::Empty => TokenStream::default(),
AttrArgs::Delimited(args) => args.tokens.clone(),
AttrArgs::Eq { expr, .. } => TokenStream::from_ast(expr),
}
}
}
#[derive(Clone, Encodable, Decodable, Debug, StableHash, Walkable)]
pub struct DelimArgs {
pub dspan: DelimSpan,
pub delim: Delimiter, pub tokens: TokenStream,
}
impl DelimArgs {
pub fn need_semicolon(&self) -> bool {
!matches!(self, DelimArgs { delim: Delimiter::Brace, .. })
}
}
#[derive(Clone, Encodable, Decodable, Debug, StableHash, Walkable)]
pub struct MacroDef {
pub body: Box<DelimArgs>,
pub macro_rules: bool,
pub eii_declaration: Option<EiiDecl>,
}
#[derive(Clone, Encodable, Decodable, Debug, StableHash, Walkable)]
pub struct EiiDecl {
pub foreign_item: Path,
pub impl_unsafe: bool,
}
#[derive(Clone, Encodable, Decodable, Debug, Copy, Hash, Eq, PartialEq)]
#[derive(StableHash, Walkable)]
pub enum StrStyle {
Cooked,
Raw(u8),
}
#[derive(Clone, Copy, Encodable, Decodable, Debug, PartialEq, Walkable)]
pub enum MatchKind {
Prefix,
Postfix,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub enum YieldKind {
Prefix(Option<Box<Expr>>),
Postfix(Box<Expr>),
}
impl YieldKind {
pub const fn expr(&self) -> Option<&Box<Expr>> {
match self {
YieldKind::Prefix(expr) => expr.as_ref(),
YieldKind::Postfix(expr) => Some(expr),
}
}
pub const fn expr_mut(&mut self) -> Option<&mut Box<Expr>> {
match self {
YieldKind::Prefix(expr) => expr.as_mut(),
YieldKind::Postfix(expr) => Some(expr),
}
}
pub const fn same_kind(&self, other: &Self) -> bool {
match (self, other) {
(YieldKind::Prefix(_), YieldKind::Prefix(_)) => true,
(YieldKind::Postfix(_), YieldKind::Postfix(_)) => true,
_ => false,
}
}
}
#[derive(Clone, Copy, Encodable, Decodable, Debug, StableHash)]
pub struct MetaItemLit {
pub symbol: Symbol,
pub suffix: Option<Symbol>,
pub kind: LitKind,
pub span: Span,
}
#[derive(Clone, Copy, Encodable, Decodable, Debug, Walkable)]
pub struct StrLit {
pub symbol: Symbol,
pub suffix: Option<Symbol>,
pub symbol_unescaped: Symbol,
pub style: StrStyle,
pub span: Span,
}
impl StrLit {
pub fn as_token_lit(&self) -> token::Lit {
let token_kind = match self.style {
StrStyle::Cooked => token::Str,
StrStyle::Raw(n) => token::StrRaw(n),
};
token::Lit::new(token_kind, self.symbol, self.suffix)
}
}
#[derive(Clone, Copy, Encodable, Decodable, Debug, Hash, Eq, PartialEq)]
#[derive(StableHash)]
pub enum LitIntType {
Signed(IntTy),
Unsigned(UintTy),
Unsuffixed,
}
#[derive(Clone, Copy, Encodable, Decodable, Debug, Hash, Eq, PartialEq)]
#[derive(StableHash)]
pub enum LitFloatType {
Suffixed(FloatTy),
Unsuffixed,
}
#[derive(Clone, Copy, Encodable, Decodable, Debug, Hash, Eq, PartialEq, StableHash)]
pub enum LitKind {
Str(Symbol, StrStyle),
ByteStr(ByteSymbol, StrStyle),
CStr(ByteSymbol, StrStyle),
Byte(u8),
Char(char),
Int(Pu128, LitIntType),
Float(Symbol, LitFloatType),
Bool(bool),
Err(ErrorGuaranteed),
}
impl LitKind {
pub fn str(&self) -> Option<Symbol> {
match *self {
LitKind::Str(s, _) => Some(s),
_ => None,
}
}
pub fn is_str(&self) -> bool {
matches!(self, LitKind::Str(..))
}
pub fn is_bytestr(&self) -> bool {
matches!(self, LitKind::ByteStr(..))
}
pub fn is_numeric(&self) -> bool {
matches!(self, LitKind::Int(..) | LitKind::Float(..))
}
pub fn is_unsuffixed(&self) -> bool {
!self.is_suffixed()
}
pub fn is_suffixed(&self) -> bool {
match *self {
LitKind::Int(_, LitIntType::Signed(..) | LitIntType::Unsigned(..))
| LitKind::Float(_, LitFloatType::Suffixed(..)) => true,
LitKind::Str(..)
| LitKind::ByteStr(..)
| LitKind::CStr(..)
| LitKind::Byte(..)
| LitKind::Char(..)
| LitKind::Int(_, LitIntType::Unsuffixed)
| LitKind::Float(_, LitFloatType::Unsuffixed)
| LitKind::Bool(..)
| LitKind::Err(_) => false,
}
}
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct MutTy {
pub ty: Box<Ty>,
pub mutbl: Mutability,
}
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct FnSig {
pub header: FnHeader,
pub decl: Box<FnDecl>,
pub span: Span,
}
impl FnSig {
pub fn header_span(&self) -> Span {
self.header.span().unwrap_or(self.span.shrink_to_lo())
}
pub fn safety_span(&self) -> Span {
match self.header.safety {
Safety::Unsafe(span) | Safety::Safe(span) => span,
Safety::Default => {
if let Some(extern_span) = self.header.ext.span() {
return extern_span.shrink_to_lo();
}
self.header_span().shrink_to_hi()
}
}
}
pub fn extern_span(&self) -> Span {
self.header.ext.span().unwrap_or(self.safety_span().shrink_to_hi())
}
pub fn as_borrowed(&self) -> BorrowedFnSig<'_> {
BorrowedFnSig { header: self.header, decl: &self.decl, span: self.span }
}
}
#[derive(Clone, Debug)]
pub struct BorrowedFnSig<'a> {
pub header: FnHeader,
pub decl: &'a FnDecl,
pub span: Span,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct AssocItemConstraint {
pub id: NodeId,
pub ident: Ident,
pub gen_args: Option<GenericArgs>,
pub kind: AssocItemConstraintKind,
pub span: Span,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub enum Term {
Ty(Box<Ty>),
Const(AnonConst),
}
impl From<Box<Ty>> for Term {
fn from(v: Box<Ty>) -> Self {
Term::Ty(v)
}
}
impl From<AnonConst> for Term {
fn from(v: AnonConst) -> Self {
Term::Const(v)
}
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub enum AssocItemConstraintKind {
Equality { term: Term },
Bound {
#[visitable(extra = BoundKind::Bound)]
bounds: GenericBounds,
},
}
#[derive(Encodable, Decodable, Debug, Walkable)]
pub struct Ty {
pub id: NodeId,
pub kind: TyKind,
pub span: Span,
}
impl Clone for Ty {
fn clone(&self) -> Self {
Self { id: self.id, kind: self.kind.clone(), span: self.span }
}
}
impl From<Box<Ty>> for Ty {
fn from(value: Box<Ty>) -> Self {
*value
}
}
impl Ty {
pub fn peel_refs(&self) -> &Self {
let mut final_ty = self;
while let TyKind::Ref(_, MutTy { ty, .. }) | TyKind::Ptr(MutTy { ty, .. }) = &final_ty.kind
{
final_ty = ty;
}
final_ty
}
pub fn is_maybe_parenthesised_infer(&self) -> bool {
match &self.kind {
TyKind::Infer => true,
TyKind::Paren(inner) => inner.is_maybe_parenthesised_infer(),
_ => false,
}
}
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct FnPtrTy {
pub safety: Safety,
pub ext: Extern,
pub generic_params: ThinVec<GenericParam>,
pub decl: Box<FnDecl>,
pub decl_span: Span,
}
impl FnPtrTy {
pub fn header(&self) -> FnHeader {
FnHeader {
constness: Const::No,
coroutine_marker: None,
safety: self.safety,
ext: self.ext,
}
}
pub fn as_borrowed_fn_sig<'a>(&'a self) -> BorrowedFnSig<'a> {
BorrowedFnSig { header: self.header(), decl: &self.decl, span: self.decl_span }
}
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct UnsafeBinderTy {
pub generic_params: ThinVec<GenericParam>,
pub inner_ty: Box<Ty>,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub enum TyKind {
Slice(Box<Ty>),
Array(Box<Ty>, AnonConst),
Ptr(MutTy),
Ref(#[visitable(extra = LifetimeCtxt::Ref)] Option<Lifetime>, MutTy),
PinnedRef(#[visitable(extra = LifetimeCtxt::Ref)] Option<Lifetime>, MutTy),
FnPtr(Box<FnPtrTy>),
UnsafeBinder(Box<UnsafeBinderTy>),
Never,
Tup(ThinVec<Box<Ty>>),
Path(Option<Box<QSelf>>, Path),
TraitObject(#[visitable(extra = BoundKind::TraitObject)] GenericBounds, TraitObjectSyntax),
ImplTrait(NodeId, #[visitable(extra = BoundKind::Impl)] GenericBounds),
Paren(Box<Ty>),
Infer,
ImplicitSelf,
MacCall(Box<MacCall>),
CVarArgs,
Pat(Box<Ty>, Box<TyPat>),
FieldOf(Box<Ty>, Option<Ident>, Ident),
View(Box<Ty>, #[visitable(ignore)] ThinVec<Ident>),
DirectConstArg(Box<Expr>),
Dummy,
Err(ErrorGuaranteed),
}
impl TyKind {
pub fn is_implicit_self(&self) -> bool {
matches!(self, TyKind::ImplicitSelf)
}
pub fn is_unit(&self) -> bool {
matches!(self, TyKind::Tup(tys) if tys.is_empty())
}
pub fn is_simple_path(&self) -> Option<Symbol> {
if let TyKind::Path(None, Path { segments, .. }) = &self
&& let [segment] = &segments[..]
&& segment.args.is_none()
{
Some(segment.ident.name)
} else {
None
}
}
pub fn maybe_scalar(&self) -> bool {
let Some(ty_sym) = self.is_simple_path() else {
return self.is_unit();
};
matches!(
ty_sym,
sym::i8
| sym::i16
| sym::i32
| sym::i64
| sym::i128
| sym::u8
| sym::u16
| sym::u32
| sym::u64
| sym::u128
| sym::f16
| sym::f32
| sym::f64
| sym::f128
| sym::char
| sym::bool
)
}
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct TyPat {
pub id: NodeId,
pub kind: TyPatKind,
pub span: Span,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub enum TyPatKind {
Range(Option<Box<AnonConst>>, Option<Box<AnonConst>>, Spanned<RangeEnd>),
NotNull,
Or(ThinVec<TyPat>),
Err(ErrorGuaranteed),
}
#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, StableHash, Walkable)]
#[repr(u8)]
pub enum TraitObjectSyntax {
Dyn = 0,
None = 1,
}
unsafe impl Tag for TraitObjectSyntax {
const BITS: u32 = 2;
fn into_usize(self) -> usize {
self as u8 as usize
}
unsafe fn from_usize(tag: usize) -> Self {
match tag {
0 => TraitObjectSyntax::Dyn,
1 => TraitObjectSyntax::None,
_ => unreachable!(),
}
}
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub enum PreciseCapturingArg {
Lifetime(#[visitable(extra = LifetimeCtxt::GenericArg)] Lifetime),
Arg(Path, NodeId),
}
#[derive(Clone, Copy, Encodable, Decodable, Debug, Walkable)]
pub enum InlineAsmRegOrRegClass {
Reg(Symbol),
RegClass(Symbol),
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, Encodable, Decodable, StableHash)]
pub struct InlineAsmOptions(u16);
bitflags::bitflags! {
impl InlineAsmOptions: u16 {
const PURE = 1 << 0;
const NOMEM = 1 << 1;
const READONLY = 1 << 2;
const PRESERVES_FLAGS = 1 << 3;
const NORETURN = 1 << 4;
const NOSTACK = 1 << 5;
const ATT_SYNTAX = 1 << 6;
const RAW = 1 << 7;
const MAY_UNWIND = 1 << 8;
}
}
impl InlineAsmOptions {
pub const COUNT: usize = Self::all().bits().count_ones() as usize;
pub const GLOBAL_OPTIONS: Self = Self::ATT_SYNTAX.union(Self::RAW);
pub const NAKED_OPTIONS: Self = Self::ATT_SYNTAX.union(Self::RAW);
pub fn human_readable_names(&self) -> Vec<&'static str> {
let mut options = vec![];
if self.contains(InlineAsmOptions::PURE) {
options.push("pure");
}
if self.contains(InlineAsmOptions::NOMEM) {
options.push("nomem");
}
if self.contains(InlineAsmOptions::READONLY) {
options.push("readonly");
}
if self.contains(InlineAsmOptions::PRESERVES_FLAGS) {
options.push("preserves_flags");
}
if self.contains(InlineAsmOptions::NORETURN) {
options.push("noreturn");
}
if self.contains(InlineAsmOptions::NOSTACK) {
options.push("nostack");
}
if self.contains(InlineAsmOptions::ATT_SYNTAX) {
options.push("att_syntax");
}
if self.contains(InlineAsmOptions::RAW) {
options.push("raw");
}
if self.contains(InlineAsmOptions::MAY_UNWIND) {
options.push("may_unwind");
}
options
}
}
impl core::fmt::Debug for InlineAsmOptions {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
bitflags::parser::to_writer(self, f)
}
}
#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Hash, StableHash, Walkable)]
pub enum InlineAsmTemplatePiece {
String(Cow<'static, str>),
Placeholder { operand_idx: usize, modifier: Option<char>, span: Span },
}
impl fmt::Display for InlineAsmTemplatePiece {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::String(s) => {
for c in s.chars() {
match c {
'{' => f.write_str("{{")?,
'}' => f.write_str("}}")?,
_ => c.fmt(f)?,
}
}
Ok(())
}
Self::Placeholder { operand_idx, modifier: Some(modifier), .. } => {
write!(f, "{{{operand_idx}:{modifier}}}")
}
Self::Placeholder { operand_idx, modifier: None, .. } => {
write!(f, "{{{operand_idx}}}")
}
}
}
}
impl InlineAsmTemplatePiece {
pub fn to_string(s: &[Self]) -> String {
use fmt::Write;
let mut out = String::new();
for p in s.iter() {
let _ = write!(out, "{p}");
}
out
}
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct InlineAsmSym {
pub id: NodeId,
pub qself: Option<Box<QSelf>>,
pub path: Path,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub enum InlineAsmOperand {
In {
reg: InlineAsmRegOrRegClass,
expr: Box<Expr>,
},
Out {
reg: InlineAsmRegOrRegClass,
late: bool,
expr: Option<Box<Expr>>,
},
InOut {
reg: InlineAsmRegOrRegClass,
late: bool,
expr: Box<Expr>,
},
SplitInOut {
reg: InlineAsmRegOrRegClass,
late: bool,
in_expr: Box<Expr>,
out_expr: Option<Box<Expr>>,
},
Const {
anon_const: AnonConst,
},
Sym {
sym: InlineAsmSym,
},
Label {
block: Box<Block>,
},
}
impl InlineAsmOperand {
pub fn reg(&self) -> Option<&InlineAsmRegOrRegClass> {
match self {
Self::In { reg, .. }
| Self::Out { reg, .. }
| Self::InOut { reg, .. }
| Self::SplitInOut { reg, .. } => Some(reg),
Self::Const { .. } | Self::Sym { .. } | Self::Label { .. } => None,
}
}
}
#[derive(Clone, Copy, Encodable, Decodable, Debug, StableHash, Walkable, PartialEq, Eq)]
pub enum AsmMacro {
Asm,
GlobalAsm,
NakedAsm,
}
impl AsmMacro {
pub const fn macro_name(self) -> &'static str {
match self {
AsmMacro::Asm => "asm",
AsmMacro::GlobalAsm => "global_asm",
AsmMacro::NakedAsm => "naked_asm",
}
}
pub const fn is_supported_option(self, option: InlineAsmOptions) -> bool {
match self {
AsmMacro::Asm => true,
AsmMacro::GlobalAsm => InlineAsmOptions::GLOBAL_OPTIONS.contains(option),
AsmMacro::NakedAsm => InlineAsmOptions::NAKED_OPTIONS.contains(option),
}
}
pub const fn diverges(self, options: InlineAsmOptions) -> bool {
match self {
AsmMacro::Asm => options.contains(InlineAsmOptions::NORETURN),
AsmMacro::GlobalAsm => true,
AsmMacro::NakedAsm => true,
}
}
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct InlineAsm {
pub asm_macro: AsmMacro,
pub template: Vec<InlineAsmTemplatePiece>,
pub template_strs: Box<[(Symbol, Option<Symbol>, Span)]>,
pub operands: Vec<(InlineAsmOperand, Span)>,
pub clobber_abis: Vec<(Symbol, Span)>,
#[visitable(ignore)]
pub options: InlineAsmOptions,
pub line_spans: Vec<Span>,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct Param {
pub attrs: AttrVec,
pub ty: Box<Ty>,
pub pat: Box<Pat>,
pub id: NodeId,
pub span: Span,
pub is_placeholder: bool,
}
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum SelfKind {
Value(Mutability),
Region(Option<Lifetime>, Mutability),
Pinned(Option<Lifetime>, Mutability),
Explicit(Box<Ty>, Mutability),
}
impl SelfKind {
pub fn to_ref_suggestion(&self) -> String {
match self {
SelfKind::Region(None, mutbl) => mutbl.ref_prefix_str().to_string(),
SelfKind::Region(Some(lt), mutbl) => format!("&{lt} {}", mutbl.prefix_str()),
SelfKind::Pinned(None, mutbl) => format!("&pin {}", mutbl.ptr_str()),
SelfKind::Pinned(Some(lt), mutbl) => format!("&{lt} pin {}", mutbl.ptr_str()),
SelfKind::Value(_) | SelfKind::Explicit(_, _) => {
unreachable!("if we had an explicit self, we wouldn't be here")
}
}
}
}
pub type ExplicitSelf = Spanned<SelfKind>;
impl Param {
pub fn to_self(&self) -> Option<ExplicitSelf> {
if let PatKind::Ident(BindingMode(ByRef::No, 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::Ref(lt, MutTy { ref ty, mutbl }) if ty.kind.is_implicit_self() => {
Some(respan(self.pat.span, SelfKind::Region(lt, mutbl)))
}
TyKind::PinnedRef(lt, MutTy { ref ty, mutbl })
if ty.kind.is_implicit_self() =>
{
Some(respan(self.pat.span, SelfKind::Pinned(lt, mutbl)))
}
_ => Some(respan(
self.pat.span.to(self.ty.span),
SelfKind::Explicit(self.ty.clone(), mutbl),
)),
};
}
}
None
}
pub fn is_self(&self) -> bool {
if let PatKind::Ident(_, ident, _) = self.pat.kind {
ident.name == kw::SelfLower
} else {
false
}
}
pub fn from_self(attrs: AttrVec, eself: ExplicitSelf, eself_ident: Ident) -> Param {
let span = eself.span.to(eself_ident.span);
let infer_ty =
Box::new(Ty { id: DUMMY_NODE_ID, kind: TyKind::ImplicitSelf, span: eself_ident.span });
let (mutbl, ty) = match eself.node {
SelfKind::Explicit(ty, mutbl) => (mutbl, ty),
SelfKind::Value(mutbl) => (mutbl, infer_ty),
SelfKind::Region(lt, mutbl) => (
Mutability::Not,
Box::new(Ty {
id: DUMMY_NODE_ID,
kind: TyKind::Ref(lt, MutTy { ty: infer_ty, mutbl }),
span,
}),
),
SelfKind::Pinned(lt, mutbl) => (
Mutability::Not,
Box::new(Ty {
id: DUMMY_NODE_ID,
kind: TyKind::PinnedRef(lt, MutTy { ty: infer_ty, mutbl }),
span,
}),
),
};
Param {
attrs,
pat: Box::new(Pat {
id: DUMMY_NODE_ID,
kind: PatKind::Ident(BindingMode(ByRef::No, mutbl), eself_ident, None),
span,
}),
span,
ty,
id: DUMMY_NODE_ID,
is_placeholder: false,
}
}
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct FnDecl {
pub inputs: ThinVec<Param>,
pub output: FnRetTy,
}
impl FnDecl {
pub fn has_self(&self) -> bool {
self.inputs.get(0).is_some_and(Param::is_self)
}
pub fn c_variadic(&self) -> bool {
self.inputs.last().is_some_and(|arg| matches!(arg.ty.kind, TyKind::CVarArgs))
}
pub const NO_SPLATTED_ARG_INDEX: u8 = u8::MAX;
pub const MAX_VALID_SPLATTED_ARG_INDEX: u8 = Self::NO_SPLATTED_ARG_INDEX - 1;
pub fn splatted(&self) -> Option<u8> {
self.inputs.iter().enumerate().find_map(|(index, arg)| {
if index >= usize::from(Self::NO_SPLATTED_ARG_INDEX) {
None
} else {
arg.attrs
.iter()
.any(|attr| attr.has_name(sym::rustc_splat))
.then_some(u8::try_from(index).unwrap())
}
})
}
}
#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, StableHash, Walkable)]
pub enum IsAuto {
Yes,
No,
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, Encodable, Decodable, Debug)]
#[derive(StableHash, Walkable)]
pub enum Safety {
Unsafe(Span),
Safe(Span),
Default,
}
#[derive(Copy, Clone, Encodable, Decodable, Debug, Walkable)]
pub struct CoroutineMarker {
pub kind: CoroutineKind,
pub span: Span,
pub closure_id: NodeId,
pub return_impl_trait_id: NodeId,
}
impl CoroutineMarker {
pub fn new(kind: CoroutineKind, span: Span) -> Self {
Self { kind, span, closure_id: DUMMY_NODE_ID, return_impl_trait_id: DUMMY_NODE_ID }
}
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, Encodable, Decodable, Debug)]
#[derive(StableHash, Walkable)]
pub enum Const {
Yes(Span),
No,
}
#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, StableHash, Walkable)]
pub enum Defaultness {
Implicit,
Default(Span),
Final(Span),
}
#[derive(Copy, Clone, PartialEq, Encodable, Decodable, StableHash, Walkable)]
pub enum ImplPolarity {
Positive,
Negative(Span),
}
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(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, Hash)]
#[derive(StableHash, Walkable)]
pub enum BoundPolarity {
Positive,
Negative(Span),
Maybe(Span),
}
impl BoundPolarity {
pub fn as_str(self) -> &'static str {
match self {
Self::Positive => "",
Self::Negative(_) => "!",
Self::Maybe(_) => "?",
}
}
}
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, Hash)]
#[derive(StableHash, Walkable)]
pub enum BoundConstness {
Never,
Always(Span),
Maybe(Span),
}
impl BoundConstness {
pub fn as_str(self) -> &'static str {
match self {
Self::Never => "",
Self::Always(_) => "const",
Self::Maybe(_) => "[const]",
}
}
}
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug)]
#[derive(StableHash, Walkable)]
pub enum BoundAsyncness {
Normal,
Async(Span),
}
impl BoundAsyncness {
pub fn as_str(self) -> &'static str {
match self {
Self::Normal => "",
Self::Async(_) => "async",
}
}
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub enum FnRetTy {
Default(Span),
Ty(Box<Ty>),
}
impl FnRetTy {
pub fn span(&self) -> Span {
match self {
&FnRetTy::Default(span) => span,
FnRetTy::Ty(ty) => ty.span,
}
}
}
#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, Walkable)]
pub enum Inline {
Yes,
No { had_parse_error: Result<(), ErrorGuaranteed> },
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub enum ModKind {
Loaded(ThinVec<Box<Item>>, Inline, ModSpans),
Unloaded,
}
#[derive(Copy, Clone, Encodable, Decodable, Debug, Default, Walkable)]
pub struct ModSpans {
pub inner_span: Span,
pub inject_use_span: Span,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct ForeignMod {
pub extern_span: Span,
pub safety: Safety,
pub abi: Option<StrLit>,
pub items: ThinVec<Box<ForeignItem>>,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct EnumDef {
pub variants: ThinVec<Variant>,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct Variant {
pub attrs: AttrVec,
pub id: NodeId,
pub span: Span,
pub vis: Visibility,
pub ident: Ident,
pub data: VariantData,
pub disr_expr: Option<AnonConst>,
pub is_placeholder: bool,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub enum UseTreeKind {
Simple(Option<Ident>),
Nested { items: ThinVec<(UseTree, NodeId)>, span: Span },
Glob(Span),
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct UseTree {
pub prefix: Path,
pub kind: UseTreeKind,
}
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"),
}
}
pub fn span(&self) -> Span {
self.prefix.span.to(self.hi_span())
}
pub fn hi_span(&self) -> Span {
match self.kind {
UseTreeKind::Simple(None) => self.prefix.span,
UseTreeKind::Simple(Some(name)) => name.span,
UseTreeKind::Nested { span, .. } => span,
UseTreeKind::Glob(span) => span,
}
}
}
#[derive(Clone, PartialEq, Eq, Hash, Debug, Copy)]
#[derive(Encodable, Decodable, StableHash, Walkable)]
pub enum AttrStyle {
Outer,
Inner,
}
impl AttrStyle {
pub fn line_doc_comment_prefix(self) -> &'static str {
match self {
AttrStyle::Outer => "///",
AttrStyle::Inner => "//!",
}
}
}
pub type AttrVec = ThinVec<Attribute>;
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct Attribute {
pub kind: AttrKind,
pub id: AttrId,
pub style: AttrStyle,
pub span: Span,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub enum AttrKind {
Normal(Box<NormalAttr>),
Synthetic(Box<SyntheticAttr>),
DocComment(CommentKind, Symbol),
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct NormalAttr {
pub item: AttrItem,
pub tokens: Option<LazyAttrTokenStream>,
}
impl NormalAttr {
pub fn from_ident(ident: Ident) -> Self {
Self {
item: AttrItem {
unsafety: Safety::Default,
path: Path::from_ident(ident),
args: AttrArgs::Empty,
span: ident.span,
},
tokens: None,
}
}
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct AttrItem {
pub unsafety: Safety,
pub path: Path,
pub args: AttrArgs,
pub span: Span,
}
#[derive(Clone, Encodable, Decodable, Debug, StableHash)]
pub enum SyntheticAttr {
CfgTrace(CfgEntry),
CfgAttrTrace(CfgEntry),
}
impl AttrItem {
pub fn is_valid_for_outer_style(&self) -> bool {
self.path == sym::cfg_attr
|| self.path == sym::cfg
|| self.path == sym::forbid
|| self.path == sym::warn
|| self.path == sym::allow
|| self.path == sym::deny
|| self.path == sym::expect
}
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct TraitRef {
pub path: Path,
pub ref_id: NodeId,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub enum Parens {
Yes,
No,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct PolyTraitRef {
pub bound_generic_params: ThinVec<GenericParam>,
pub modifiers: TraitBoundModifiers,
pub trait_ref: TraitRef,
pub span: Span,
pub parens: Parens,
}
impl PolyTraitRef {
pub fn new(
generic_params: ThinVec<GenericParam>,
path: Path,
modifiers: TraitBoundModifiers,
span: Span,
parens: Parens,
) -> Self {
PolyTraitRef {
bound_generic_params: generic_params,
modifiers,
trait_ref: TraitRef { path, ref_id: DUMMY_NODE_ID },
span,
parens,
}
}
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct Visibility {
pub kind: VisibilityKind,
pub span: Span,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub enum VisibilityKind {
Public,
Restricted { path: Box<Path>, id: NodeId, shorthand: bool },
Inherited,
}
impl VisibilityKind {
pub fn is_pub(&self) -> bool {
matches!(self, VisibilityKind::Public)
}
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct ImplRestriction {
pub kind: RestrictionKind,
pub span: Span,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct MutRestriction {
pub kind: RestrictionKind,
pub span: Span,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub enum RestrictionKind {
Unrestricted,
Restricted { path: Box<Path>, id: NodeId, shorthand: bool },
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct FieldDef {
pub attrs: AttrVec,
pub id: NodeId,
pub span: Span,
pub vis: Visibility,
pub extras: Option<Box<FieldDefExtras>>,
pub ident: Option<Ident>,
pub ty: Box<Ty>,
pub is_placeholder: bool,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct FieldDefExtras {
pub safety: Safety,
pub mut_restriction: MutRestriction,
pub default: Option<AnonConst>,
}
impl FieldDef {
pub fn mut_restriction(&self) -> &MutRestriction {
static DEFAULT: MutRestriction =
MutRestriction { kind: RestrictionKind::Unrestricted, span: DUMMY_SP };
self.extras.as_ref().map_or(&DEFAULT, |extras| &extras.mut_restriction)
}
pub fn default_value(&self) -> Option<&AnonConst> {
self.extras.as_ref().and_then(|e| e.default.as_ref())
}
pub fn safety(&self) -> Safety {
self.extras.as_ref().map_or(Safety::Default, |extras| extras.safety)
}
}
#[derive(Copy, Clone, Debug, Encodable, Decodable, StableHash, Walkable)]
pub enum Recovered {
No,
Yes(ErrorGuaranteed),
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub enum VariantData {
Struct { fields: ThinVec<FieldDef>, recovered: Recovered },
Tuple(ThinVec<FieldDef>, NodeId),
Unit(NodeId),
}
impl VariantData {
pub fn fields(&self) -> &[FieldDef] {
match self {
VariantData::Struct { fields, .. } | VariantData::Tuple(fields, _) => fields,
_ => &[],
}
}
pub fn ctor_node_id(&self) -> Option<NodeId> {
match *self {
VariantData::Struct { .. } => None,
VariantData::Tuple(_, id) | VariantData::Unit(id) => Some(id),
}
}
}
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Item<K = ItemKind> {
pub attrs: AttrVec,
pub id: NodeId,
pub span: Span,
pub vis: Visibility,
pub kind: K,
pub tokens: Option<LazyAttrTokenStream>,
}
impl Item {
pub fn span_with_attributes(&self) -> Span {
self.attrs.iter().fold(self.span, |acc, attr| acc.to(attr.span))
}
pub fn opt_generics(&self) -> Option<&Generics> {
self.kind.generics()
}
}
impl Item<AssocItemKind> {
pub fn opt_generics(&self) -> Option<&Generics> {
match &self.kind {
AssocItemKind::Fn(fun) => Some(&fun.generics),
AssocItemKind::Const(ct) => Some(&ct.generics),
AssocItemKind::Type(ty) => Some(&ty.generics),
AssocItemKind::Delegation(..)
| AssocItemKind::MacCall(_)
| AssocItemKind::DelegationMac(_) => None,
}
}
}
#[derive(Clone, Copy, Encodable, Decodable, Debug, Walkable)]
pub enum Extern {
None,
Implicit(Span),
Explicit(StrLit, Span),
}
impl Extern {
pub fn from_abi(abi: Option<StrLit>, span: Span) -> Extern {
match abi {
Some(name) => Extern::Explicit(name, span),
None => Extern::Implicit(span),
}
}
pub fn span(self) -> Option<Span> {
match self {
Extern::None => None,
Extern::Implicit(span) | Extern::Explicit(_, span) => Some(span),
}
}
}
#[derive(Clone, Copy, Encodable, Decodable, Debug, Walkable)]
pub struct FnHeader {
pub constness: Const,
pub coroutine_marker: Option<CoroutineMarker>,
pub safety: Safety,
pub ext: Extern,
}
impl FnHeader {
pub fn has_qualifiers(&self) -> bool {
let Self { safety, coroutine_marker, constness, ext } = self;
matches!(safety, Safety::Unsafe(_))
|| coroutine_marker.is_some()
|| matches!(constness, Const::Yes(_))
|| !matches!(ext, Extern::None)
}
pub fn span(&self) -> Option<Span> {
let mut spans = smallvec::SmallVec::<[Span; 4]>::new();
match self.ext {
Extern::Implicit(span) | Extern::Explicit(_, span) => spans.push(span),
Extern::None => {}
}
match self.safety {
Safety::Unsafe(span) | Safety::Safe(span) => spans.push(span),
Safety::Default => {}
};
if let Some(coroutine_marker) = self.coroutine_marker {
spans.push(coroutine_marker.span);
}
if let Const::Yes(span) = self.constness {
spans.push(span)
}
spans.into_iter().reduce(Span::to)
}
}
impl Default for FnHeader {
fn default() -> FnHeader {
FnHeader {
safety: Safety::Default,
coroutine_marker: None,
constness: Const::No,
ext: Extern::None,
}
}
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct TraitAlias {
pub constness: Const,
pub ident: Ident,
pub generics: Generics,
#[visitable(extra = BoundKind::Bound)]
pub bounds: GenericBounds,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct Trait {
pub impl_restriction: ImplRestriction,
pub constness: Const,
pub safety: Safety,
pub is_auto: IsAuto,
pub ident: Ident,
pub generics: Generics,
#[visitable(extra = BoundKind::SuperTraits)]
pub bounds: GenericBounds,
#[visitable(extra = AssocCtxt::Trait)]
pub items: ThinVec<Box<AssocItem>>,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct TyAlias {
pub defaultness: Defaultness,
pub ident: Ident,
pub generics: Generics,
pub after_where_clause: WhereClause,
#[visitable(extra = BoundKind::Bound)]
pub bounds: GenericBounds,
pub ty: Option<Box<Ty>>,
}
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Impl {
pub generics: Generics,
pub constness: Const,
pub of_trait: Option<Box<TraitImplHeader>>,
pub self_ty: Box<Ty>,
pub items: ThinVec<Box<AssocItem>>,
}
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct TraitImplHeader {
pub defaultness: Defaultness,
pub safety: Safety,
pub polarity: ImplPolarity,
pub trait_ref: TraitRef,
}
#[derive(Clone, Encodable, Decodable, Debug, Default, Walkable)]
pub struct FnContract {
pub declarations: ThinVec<Stmt>,
pub requires: Option<Box<Expr>>,
pub ensures: Option<Box<Expr>>,
}
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Fn {
pub defaultness: Defaultness,
pub ident: Ident,
pub generics: Generics,
pub sig: FnSig,
pub contract: Option<Box<FnContract>>,
pub define_opaque: Option<ThinVec<(NodeId, Path)>>,
pub body: Option<Box<Block>>,
pub eii_impl: Option<Box<EiiImpl>>,
}
impl Fn {
pub fn is_pin_drop_sugar(&self) -> bool {
self.ident.name == sym::drop
&& self
.sig
.decl
.inputs
.first()
.and_then(|param| param.to_self())
.is_some_and(|eself| matches!(eself.node, SelfKind::Pinned(None, Mutability::Mut)))
}
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct EiiImpl {
pub node_id: NodeId,
pub eii_macro_path: Path,
pub known_eii_macro_resolution: Option<Path>,
pub impl_safety: Safety,
pub span: Span,
pub inner_span: Span,
pub is_default: bool,
}
#[derive(Clone, Copy, Encodable, Decodable, Debug, PartialEq, Eq)]
pub enum DelegationSource {
Single,
List(LocalExpnId),
Glob,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct Delegation {
pub id: NodeId,
pub qself: Option<Box<QSelf>>,
pub path: Path,
pub ident: Ident,
pub rename: Option<Ident>,
pub body: Option<Box<Block>>,
#[visitable(ignore)]
pub source: DelegationSource,
}
impl Delegation {
pub fn last_segment_span(&self) -> Span {
self.path.segments.last().unwrap().ident.span
}
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub enum DelegationSuffixes {
List(ThinVec<(Ident, Option<Ident>)>),
Glob(Span),
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct DelegationMac {
pub qself: Option<Box<QSelf>>,
pub prefix: Path,
pub suffixes: DelegationSuffixes,
pub body: Option<Box<Block>>,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct StaticItem {
pub ident: Ident,
pub ty: Box<Ty>,
pub safety: Safety,
pub mutability: Mutability,
pub expr: Option<Box<Expr>>,
pub define_opaque: Option<ThinVec<(NodeId, Path)>>,
pub eii_impl: Option<Box<EiiImpl>>,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct ConstItem {
pub defaultness: Defaultness,
pub ident: Ident,
pub generics: Generics,
pub ty: Box<Ty>,
pub body: Option<Box<Expr>>,
#[visitable(ignore)]
pub kind: ConstItemKind,
pub define_opaque: Option<ThinVec<(NodeId, Path)>>,
}
#[derive(Clone, Copy, Encodable, Decodable, Debug, PartialEq, Eq)]
pub enum ConstItemKind {
Body,
TypeConst,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct ConstBlockItem {
pub id: NodeId,
pub span: Span,
pub block: Box<Block>,
}
impl ConstBlockItem {
pub const IDENT: Ident = Ident { name: kw::Underscore, span: DUMMY_SP };
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct Guard {
pub cond: Expr,
pub span_with_leading_if: Span,
}
impl Guard {
pub fn span(&self) -> Span {
self.cond.span
}
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct TestBinderConstraints {
pub generics: Generics,
pub body: Box<TestBinderBody>,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct TestBinderBody {
pub foralls: ThinVec<TestBinderForall>,
pub exists: ThinVec<TestBinderExists>,
pub constraints: Vec<TestBinderConstraint>,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct TestBinderForall {
pub span: Span,
pub node_id: NodeId,
pub generics: Generics,
pub body: TestBinderBody,
pub assert_on_exit: Option<ThinVec<TestBinderConstraint>>,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct TestBinderExists {
pub span: Span,
pub node_id: NodeId,
pub params: ThinVec<GenericParam>,
pub body: TestBinderBody,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub enum TestBinderConstraint {
And {
items: ThinVec<TestBinderConstraint>,
},
Or {
items: ThinVec<TestBinderConstraint>,
},
Lifetime {
#[visitable(extra = LifetimeCtxt::Bound)]
lhs: Lifetime,
#[visitable(extra = LifetimeCtxt::Bound)]
rhs: Lifetime,
},
Type {
lhs: Box<Ty>,
#[visitable(extra = LifetimeCtxt::Bound)]
rhs: Lifetime,
},
}
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum ItemKind {
ExternCrate(Option<Symbol>, Ident),
Use(UseTree),
Static(Box<StaticItem>),
Const(Box<ConstItem>),
ConstBlock(ConstBlockItem),
Fn(Box<Fn>),
Mod(Safety, Ident, ModKind),
ForeignMod(ForeignMod),
GlobalAsm(Box<InlineAsm>),
TyAlias(Box<TyAlias>),
Enum(Ident, Generics, EnumDef),
Struct(Ident, Generics, VariantData),
Union(Ident, Generics, VariantData),
Trait(Box<Trait>),
TraitAlias(Box<TraitAlias>),
Impl(Impl),
MacCall(Box<MacCall>),
MacroDef(Ident, MacroDef),
Delegation(Box<Delegation>),
DelegationMac(Box<DelegationMac>),
TestBinderConstraints(Box<TestBinderConstraints>),
}
impl ItemKind {
pub fn ident(&self) -> Option<Ident> {
match *self {
ItemKind::ExternCrate(_, ident)
| ItemKind::Mod(_, ident, _)
| ItemKind::Enum(ident, ..)
| ItemKind::Struct(ident, ..)
| ItemKind::Union(ident, ..)
| ItemKind::MacroDef(ident, _) => Some(ident),
ItemKind::Static(ref i) => Some(i.ident),
ItemKind::Const(ref i) => Some(i.ident),
ItemKind::Fn(ref i) => Some(i.ident),
ItemKind::TyAlias(ref i) => Some(i.ident),
ItemKind::Trait(ref i) => Some(i.ident),
ItemKind::TraitAlias(ref i) => Some(i.ident),
ItemKind::Delegation(ref i) => Some(i.ident),
ItemKind::ConstBlock(_) => Some(ConstBlockItem::IDENT),
ItemKind::Use(_)
| ItemKind::ForeignMod(_)
| ItemKind::GlobalAsm(_)
| ItemKind::Impl(_)
| ItemKind::MacCall(_)
| ItemKind::DelegationMac(_)
| ItemKind::TestBinderConstraints(_) => None,
}
}
pub fn article(&self) -> &'static str {
use ItemKind::*;
match self {
Use(..)
| Static(..)
| Const(..)
| ConstBlock(..)
| Fn(..)
| Mod(..)
| GlobalAsm(..)
| TyAlias(..)
| Struct(..)
| Union(..)
| Trait(..)
| TraitAlias(..)
| MacroDef(..)
| Delegation(..)
| DelegationMac(..)
| TestBinderConstraints(..) => "a",
ExternCrate(..) | ForeignMod(..) | MacCall(..) | Enum(..) | Impl { .. } => "an",
}
}
pub fn descr(&self) -> &'static str {
match self {
ItemKind::ExternCrate(..) => "extern crate",
ItemKind::Use(..) => "`use` import",
ItemKind::Static(..) => "static item",
ItemKind::Const(..) => "constant item",
ItemKind::ConstBlock(..) => "const block",
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::MacCall(..) => "item macro invocation",
ItemKind::MacroDef(..) => "macro definition",
ItemKind::Impl { .. } => "implementation",
ItemKind::Delegation(..) => "delegated function",
ItemKind::DelegationMac(..) => "delegation",
ItemKind::TestBinderConstraints(..) => "test_binder_constraints!",
}
}
pub fn generics(&self) -> Option<&Generics> {
match self {
Self::Enum(_, generics, _)
| Self::Struct(_, generics, _)
| Self::Union(_, generics, _)
| Self::Impl(Impl { generics, .. }) => Some(generics),
Self::Fn(i) => Some(&i.generics),
Self::TyAlias(i) => Some(&i.generics),
Self::Const(i) => Some(&i.generics),
Self::Trait(i) => Some(&i.generics),
Self::TraitAlias(i) => Some(&i.generics),
Self::TestBinderConstraints(i) => Some(&i.generics),
Self::ExternCrate(..)
| Self::Use(..)
| Self::Static(..)
| Self::ConstBlock(..)
| Self::Mod(..)
| Self::ForeignMod(..)
| Self::GlobalAsm(..)
| Self::MacCall(..)
| Self::MacroDef(..)
| Self::Delegation(..)
| Self::DelegationMac(..) => None,
}
}
}
pub type AssocItem = Item<AssocItemKind>;
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum AssocItemKind {
Const(Box<ConstItem>),
Fn(Box<Fn>),
Type(Box<TyAlias>),
MacCall(Box<MacCall>),
Delegation(Box<Delegation>),
DelegationMac(Box<DelegationMac>),
}
impl AssocItemKind {
pub fn ident(&self) -> Option<Ident> {
match *self {
AssocItemKind::Const(ref i) => Some(i.ident),
AssocItemKind::Fn(ref i) => Some(i.ident),
AssocItemKind::Type(ref i) => Some(i.ident),
AssocItemKind::Delegation(ref i) => Some(i.ident),
AssocItemKind::MacCall(_) | AssocItemKind::DelegationMac(_) => None,
}
}
pub fn defaultness(&self) -> Defaultness {
match *self {
Self::Const(ref i) => i.defaultness,
Self::Fn(ref i) => i.defaultness,
Self::Type(ref i) => i.defaultness,
Self::MacCall(..) | Self::Delegation(..) | Self::DelegationMac(..) => {
Defaultness::Implicit
}
}
}
}
impl From<AssocItemKind> for ItemKind {
fn from(assoc_item_kind: AssocItemKind) -> ItemKind {
match assoc_item_kind {
AssocItemKind::Const(item) => ItemKind::Const(item),
AssocItemKind::Fn(fn_kind) => ItemKind::Fn(fn_kind),
AssocItemKind::Type(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind),
AssocItemKind::MacCall(a) => ItemKind::MacCall(a),
AssocItemKind::Delegation(delegation) => ItemKind::Delegation(delegation),
AssocItemKind::DelegationMac(delegation) => ItemKind::DelegationMac(delegation),
}
}
}
impl TryFrom<ItemKind> for AssocItemKind {
type Error = ItemKind;
fn try_from(item_kind: ItemKind) -> Result<AssocItemKind, ItemKind> {
Ok(match item_kind {
ItemKind::Const(item) => AssocItemKind::Const(item),
ItemKind::Fn(fn_kind) => AssocItemKind::Fn(fn_kind),
ItemKind::TyAlias(ty_kind) => AssocItemKind::Type(ty_kind),
ItemKind::MacCall(a) => AssocItemKind::MacCall(a),
ItemKind::Delegation(d) => AssocItemKind::Delegation(d),
ItemKind::DelegationMac(d) => AssocItemKind::DelegationMac(d),
_ => return Err(item_kind),
})
}
}
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum ForeignItemKind {
Static(Box<StaticItem>),
Fn(Box<Fn>),
TyAlias(Box<TyAlias>),
MacCall(Box<MacCall>),
}
impl ForeignItemKind {
pub fn ident(&self) -> Option<Ident> {
match *self {
ForeignItemKind::Static(ref i) => Some(i.ident),
ForeignItemKind::Fn(ref i) => Some(i.ident),
ForeignItemKind::TyAlias(ref i) => Some(i.ident),
ForeignItemKind::MacCall(_) => None,
}
}
}
impl From<ForeignItemKind> for ItemKind {
fn from(foreign_item_kind: ForeignItemKind) -> ItemKind {
match foreign_item_kind {
ForeignItemKind::Static(static_foreign_item) => ItemKind::Static(static_foreign_item),
ForeignItemKind::Fn(fn_kind) => ItemKind::Fn(fn_kind),
ForeignItemKind::TyAlias(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind),
ForeignItemKind::MacCall(a) => ItemKind::MacCall(a),
}
}
}
impl TryFrom<ItemKind> for ForeignItemKind {
type Error = ItemKind;
fn try_from(item_kind: ItemKind) -> Result<ForeignItemKind, ItemKind> {
Ok(match item_kind {
ItemKind::Static(static_item) => ForeignItemKind::Static(static_item),
ItemKind::Fn(fn_kind) => ForeignItemKind::Fn(fn_kind),
ItemKind::TyAlias(ty_alias_kind) => ForeignItemKind::TyAlias(ty_alias_kind),
ItemKind::MacCall(a) => ForeignItemKind::MacCall(a),
_ => return Err(item_kind),
})
}
}
pub type ForeignItem = Item<ForeignItemKind>;
#[derive(Debug)]
pub enum AstOwner {
NonOwner,
NestedUseTree(LocalDefId),
Crate(Box<Crate>),
Item(Box<Item>),
TraitItem(Box<AssocItem>),
ImplItem(Box<AssocItem>),
ForeignItem(Box<ForeignItem>),
}
#[cfg(target_pointer_width = "64")]
mod size_asserts {
use crate::static_assert_size;
use super::*;
static_assert_size!(AssocItem, 72);
static_assert_size!(AssocItemKind, 16);
static_assert_size!(AttrKind, 16);
static_assert_size!(Attribute, 32);
static_assert_size!(Block, 24);
static_assert_size!(Expr, 72);
static_assert_size!(ExprKind, 40);
static_assert_size!(FieldDef, 80);
static_assert_size!(Fn, 192);
static_assert_size!(FnDecl, 24);
static_assert_size!(FnHeader, 80);
static_assert_size!(FnSig, 96);
static_assert_size!(ForeignItem, 72);
static_assert_size!(ForeignItemKind, 16);
static_assert_size!(GenericArg, 24);
static_assert_size!(GenericArgs, 40);
static_assert_size!(GenericBound, 80);
static_assert_size!(GenericParam, 88);
static_assert_size!(Generics, 40);
static_assert_size!(Impl, 80);
static_assert_size!(Item, 144);
static_assert_size!(ItemKind, 88);
static_assert_size!(Lifetime, 16);
static_assert_size!(LitKind, 24);
static_assert_size!(Local, 96);
static_assert_size!(MetaItem, 88);
static_assert_size!(MetaItemKind, 48);
static_assert_size!(MetaItemLit, 48);
static_assert_size!(NormalAttr, 80);
static_assert_size!(Param, 40);
static_assert_size!(Pat, 64);
static_assert_size!(PatKind, 48);
static_assert_size!(Path, 16);
static_assert_size!(PathSegment, 24);
static_assert_size!(QSelf, 24);
static_assert_size!(Stmt, 32);
static_assert_size!(StmtKind, 16);
static_assert_size!(TraitImplHeader, 64);
static_assert_size!(Ty, 56);
static_assert_size!(TyKind, 40);
}