use crate::def::{DefKind, Namespace, Res};
use crate::def_id::DefId;
crate use crate::hir_id::HirId;
use crate::{itemlikevisit, LangItem};
use rustc_ast::util::parser::ExprPrecedence;
use rustc_ast::{self as ast, CrateSugar, LlvmAsmDialect};
use rustc_ast::{AttrVec, Attribute, FloatTy, IntTy, Label, LitKind, StrStyle, UintTy};
pub use rustc_ast::{BorrowKind, ImplPolarity, IsAuto};
pub use rustc_ast::{CaptureBy, Movability, Mutability};
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_data_structures::sync::{par_for_each_in, Send, Sync};
use rustc_macros::HashStable_Generic;
use rustc_span::def_id::LocalDefId;
use rustc_span::source_map::Spanned;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{MultiSpan, Span, DUMMY_SP};
use rustc_target::asm::InlineAsmRegOrRegClass;
use rustc_target::spec::abi::Abi;
use smallvec::SmallVec;
use std::collections::{BTreeMap, BTreeSet};
use std::fmt;
#[derive(Copy, Clone, Encodable, HashStable_Generic)]
pub struct Lifetime {
pub hir_id: HirId,
pub span: Span,
pub name: LifetimeName,
}
#[derive(Debug, Clone, PartialEq, Eq, Encodable, Hash, Copy)]
#[derive(HashStable_Generic)]
pub enum ParamName {
Plain(Ident),
Fresh(usize),
Error,
}
impl ParamName {
pub fn ident(&self) -> Ident {
match *self {
ParamName::Plain(ident) => ident,
ParamName::Fresh(_) | ParamName::Error => {
Ident::with_dummy_span(kw::UnderscoreLifetime)
}
}
}
pub fn normalize_to_macros_2_0(&self) -> ParamName {
match *self {
ParamName::Plain(ident) => ParamName::Plain(ident.normalize_to_macros_2_0()),
param_name => param_name,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Encodable, Hash, Copy)]
#[derive(HashStable_Generic)]
pub enum LifetimeName {
Param(ParamName),
Implicit,
ImplicitObjectLifetimeDefault,
Error,
Underscore,
Static,
}
impl LifetimeName {
pub fn ident(&self) -> Ident {
match *self {
LifetimeName::ImplicitObjectLifetimeDefault
| LifetimeName::Implicit
| LifetimeName::Error => Ident::invalid(),
LifetimeName::Underscore => Ident::with_dummy_span(kw::UnderscoreLifetime),
LifetimeName::Static => Ident::with_dummy_span(kw::StaticLifetime),
LifetimeName::Param(param_name) => param_name.ident(),
}
}
pub fn is_elided(&self) -> bool {
match self {
LifetimeName::ImplicitObjectLifetimeDefault
| LifetimeName::Implicit
| LifetimeName::Underscore => true,
LifetimeName::Error | LifetimeName::Param(_) | LifetimeName::Static => false,
}
}
fn is_static(&self) -> bool {
self == &LifetimeName::Static
}
pub fn normalize_to_macros_2_0(&self) -> LifetimeName {
match *self {
LifetimeName::Param(param_name) => {
LifetimeName::Param(param_name.normalize_to_macros_2_0())
}
lifetime_name => lifetime_name,
}
}
}
impl fmt::Display for Lifetime {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.name.ident().fmt(f)
}
}
impl fmt::Debug for Lifetime {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "lifetime({}: {})", self.hir_id, self.name.ident())
}
}
impl Lifetime {
pub fn is_elided(&self) -> bool {
self.name.is_elided()
}
pub fn is_static(&self) -> bool {
self.name.is_static()
}
}
#[derive(Debug, HashStable_Generic)]
pub struct Path<'hir> {
pub span: Span,
pub res: Res,
pub segments: &'hir [PathSegment<'hir>],
}
impl Path<'_> {
pub fn is_global(&self) -> bool {
!self.segments.is_empty() && self.segments[0].ident.name == kw::PathRoot
}
}
#[derive(Debug, HashStable_Generic)]
pub struct PathSegment<'hir> {
#[stable_hasher(project(name))]
pub ident: Ident,
pub hir_id: Option<HirId>,
pub res: Option<Res>,
pub args: Option<&'hir GenericArgs<'hir>>,
pub infer_args: bool,
}
impl<'hir> PathSegment<'hir> {
pub fn from_ident(ident: Ident) -> PathSegment<'hir> {
PathSegment { ident, hir_id: None, res: None, infer_args: true, args: None }
}
pub fn generic_args(&self) -> &GenericArgs<'hir> {
if let Some(ref args) = self.args {
args
} else {
const DUMMY: &GenericArgs<'_> = &GenericArgs::none();
DUMMY
}
}
}
#[derive(Encodable, Debug, HashStable_Generic)]
pub struct ConstArg {
pub value: AnonConst,
pub span: Span,
}
#[derive(Debug, HashStable_Generic)]
pub enum GenericArg<'hir> {
Lifetime(Lifetime),
Type(Ty<'hir>),
Const(ConstArg),
}
impl GenericArg<'_> {
pub fn span(&self) -> Span {
match self {
GenericArg::Lifetime(l) => l.span,
GenericArg::Type(t) => t.span,
GenericArg::Const(c) => c.span,
}
}
pub fn id(&self) -> HirId {
match self {
GenericArg::Lifetime(l) => l.hir_id,
GenericArg::Type(t) => t.hir_id,
GenericArg::Const(c) => c.value.hir_id,
}
}
pub fn is_const(&self) -> bool {
matches!(self, GenericArg::Const(_))
}
pub fn descr(&self) -> &'static str {
match self {
GenericArg::Lifetime(_) => "lifetime",
GenericArg::Type(_) => "type",
GenericArg::Const(_) => "constant",
}
}
pub fn short_descr(&self) -> &'static str {
match self {
GenericArg::Lifetime(_) => "lifetime",
GenericArg::Type(_) => "type",
GenericArg::Const(_) => "const",
}
}
}
#[derive(Debug, HashStable_Generic)]
pub struct GenericArgs<'hir> {
pub args: &'hir [GenericArg<'hir>],
pub bindings: &'hir [TypeBinding<'hir>],
pub parenthesized: bool,
}
impl GenericArgs<'_> {
pub const fn none() -> Self {
Self { args: &[], bindings: &[], parenthesized: false }
}
pub fn inputs(&self) -> &[Ty<'_>] {
if self.parenthesized {
for arg in self.args {
match arg {
GenericArg::Lifetime(_) => {}
GenericArg::Type(ref ty) => {
if let TyKind::Tup(ref tys) = ty.kind {
return tys;
}
break;
}
GenericArg::Const(_) => {}
}
}
}
panic!("GenericArgs::inputs: not a `Fn(T) -> U`");
}
pub fn own_counts(&self) -> GenericParamCount {
let mut own_counts: GenericParamCount = Default::default();
for arg in self.args {
match arg {
GenericArg::Lifetime(_) => own_counts.lifetimes += 1,
GenericArg::Type(_) => own_counts.types += 1,
GenericArg::Const(_) => own_counts.consts += 1,
};
}
own_counts
}
}
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Hash, Debug)]
#[derive(HashStable_Generic)]
pub enum TraitBoundModifier {
None,
Maybe,
MaybeConst,
}
#[derive(Debug, HashStable_Generic)]
pub enum GenericBound<'hir> {
Trait(PolyTraitRef<'hir>, TraitBoundModifier),
LangItemTrait(LangItem, Span, HirId, &'hir GenericArgs<'hir>),
Outlives(Lifetime),
}
impl GenericBound<'_> {
pub fn trait_ref(&self) -> Option<&TraitRef<'_>> {
match self {
GenericBound::Trait(data, _) => Some(&data.trait_ref),
_ => None,
}
}
pub fn span(&self) -> Span {
match self {
&GenericBound::Trait(ref t, ..) => t.span,
&GenericBound::LangItemTrait(_, span, ..) => span,
&GenericBound::Outlives(ref l) => l.span,
}
}
}
pub type GenericBounds<'hir> = &'hir [GenericBound<'hir>];
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug, HashStable_Generic)]
pub enum LifetimeParamKind {
Explicit,
InBand,
Elided,
Error,
}
#[derive(Debug, HashStable_Generic)]
pub enum GenericParamKind<'hir> {
Lifetime {
kind: LifetimeParamKind,
},
Type {
default: Option<&'hir Ty<'hir>>,
synthetic: Option<SyntheticTyParamKind>,
},
Const {
ty: &'hir Ty<'hir>,
},
}
#[derive(Debug, HashStable_Generic)]
pub struct GenericParam<'hir> {
pub hir_id: HirId,
pub name: ParamName,
pub attrs: &'hir [Attribute],
pub bounds: GenericBounds<'hir>,
pub span: Span,
pub pure_wrt_drop: bool,
pub kind: GenericParamKind<'hir>,
}
impl GenericParam<'hir> {
pub fn bounds_span(&self) -> Option<Span> {
self.bounds.iter().fold(None, |span, bound| {
let span = span.map(|s| s.to(bound.span())).unwrap_or_else(|| bound.span());
Some(span)
})
}
}
#[derive(Default)]
pub struct GenericParamCount {
pub lifetimes: usize,
pub types: usize,
pub consts: usize,
}
#[derive(Debug, HashStable_Generic)]
pub struct Generics<'hir> {
pub params: &'hir [GenericParam<'hir>],
pub where_clause: WhereClause<'hir>,
pub span: Span,
}
impl Generics<'hir> {
pub const fn empty() -> Generics<'hir> {
Generics {
params: &[],
where_clause: WhereClause { predicates: &[], span: DUMMY_SP },
span: DUMMY_SP,
}
}
pub fn get_named(&self, name: Symbol) -> Option<&GenericParam<'_>> {
for param in self.params {
if name == param.name.ident().name {
return Some(param);
}
}
None
}
pub fn spans(&self) -> MultiSpan {
if self.params.is_empty() {
self.span.into()
} else {
self.params.iter().map(|p| p.span).collect::<Vec<Span>>().into()
}
}
}
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
#[derive(HashStable_Generic)]
pub enum SyntheticTyParamKind {
ImplTrait,
FromAttr,
}
#[derive(Debug, HashStable_Generic)]
pub struct WhereClause<'hir> {
pub predicates: &'hir [WherePredicate<'hir>],
pub span: Span,
}
impl WhereClause<'_> {
pub fn span(&self) -> Option<Span> {
if self.predicates.is_empty() { None } else { Some(self.span) }
}
pub fn span_for_predicates_or_empty_place(&self) -> Span {
self.span
}
pub fn tail_span_for_suggestion(&self) -> Span {
let end = self.span_for_predicates_or_empty_place().shrink_to_hi();
self.predicates.last().map(|p| p.span()).unwrap_or(end).shrink_to_hi().to(end)
}
}
#[derive(Debug, HashStable_Generic)]
pub enum WherePredicate<'hir> {
BoundPredicate(WhereBoundPredicate<'hir>),
RegionPredicate(WhereRegionPredicate<'hir>),
EqPredicate(WhereEqPredicate<'hir>),
}
impl WherePredicate<'_> {
pub fn span(&self) -> Span {
match self {
&WherePredicate::BoundPredicate(ref p) => p.span,
&WherePredicate::RegionPredicate(ref p) => p.span,
&WherePredicate::EqPredicate(ref p) => p.span,
}
}
}
#[derive(Debug, HashStable_Generic)]
pub struct WhereBoundPredicate<'hir> {
pub span: Span,
pub bound_generic_params: &'hir [GenericParam<'hir>],
pub bounded_ty: &'hir Ty<'hir>,
pub bounds: GenericBounds<'hir>,
}
#[derive(Debug, HashStable_Generic)]
pub struct WhereRegionPredicate<'hir> {
pub span: Span,
pub lifetime: Lifetime,
pub bounds: GenericBounds<'hir>,
}
#[derive(Debug, HashStable_Generic)]
pub struct WhereEqPredicate<'hir> {
pub hir_id: HirId,
pub span: Span,
pub lhs_ty: &'hir Ty<'hir>,
pub rhs_ty: &'hir Ty<'hir>,
}
#[derive(Encodable, Debug, HashStable_Generic)]
pub struct ModuleItems {
pub items: BTreeSet<HirId>,
pub trait_items: BTreeSet<TraitItemId>,
pub impl_items: BTreeSet<ImplItemId>,
}
#[derive(Encodable, Debug, HashStable_Generic)]
pub struct CrateItem<'hir> {
pub module: Mod<'hir>,
pub attrs: &'hir [Attribute],
pub span: Span,
}
#[derive(Debug)]
pub struct Crate<'hir> {
pub item: CrateItem<'hir>,
pub exported_macros: &'hir [MacroDef<'hir>],
pub non_exported_macro_attrs: &'hir [Attribute],
pub items: BTreeMap<HirId, Item<'hir>>,
pub trait_items: BTreeMap<TraitItemId, TraitItem<'hir>>,
pub impl_items: BTreeMap<ImplItemId, ImplItem<'hir>>,
pub bodies: BTreeMap<BodyId, Body<'hir>>,
pub trait_impls: BTreeMap<DefId, Vec<HirId>>,
pub body_ids: Vec<BodyId>,
pub modules: BTreeMap<HirId, ModuleItems>,
pub proc_macros: Vec<HirId>,
pub trait_map: BTreeMap<HirId, Vec<TraitCandidate>>,
}
impl Crate<'hir> {
pub fn item(&self, id: HirId) -> &Item<'hir> {
&self.items[&id]
}
pub fn trait_item(&self, id: TraitItemId) -> &TraitItem<'hir> {
&self.trait_items[&id]
}
pub fn impl_item(&self, id: ImplItemId) -> &ImplItem<'hir> {
&self.impl_items[&id]
}
pub fn body(&self, id: BodyId) -> &Body<'hir> {
&self.bodies[&id]
}
}
impl Crate<'_> {
pub fn visit_all_item_likes<'hir, V>(&'hir self, visitor: &mut V)
where
V: itemlikevisit::ItemLikeVisitor<'hir>,
{
for item in self.items.values() {
visitor.visit_item(item);
}
for trait_item in self.trait_items.values() {
visitor.visit_trait_item(trait_item);
}
for impl_item in self.impl_items.values() {
visitor.visit_impl_item(impl_item);
}
}
pub fn par_visit_all_item_likes<'hir, V>(&'hir self, visitor: &V)
where
V: itemlikevisit::ParItemLikeVisitor<'hir> + Sync + Send,
{
parallel!(
{
par_for_each_in(&self.items, |(_, item)| {
visitor.visit_item(item);
});
},
{
par_for_each_in(&self.trait_items, |(_, trait_item)| {
visitor.visit_trait_item(trait_item);
});
},
{
par_for_each_in(&self.impl_items, |(_, impl_item)| {
visitor.visit_impl_item(impl_item);
});
}
);
}
}
#[derive(Debug, HashStable_Generic)]
pub struct MacroDef<'hir> {
pub ident: Ident,
pub vis: Visibility<'hir>,
pub attrs: &'hir [Attribute],
pub hir_id: HirId,
pub span: Span,
pub ast: ast::MacroDef,
}
#[derive(Debug, HashStable_Generic)]
pub struct Block<'hir> {
pub stmts: &'hir [Stmt<'hir>],
pub expr: Option<&'hir Expr<'hir>>,
#[stable_hasher(ignore)]
pub hir_id: HirId,
pub rules: BlockCheckMode,
pub span: Span,
pub targeted_by_break: bool,
}
#[derive(Debug, HashStable_Generic)]
pub struct Pat<'hir> {
#[stable_hasher(ignore)]
pub hir_id: HirId,
pub kind: PatKind<'hir>,
pub span: Span,
pub default_binding_modes: bool,
}
impl Pat<'_> {
fn walk_short_(&self, it: &mut impl FnMut(&Pat<'_>) -> bool) -> bool {
if !it(self) {
return false;
}
use PatKind::*;
match &self.kind {
Wild | Lit(_) | Range(..) | Binding(.., None) | Path(_) => true,
Box(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_short_(it),
Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk_short_(it)),
TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().all(|p| p.walk_short_(it)),
Slice(before, slice, after) => {
before.iter().chain(slice.iter()).chain(after.iter()).all(|p| p.walk_short_(it))
}
}
}
pub fn walk_short(&self, mut it: impl FnMut(&Pat<'_>) -> bool) -> bool {
self.walk_short_(&mut it)
}
fn walk_(&self, it: &mut impl FnMut(&Pat<'_>) -> bool) {
if !it(self) {
return;
}
use PatKind::*;
match &self.kind {
Wild | Lit(_) | Range(..) | Binding(.., None) | Path(_) => {}
Box(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_(it),
Struct(_, fields, _) => fields.iter().for_each(|field| field.pat.walk_(it)),
TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().for_each(|p| p.walk_(it)),
Slice(before, slice, after) => {
before.iter().chain(slice.iter()).chain(after.iter()).for_each(|p| p.walk_(it))
}
}
}
pub fn walk(&self, mut it: impl FnMut(&Pat<'_>) -> bool) {
self.walk_(&mut it)
}
pub fn walk_always(&self, mut it: impl FnMut(&Pat<'_>)) {
self.walk(|p| {
it(p);
true
})
}
}
#[derive(Debug, HashStable_Generic)]
pub struct FieldPat<'hir> {
#[stable_hasher(ignore)]
pub hir_id: HirId,
#[stable_hasher(project(name))]
pub ident: Ident,
pub pat: &'hir Pat<'hir>,
pub is_shorthand: bool,
pub span: Span,
}
#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
pub enum BindingAnnotation {
Unannotated,
Mutable,
Ref,
RefMut,
}
#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
pub enum RangeEnd {
Included,
Excluded,
}
impl fmt::Display for RangeEnd {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
RangeEnd::Included => "..=",
RangeEnd::Excluded => "..",
})
}
}
#[derive(Debug, HashStable_Generic)]
pub enum PatKind<'hir> {
Wild,
Binding(BindingAnnotation, HirId, Ident, Option<&'hir Pat<'hir>>),
Struct(QPath<'hir>, &'hir [FieldPat<'hir>], bool),
TupleStruct(QPath<'hir>, &'hir [&'hir Pat<'hir>], Option<usize>),
Or(&'hir [&'hir Pat<'hir>]),
Path(QPath<'hir>),
Tuple(&'hir [&'hir Pat<'hir>], Option<usize>),
Box(&'hir Pat<'hir>),
Ref(&'hir Pat<'hir>, Mutability),
Lit(&'hir Expr<'hir>),
Range(Option<&'hir Expr<'hir>>, Option<&'hir Expr<'hir>>, RangeEnd),
Slice(&'hir [&'hir Pat<'hir>], Option<&'hir Pat<'hir>>, &'hir [&'hir Pat<'hir>]),
}
#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
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 {
match self {
BinOpKind::Add => "+",
BinOpKind::Sub => "-",
BinOpKind::Mul => "*",
BinOpKind::Div => "/",
BinOpKind::Rem => "%",
BinOpKind::And => "&&",
BinOpKind::Or => "||",
BinOpKind::BitXor => "^",
BinOpKind::BitAnd => "&",
BinOpKind::BitOr => "|",
BinOpKind::Shl => "<<",
BinOpKind::Shr => ">>",
BinOpKind::Eq => "==",
BinOpKind::Lt => "<",
BinOpKind::Le => "<=",
BinOpKind::Ne => "!=",
BinOpKind::Ge => ">=",
BinOpKind::Gt => ">",
}
}
pub fn is_lazy(self) -> bool {
matches!(self, BinOpKind::And | BinOpKind::Or)
}
pub fn is_shift(self) -> bool {
matches!(self, BinOpKind::Shl | BinOpKind::Shr)
}
pub fn is_comparison(self) -> bool {
match self {
BinOpKind::Eq
| BinOpKind::Lt
| BinOpKind::Le
| BinOpKind::Ne
| BinOpKind::Gt
| BinOpKind::Ge => true,
BinOpKind::And
| BinOpKind::Or
| BinOpKind::Add
| BinOpKind::Sub
| BinOpKind::Mul
| BinOpKind::Div
| BinOpKind::Rem
| BinOpKind::BitXor
| BinOpKind::BitAnd
| BinOpKind::BitOr
| BinOpKind::Shl
| BinOpKind::Shr => false,
}
}
pub fn is_by_value(self) -> bool {
!self.is_comparison()
}
}
impl Into<ast::BinOpKind> for BinOpKind {
fn into(self) -> ast::BinOpKind {
match self {
BinOpKind::Add => ast::BinOpKind::Add,
BinOpKind::Sub => ast::BinOpKind::Sub,
BinOpKind::Mul => ast::BinOpKind::Mul,
BinOpKind::Div => ast::BinOpKind::Div,
BinOpKind::Rem => ast::BinOpKind::Rem,
BinOpKind::And => ast::BinOpKind::And,
BinOpKind::Or => ast::BinOpKind::Or,
BinOpKind::BitXor => ast::BinOpKind::BitXor,
BinOpKind::BitAnd => ast::BinOpKind::BitAnd,
BinOpKind::BitOr => ast::BinOpKind::BitOr,
BinOpKind::Shl => ast::BinOpKind::Shl,
BinOpKind::Shr => ast::BinOpKind::Shr,
BinOpKind::Eq => ast::BinOpKind::Eq,
BinOpKind::Lt => ast::BinOpKind::Lt,
BinOpKind::Le => ast::BinOpKind::Le,
BinOpKind::Ne => ast::BinOpKind::Ne,
BinOpKind::Ge => ast::BinOpKind::Ge,
BinOpKind::Gt => ast::BinOpKind::Gt,
}
}
}
pub type BinOp = Spanned<BinOpKind>;
#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
pub enum UnOp {
UnDeref,
UnNot,
UnNeg,
}
impl UnOp {
pub fn as_str(self) -> &'static str {
match self {
Self::UnDeref => "*",
Self::UnNot => "!",
Self::UnNeg => "-",
}
}
pub fn is_by_value(self) -> bool {
matches!(self, Self::UnNeg | Self::UnNot)
}
}
#[derive(Debug, HashStable_Generic)]
pub struct Stmt<'hir> {
pub hir_id: HirId,
pub kind: StmtKind<'hir>,
pub span: Span,
}
#[derive(Debug, HashStable_Generic)]
pub enum StmtKind<'hir> {
Local(&'hir Local<'hir>),
Item(ItemId),
Expr(&'hir Expr<'hir>),
Semi(&'hir Expr<'hir>),
}
impl<'hir> StmtKind<'hir> {
pub fn attrs(&self, get_item: impl FnOnce(ItemId) -> &'hir Item<'hir>) -> &'hir [Attribute] {
match *self {
StmtKind::Local(ref l) => &l.attrs,
StmtKind::Item(ref item_id) => &get_item(*item_id).attrs,
StmtKind::Expr(ref e) | StmtKind::Semi(ref e) => &e.attrs,
}
}
}
#[derive(Debug, HashStable_Generic)]
pub struct Local<'hir> {
pub pat: &'hir Pat<'hir>,
pub ty: Option<&'hir Ty<'hir>>,
pub init: Option<&'hir Expr<'hir>>,
pub hir_id: HirId,
pub span: Span,
pub attrs: AttrVec,
pub source: LocalSource,
}
#[derive(Debug, HashStable_Generic)]
pub struct Arm<'hir> {
#[stable_hasher(ignore)]
pub hir_id: HirId,
pub span: Span,
pub attrs: &'hir [Attribute],
pub pat: &'hir Pat<'hir>,
pub guard: Option<Guard<'hir>>,
pub body: &'hir Expr<'hir>,
}
#[derive(Debug, HashStable_Generic)]
pub enum Guard<'hir> {
If(&'hir Expr<'hir>),
}
#[derive(Debug, HashStable_Generic)]
pub struct Field<'hir> {
#[stable_hasher(ignore)]
pub hir_id: HirId,
pub ident: Ident,
pub expr: &'hir Expr<'hir>,
pub span: Span,
pub is_shorthand: bool,
}
#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
pub enum BlockCheckMode {
DefaultBlock,
UnsafeBlock(UnsafeSource),
PushUnsafeBlock(UnsafeSource),
PopUnsafeBlock(UnsafeSource),
}
#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
pub enum UnsafeSource {
CompilerGenerated,
UserProvided,
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Hash, Debug)]
pub struct BodyId {
pub hir_id: HirId,
}
#[derive(Debug)]
pub struct Body<'hir> {
pub params: &'hir [Param<'hir>],
pub value: Expr<'hir>,
pub generator_kind: Option<GeneratorKind>,
}
impl Body<'hir> {
pub fn id(&self) -> BodyId {
BodyId { hir_id: self.value.hir_id }
}
pub fn generator_kind(&self) -> Option<GeneratorKind> {
self.generator_kind
}
}
#[derive(Clone, PartialEq, Eq, HashStable_Generic, Encodable, Decodable, Debug, Copy)]
pub enum GeneratorKind {
Async(AsyncGeneratorKind),
Gen,
}
impl fmt::Display for GeneratorKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
GeneratorKind::Async(k) => fmt::Display::fmt(k, f),
GeneratorKind::Gen => f.write_str("generator"),
}
}
}
#[derive(Clone, PartialEq, Eq, HashStable_Generic, Encodable, Decodable, Debug, Copy)]
pub enum AsyncGeneratorKind {
Block,
Closure,
Fn,
}
impl fmt::Display for AsyncGeneratorKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
AsyncGeneratorKind::Block => "`async` block",
AsyncGeneratorKind::Closure => "`async` closure body",
AsyncGeneratorKind::Fn => "`async fn` body",
})
}
}
#[derive(Copy, Clone, Debug)]
pub enum BodyOwnerKind {
Fn,
Closure,
Const,
Static(Mutability),
}
impl BodyOwnerKind {
pub fn is_fn_or_closure(self) -> bool {
match self {
BodyOwnerKind::Fn | BodyOwnerKind::Closure => true,
BodyOwnerKind::Const | BodyOwnerKind::Static(_) => false,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ConstContext {
ConstFn,
Static(Mutability),
Const,
}
impl ConstContext {
pub fn keyword_name(self) -> &'static str {
match self {
Self::Const => "const",
Self::Static(Mutability::Not) => "static",
Self::Static(Mutability::Mut) => "static mut",
Self::ConstFn => "const fn",
}
}
}
impl fmt::Display for ConstContext {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
Self::Const => write!(f, "constant"),
Self::Static(_) => write!(f, "static"),
Self::ConstFn => write!(f, "constant function"),
}
}
}
pub type Lit = Spanned<LitKind>;
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug, HashStable_Generic)]
pub struct AnonConst {
pub hir_id: HirId,
pub body: BodyId,
}
#[derive(Debug)]
pub struct Expr<'hir> {
pub hir_id: HirId,
pub kind: ExprKind<'hir>,
pub attrs: AttrVec,
pub span: Span,
}
#[cfg(target_arch = "x86_64")]
rustc_data_structures::static_assert_size!(Expr<'static>, 72);
impl Expr<'_> {
pub fn precedence(&self) -> ExprPrecedence {
match self.kind {
ExprKind::Box(_) => ExprPrecedence::Box,
ExprKind::ConstBlock(_) => ExprPrecedence::ConstBlock,
ExprKind::Array(_) => ExprPrecedence::Array,
ExprKind::Call(..) => ExprPrecedence::Call,
ExprKind::MethodCall(..) => ExprPrecedence::MethodCall,
ExprKind::Tup(_) => ExprPrecedence::Tup,
ExprKind::Binary(op, ..) => ExprPrecedence::Binary(op.node.into()),
ExprKind::Unary(..) => ExprPrecedence::Unary,
ExprKind::Lit(_) => ExprPrecedence::Lit,
ExprKind::Type(..) | ExprKind::Cast(..) => ExprPrecedence::Cast,
ExprKind::DropTemps(ref expr, ..) => expr.precedence(),
ExprKind::Loop(..) => ExprPrecedence::Loop,
ExprKind::Match(..) => ExprPrecedence::Match,
ExprKind::Closure(..) => ExprPrecedence::Closure,
ExprKind::Block(..) => ExprPrecedence::Block,
ExprKind::Assign(..) => ExprPrecedence::Assign,
ExprKind::AssignOp(..) => ExprPrecedence::AssignOp,
ExprKind::Field(..) => ExprPrecedence::Field,
ExprKind::Index(..) => ExprPrecedence::Index,
ExprKind::Path(..) => ExprPrecedence::Path,
ExprKind::AddrOf(..) => ExprPrecedence::AddrOf,
ExprKind::Break(..) => ExprPrecedence::Break,
ExprKind::Continue(..) => ExprPrecedence::Continue,
ExprKind::Ret(..) => ExprPrecedence::Ret,
ExprKind::InlineAsm(..) => ExprPrecedence::InlineAsm,
ExprKind::LlvmInlineAsm(..) => ExprPrecedence::InlineAsm,
ExprKind::Struct(..) => ExprPrecedence::Struct,
ExprKind::Repeat(..) => ExprPrecedence::Repeat,
ExprKind::Yield(..) => ExprPrecedence::Yield,
ExprKind::Err => ExprPrecedence::Err,
}
}
pub fn is_syntactic_place_expr(&self) -> bool {
self.is_place_expr(|_| true)
}
pub fn is_place_expr(&self, mut allow_projections_from: impl FnMut(&Self) -> bool) -> bool {
match self.kind {
ExprKind::Path(QPath::Resolved(_, ref path)) => {
matches!(path.res, Res::Local(..) | Res::Def(DefKind::Static, _) | Res::Err)
}
ExprKind::Type(ref e, _) => e.is_place_expr(allow_projections_from),
ExprKind::Unary(UnOp::UnDeref, _) => true,
ExprKind::Field(ref base, _) | ExprKind::Index(ref base, _) => {
allow_projections_from(base) || base.is_place_expr(allow_projections_from)
}
ExprKind::Path(QPath::LangItem(..)) => false,
ExprKind::Path(QPath::TypeRelative(..))
| ExprKind::Call(..)
| ExprKind::MethodCall(..)
| ExprKind::Struct(..)
| ExprKind::Tup(..)
| ExprKind::Match(..)
| ExprKind::Closure(..)
| ExprKind::Block(..)
| ExprKind::Repeat(..)
| ExprKind::Array(..)
| ExprKind::Break(..)
| ExprKind::Continue(..)
| ExprKind::Ret(..)
| ExprKind::Loop(..)
| ExprKind::Assign(..)
| ExprKind::InlineAsm(..)
| ExprKind::LlvmInlineAsm(..)
| ExprKind::AssignOp(..)
| ExprKind::Lit(_)
| ExprKind::ConstBlock(..)
| ExprKind::Unary(..)
| ExprKind::Box(..)
| ExprKind::AddrOf(..)
| ExprKind::Binary(..)
| ExprKind::Yield(..)
| ExprKind::Cast(..)
| ExprKind::DropTemps(..)
| ExprKind::Err => false,
}
}
pub fn peel_drop_temps(&self) -> &Self {
let mut expr = self;
while let ExprKind::DropTemps(inner) = &expr.kind {
expr = inner;
}
expr
}
}
pub fn is_range_literal(expr: &Expr<'_>) -> bool {
match expr.kind {
ExprKind::Struct(ref qpath, _, _) => matches!(
**qpath,
QPath::LangItem(
LangItem::Range
| LangItem::RangeTo
| LangItem::RangeFrom
| LangItem::RangeFull
| LangItem::RangeToInclusive,
_,
)
),
ExprKind::Call(ref func, _) => {
matches!(func.kind, ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, _)))
}
_ => false,
}
}
#[derive(Debug, HashStable_Generic)]
pub enum ExprKind<'hir> {
Box(&'hir Expr<'hir>),
ConstBlock(AnonConst),
Array(&'hir [Expr<'hir>]),
Call(&'hir Expr<'hir>, &'hir [Expr<'hir>]),
MethodCall(&'hir PathSegment<'hir>, Span, &'hir [Expr<'hir>], Span),
Tup(&'hir [Expr<'hir>]),
Binary(BinOp, &'hir Expr<'hir>, &'hir Expr<'hir>),
Unary(UnOp, &'hir Expr<'hir>),
Lit(Lit),
Cast(&'hir Expr<'hir>, &'hir Ty<'hir>),
Type(&'hir Expr<'hir>, &'hir Ty<'hir>),
DropTemps(&'hir Expr<'hir>),
Loop(&'hir Block<'hir>, Option<Label>, LoopSource),
Match(&'hir Expr<'hir>, &'hir [Arm<'hir>], MatchSource),
Closure(CaptureBy, &'hir FnDecl<'hir>, BodyId, Span, Option<Movability>),
Block(&'hir Block<'hir>, Option<Label>),
Assign(&'hir Expr<'hir>, &'hir Expr<'hir>, Span),
AssignOp(BinOp, &'hir Expr<'hir>, &'hir Expr<'hir>),
Field(&'hir Expr<'hir>, Ident),
Index(&'hir Expr<'hir>, &'hir Expr<'hir>),
Path(QPath<'hir>),
AddrOf(BorrowKind, Mutability, &'hir Expr<'hir>),
Break(Destination, Option<&'hir Expr<'hir>>),
Continue(Destination),
Ret(Option<&'hir Expr<'hir>>),
InlineAsm(&'hir InlineAsm<'hir>),
LlvmInlineAsm(&'hir LlvmInlineAsm<'hir>),
Struct(&'hir QPath<'hir>, &'hir [Field<'hir>], Option<&'hir Expr<'hir>>),
Repeat(&'hir Expr<'hir>, AnonConst),
Yield(&'hir Expr<'hir>, YieldSource),
Err,
}
#[derive(Debug, HashStable_Generic)]
pub enum QPath<'hir> {
Resolved(Option<&'hir Ty<'hir>>, &'hir Path<'hir>),
TypeRelative(&'hir Ty<'hir>, &'hir PathSegment<'hir>),
LangItem(LangItem, Span),
}
impl<'hir> QPath<'hir> {
pub fn span(&self) -> Span {
match *self {
QPath::Resolved(_, path) => path.span,
QPath::TypeRelative(_, ps) => ps.ident.span,
QPath::LangItem(_, span) => span,
}
}
pub fn qself_span(&self) -> Span {
match *self {
QPath::Resolved(_, path) => path.span,
QPath::TypeRelative(qself, _) => qself.span,
QPath::LangItem(_, span) => span,
}
}
pub fn last_segment_span(&self) -> Span {
match *self {
QPath::Resolved(_, path) => path.segments.last().unwrap().ident.span,
QPath::TypeRelative(_, segment) => segment.ident.span,
QPath::LangItem(_, span) => span,
}
}
}
#[derive(Copy, Clone, Encodable, Debug, HashStable_Generic)]
pub enum LocalSource {
Normal,
ForLoopDesugar,
AsyncFn,
AwaitDesugar,
AssignDesugar(Span),
}
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Hash, Debug)]
#[derive(HashStable_Generic)]
pub enum MatchSource {
Normal,
IfDesugar { contains_else_clause: bool },
IfLetDesugar { contains_else_clause: bool },
WhileDesugar,
WhileLetDesugar,
ForLoopDesugar,
TryDesugar,
AwaitDesugar,
}
impl MatchSource {
pub fn name(self) -> &'static str {
use MatchSource::*;
match self {
Normal => "match",
IfDesugar { .. } | IfLetDesugar { .. } => "if",
WhileDesugar | WhileLetDesugar => "while",
ForLoopDesugar => "for",
TryDesugar => "?",
AwaitDesugar => ".await",
}
}
}
#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
pub enum LoopSource {
Loop,
While,
WhileLet,
ForLoop,
}
impl LoopSource {
pub fn name(self) -> &'static str {
match self {
LoopSource::Loop => "loop",
LoopSource::While | LoopSource::WhileLet => "while",
LoopSource::ForLoop => "for",
}
}
}
#[derive(Copy, Clone, Encodable, Debug, HashStable_Generic)]
pub enum LoopIdError {
OutsideLoopScope,
UnlabeledCfInWhileCondition,
UnresolvedLabel,
}
impl fmt::Display for LoopIdError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
LoopIdError::OutsideLoopScope => "not inside loop scope",
LoopIdError::UnlabeledCfInWhileCondition => {
"unlabeled control flow (break or continue) in while condition"
}
LoopIdError::UnresolvedLabel => "label not found",
})
}
}
#[derive(Copy, Clone, Encodable, Debug, HashStable_Generic)]
pub struct Destination {
pub label: Option<Label>,
pub target_id: Result<HirId, LoopIdError>,
}
#[derive(Copy, Clone, PartialEq, Eq, Debug, Encodable, Decodable, HashStable_Generic)]
pub enum YieldSource {
Await { expr: Option<HirId> },
Yield,
}
impl YieldSource {
pub fn is_await(&self) -> bool {
match self {
YieldSource::Await { .. } => true,
YieldSource::Yield => false,
}
}
}
impl fmt::Display for YieldSource {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
YieldSource::Await { .. } => "`await`",
YieldSource::Yield => "`yield`",
})
}
}
impl From<GeneratorKind> for YieldSource {
fn from(kind: GeneratorKind) -> Self {
match kind {
GeneratorKind::Gen => Self::Yield,
GeneratorKind::Async(_) => Self::Await { expr: None },
}
}
}
#[derive(Debug, HashStable_Generic)]
pub struct MutTy<'hir> {
pub ty: &'hir Ty<'hir>,
pub mutbl: Mutability,
}
#[derive(Debug, HashStable_Generic)]
pub struct FnSig<'hir> {
pub header: FnHeader,
pub decl: &'hir FnDecl<'hir>,
pub span: Span,
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Debug)]
pub struct TraitItemId {
pub hir_id: HirId,
}
#[derive(Debug)]
pub struct TraitItem<'hir> {
pub ident: Ident,
pub hir_id: HirId,
pub attrs: &'hir [Attribute],
pub generics: Generics<'hir>,
pub kind: TraitItemKind<'hir>,
pub span: Span,
}
#[derive(Encodable, Debug, HashStable_Generic)]
pub enum TraitFn<'hir> {
Required(&'hir [Ident]),
Provided(BodyId),
}
#[derive(Debug, HashStable_Generic)]
pub enum TraitItemKind<'hir> {
Const(&'hir Ty<'hir>, Option<BodyId>),
Fn(FnSig<'hir>, TraitFn<'hir>),
Type(GenericBounds<'hir>, Option<&'hir Ty<'hir>>),
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Debug)]
pub struct ImplItemId {
pub hir_id: HirId,
}
#[derive(Debug)]
pub struct ImplItem<'hir> {
pub ident: Ident,
pub hir_id: HirId,
pub vis: Visibility<'hir>,
pub defaultness: Defaultness,
pub attrs: &'hir [Attribute],
pub generics: Generics<'hir>,
pub kind: ImplItemKind<'hir>,
pub span: Span,
}
#[derive(Debug, HashStable_Generic)]
pub enum ImplItemKind<'hir> {
Const(&'hir Ty<'hir>, BodyId),
Fn(FnSig<'hir>, BodyId),
TyAlias(&'hir Ty<'hir>),
}
impl ImplItemKind<'_> {
pub fn namespace(&self) -> Namespace {
match self {
ImplItemKind::TyAlias(..) => Namespace::TypeNS,
ImplItemKind::Const(..) | ImplItemKind::Fn(..) => Namespace::ValueNS,
}
}
}
pub const FN_OUTPUT_NAME: Symbol = sym::Output;
#[derive(Debug, HashStable_Generic)]
pub struct TypeBinding<'hir> {
pub hir_id: HirId,
#[stable_hasher(project(name))]
pub ident: Ident,
pub kind: TypeBindingKind<'hir>,
pub span: Span,
}
#[derive(Debug, HashStable_Generic)]
pub enum TypeBindingKind<'hir> {
Constraint { bounds: &'hir [GenericBound<'hir>] },
Equality { ty: &'hir Ty<'hir> },
}
impl TypeBinding<'_> {
pub fn ty(&self) -> &Ty<'_> {
match self.kind {
TypeBindingKind::Equality { ref ty } => ty,
_ => panic!("expected equality type binding for parenthesized generic args"),
}
}
}
#[derive(Debug)]
pub struct Ty<'hir> {
pub hir_id: HirId,
pub kind: TyKind<'hir>,
pub span: Span,
}
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
#[derive(HashStable_Generic)]
pub enum PrimTy {
Int(IntTy),
Uint(UintTy),
Float(FloatTy),
Str,
Bool,
Char,
}
impl PrimTy {
pub fn name_str(self) -> &'static str {
match self {
PrimTy::Int(i) => i.name_str(),
PrimTy::Uint(u) => u.name_str(),
PrimTy::Float(f) => f.name_str(),
PrimTy::Str => "str",
PrimTy::Bool => "bool",
PrimTy::Char => "char",
}
}
pub fn name(self) -> Symbol {
match self {
PrimTy::Int(i) => i.name(),
PrimTy::Uint(u) => u.name(),
PrimTy::Float(f) => f.name(),
PrimTy::Str => sym::str,
PrimTy::Bool => sym::bool,
PrimTy::Char => sym::char,
}
}
}
#[derive(Debug, HashStable_Generic)]
pub struct BareFnTy<'hir> {
pub unsafety: Unsafety,
pub abi: Abi,
pub generic_params: &'hir [GenericParam<'hir>],
pub decl: &'hir FnDecl<'hir>,
pub param_names: &'hir [Ident],
}
#[derive(Debug, HashStable_Generic)]
pub struct OpaqueTy<'hir> {
pub generics: Generics<'hir>,
pub bounds: GenericBounds<'hir>,
pub impl_trait_fn: Option<DefId>,
pub origin: OpaqueTyOrigin,
}
#[derive(Copy, Clone, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum OpaqueTyOrigin {
FnReturn,
AsyncFn,
Binding,
Misc,
}
#[derive(Debug, HashStable_Generic)]
pub enum TyKind<'hir> {
Slice(&'hir Ty<'hir>),
Array(&'hir Ty<'hir>, AnonConst),
Ptr(MutTy<'hir>),
Rptr(Lifetime, MutTy<'hir>),
BareFn(&'hir BareFnTy<'hir>),
Never,
Tup(&'hir [Ty<'hir>]),
Path(QPath<'hir>),
OpaqueDef(ItemId, &'hir [GenericArg<'hir>]),
TraitObject(&'hir [PolyTraitRef<'hir>], Lifetime),
Typeof(AnonConst),
Infer,
Err,
}
#[derive(Debug, HashStable_Generic)]
pub enum InlineAsmOperand<'hir> {
In {
reg: InlineAsmRegOrRegClass,
expr: Expr<'hir>,
},
Out {
reg: InlineAsmRegOrRegClass,
late: bool,
expr: Option<Expr<'hir>>,
},
InOut {
reg: InlineAsmRegOrRegClass,
late: bool,
expr: Expr<'hir>,
},
SplitInOut {
reg: InlineAsmRegOrRegClass,
late: bool,
in_expr: Expr<'hir>,
out_expr: Option<Expr<'hir>>,
},
Const {
expr: Expr<'hir>,
},
Sym {
expr: Expr<'hir>,
},
}
impl<'hir> InlineAsmOperand<'hir> {
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 { .. } => None,
}
}
}
#[derive(Debug, HashStable_Generic)]
pub struct InlineAsm<'hir> {
pub template: &'hir [InlineAsmTemplatePiece],
pub operands: &'hir [InlineAsmOperand<'hir>],
pub options: InlineAsmOptions,
pub line_spans: &'hir [Span],
}
#[derive(Copy, Clone, Encodable, Decodable, Debug, HashStable_Generic, PartialEq)]
pub struct LlvmInlineAsmOutput {
pub constraint: Symbol,
pub is_rw: bool,
pub is_indirect: bool,
pub span: Span,
}
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic, PartialEq)]
pub struct LlvmInlineAsmInner {
pub asm: Symbol,
pub asm_str_style: StrStyle,
pub outputs: Vec<LlvmInlineAsmOutput>,
pub inputs: Vec<Symbol>,
pub clobbers: Vec<Symbol>,
pub volatile: bool,
pub alignstack: bool,
pub dialect: LlvmAsmDialect,
}
#[derive(Debug, HashStable_Generic)]
pub struct LlvmInlineAsm<'hir> {
pub inner: LlvmInlineAsmInner,
pub outputs_exprs: &'hir [Expr<'hir>],
pub inputs_exprs: &'hir [Expr<'hir>],
}
#[derive(Debug, HashStable_Generic)]
pub struct Param<'hir> {
pub attrs: &'hir [Attribute],
pub hir_id: HirId,
pub pat: &'hir Pat<'hir>,
pub ty_span: Span,
pub span: Span,
}
#[derive(Debug, HashStable_Generic)]
pub struct FnDecl<'hir> {
pub inputs: &'hir [Ty<'hir>],
pub output: FnRetTy<'hir>,
pub c_variadic: bool,
pub implicit_self: ImplicitSelfKind,
}
#[derive(Copy, Clone, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum ImplicitSelfKind {
Imm,
Mut,
ImmRef,
MutRef,
None,
}
impl ImplicitSelfKind {
pub fn has_implicit_self(&self) -> bool {
!matches!(*self, ImplicitSelfKind::None)
}
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable, Debug)]
#[derive(HashStable_Generic)]
pub enum IsAsync {
Async,
NotAsync,
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Encodable, Decodable, HashStable_Generic)]
pub enum Defaultness {
Default { has_value: bool },
Final,
}
impl Defaultness {
pub fn has_value(&self) -> bool {
match *self {
Defaultness::Default { has_value } => has_value,
Defaultness::Final => true,
}
}
pub fn is_final(&self) -> bool {
*self == Defaultness::Final
}
pub fn is_default(&self) -> bool {
matches!(*self, Defaultness::Default { .. })
}
}
#[derive(Debug, HashStable_Generic)]
pub enum FnRetTy<'hir> {
DefaultReturn(Span),
Return(&'hir Ty<'hir>),
}
impl FnRetTy<'_> {
pub fn span(&self) -> Span {
match *self {
Self::DefaultReturn(span) => span,
Self::Return(ref ty) => ty.span,
}
}
}
#[derive(Encodable, Debug)]
pub struct Mod<'hir> {
pub inner: Span,
pub item_ids: &'hir [ItemId],
}
#[derive(Debug, HashStable_Generic)]
pub struct ForeignMod<'hir> {
pub abi: Abi,
pub items: &'hir [ForeignItem<'hir>],
}
#[derive(Encodable, Debug, HashStable_Generic)]
pub struct GlobalAsm {
pub asm: Symbol,
}
#[derive(Debug, HashStable_Generic)]
pub struct EnumDef<'hir> {
pub variants: &'hir [Variant<'hir>],
}
#[derive(Debug, HashStable_Generic)]
pub struct Variant<'hir> {
#[stable_hasher(project(name))]
pub ident: Ident,
pub attrs: &'hir [Attribute],
pub id: HirId,
pub data: VariantData<'hir>,
pub disr_expr: Option<AnonConst>,
pub span: Span,
}
#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
pub enum UseKind {
Single,
Glob,
ListStem,
}
#[derive(Debug, HashStable_Generic)]
pub struct TraitRef<'hir> {
pub path: &'hir Path<'hir>,
#[stable_hasher(ignore)]
pub hir_ref_id: HirId,
}
impl TraitRef<'_> {
pub fn trait_def_id(&self) -> Option<DefId> {
match self.path.res {
Res::Def(DefKind::Trait | DefKind::TraitAlias, did) => Some(did),
Res::Err => None,
_ => unreachable!(),
}
}
}
#[derive(Debug, HashStable_Generic)]
pub struct PolyTraitRef<'hir> {
pub bound_generic_params: &'hir [GenericParam<'hir>],
pub trait_ref: TraitRef<'hir>,
pub span: Span,
}
pub type Visibility<'hir> = Spanned<VisibilityKind<'hir>>;
#[derive(Debug)]
pub enum VisibilityKind<'hir> {
Public,
Crate(CrateSugar),
Restricted { path: &'hir Path<'hir>, hir_id: HirId },
Inherited,
}
impl VisibilityKind<'_> {
pub fn is_pub(&self) -> bool {
matches!(*self, VisibilityKind::Public)
}
pub fn is_pub_restricted(&self) -> bool {
match *self {
VisibilityKind::Public | VisibilityKind::Inherited => false,
VisibilityKind::Crate(..) | VisibilityKind::Restricted { .. } => true,
}
}
}
#[derive(Debug, HashStable_Generic)]
pub struct StructField<'hir> {
pub span: Span,
#[stable_hasher(project(name))]
pub ident: Ident,
pub vis: Visibility<'hir>,
pub hir_id: HirId,
pub ty: &'hir Ty<'hir>,
pub attrs: &'hir [Attribute],
}
impl StructField<'_> {
pub fn is_positional(&self) -> bool {
let first = self.ident.as_str().as_bytes()[0];
first >= b'0' && first <= b'9'
}
}
#[derive(Debug, HashStable_Generic)]
pub enum VariantData<'hir> {
Struct(&'hir [StructField<'hir>], bool),
Tuple(&'hir [StructField<'hir>], HirId),
Unit(HirId),
}
impl VariantData<'hir> {
pub fn fields(&self) -> &'hir [StructField<'hir>] {
match *self {
VariantData::Struct(ref fields, ..) | VariantData::Tuple(ref fields, ..) => fields,
_ => &[],
}
}
pub fn ctor_hir_id(&self) -> Option<HirId> {
match *self {
VariantData::Struct(_, _) => None,
VariantData::Tuple(_, hir_id) | VariantData::Unit(hir_id) => Some(hir_id),
}
}
}
#[derive(Copy, Clone, Encodable, Debug)]
pub struct ItemId {
pub id: HirId,
}
#[derive(Debug)]
pub struct Item<'hir> {
pub ident: Ident,
pub hir_id: HirId,
pub attrs: &'hir [Attribute],
pub kind: ItemKind<'hir>,
pub vis: Visibility<'hir>,
pub span: Span,
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[derive(Encodable, Decodable, HashStable_Generic)]
pub enum Unsafety {
Unsafe,
Normal,
}
impl Unsafety {
pub fn prefix_str(&self) -> &'static str {
match self {
Self::Unsafe => "unsafe ",
Self::Normal => "",
}
}
}
impl fmt::Display for Unsafety {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match *self {
Self::Unsafe => "unsafe",
Self::Normal => "normal",
})
}
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[derive(Encodable, Decodable, HashStable_Generic)]
pub enum Constness {
Const,
NotConst,
}
#[derive(Copy, Clone, Encodable, Debug, HashStable_Generic)]
pub struct FnHeader {
pub unsafety: Unsafety,
pub constness: Constness,
pub asyncness: IsAsync,
pub abi: Abi,
}
impl FnHeader {
pub fn is_const(&self) -> bool {
matches!(&self.constness, Constness::Const)
}
}
#[derive(Debug, HashStable_Generic)]
pub enum ItemKind<'hir> {
ExternCrate(Option<Symbol>),
Use(&'hir Path<'hir>, UseKind),
Static(&'hir Ty<'hir>, Mutability, BodyId),
Const(&'hir Ty<'hir>, BodyId),
Fn(FnSig<'hir>, Generics<'hir>, BodyId),
Mod(Mod<'hir>),
ForeignMod(ForeignMod<'hir>),
GlobalAsm(&'hir GlobalAsm),
TyAlias(&'hir Ty<'hir>, Generics<'hir>),
OpaqueTy(OpaqueTy<'hir>),
Enum(EnumDef<'hir>, Generics<'hir>),
Struct(VariantData<'hir>, Generics<'hir>),
Union(VariantData<'hir>, Generics<'hir>),
Trait(IsAuto, Unsafety, Generics<'hir>, GenericBounds<'hir>, &'hir [TraitItemRef]),
TraitAlias(Generics<'hir>, GenericBounds<'hir>),
Impl {
unsafety: Unsafety,
polarity: ImplPolarity,
defaultness: Defaultness,
defaultness_span: Option<Span>,
constness: Constness,
generics: Generics<'hir>,
of_trait: Option<TraitRef<'hir>>,
self_ty: &'hir Ty<'hir>,
items: &'hir [ImplItemRef<'hir>],
},
}
impl ItemKind<'_> {
pub fn generics(&self) -> Option<&Generics<'_>> {
Some(match *self {
ItemKind::Fn(_, ref generics, _)
| ItemKind::TyAlias(_, ref generics)
| ItemKind::OpaqueTy(OpaqueTy { ref generics, impl_trait_fn: None, .. })
| ItemKind::Enum(_, ref generics)
| ItemKind::Struct(_, ref generics)
| ItemKind::Union(_, ref generics)
| ItemKind::Trait(_, _, ref generics, _, _)
| ItemKind::Impl { ref generics, .. } => generics,
_ => return None,
})
}
}
#[derive(Encodable, Debug, HashStable_Generic)]
pub struct TraitItemRef {
pub id: TraitItemId,
#[stable_hasher(project(name))]
pub ident: Ident,
pub kind: AssocItemKind,
pub span: Span,
pub defaultness: Defaultness,
}
#[derive(Debug, HashStable_Generic)]
pub struct ImplItemRef<'hir> {
pub id: ImplItemId,
#[stable_hasher(project(name))]
pub ident: Ident,
pub kind: AssocItemKind,
pub span: Span,
pub vis: Visibility<'hir>,
pub defaultness: Defaultness,
}
#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
pub enum AssocItemKind {
Const,
Fn { has_self: bool },
Type,
}
#[derive(Debug, HashStable_Generic)]
pub struct ForeignItem<'hir> {
#[stable_hasher(project(name))]
pub ident: Ident,
pub attrs: &'hir [Attribute],
pub kind: ForeignItemKind<'hir>,
pub hir_id: HirId,
pub span: Span,
pub vis: Visibility<'hir>,
}
#[derive(Debug, HashStable_Generic)]
pub enum ForeignItemKind<'hir> {
Fn(&'hir FnDecl<'hir>, &'hir [Ident], Generics<'hir>),
Static(&'hir Ty<'hir>, Mutability),
Type,
}
#[derive(Debug, Copy, Clone, Encodable, HashStable_Generic)]
pub struct Upvar {
pub span: Span,
}
#[derive(Encodable, Decodable, Clone, Debug)]
pub struct TraitCandidate {
pub def_id: DefId,
pub import_ids: SmallVec<[LocalDefId; 1]>,
}
#[derive(Copy, Clone, Debug, HashStable_Generic)]
pub enum Node<'hir> {
Param(&'hir Param<'hir>),
Item(&'hir Item<'hir>),
ForeignItem(&'hir ForeignItem<'hir>),
TraitItem(&'hir TraitItem<'hir>),
ImplItem(&'hir ImplItem<'hir>),
Variant(&'hir Variant<'hir>),
Field(&'hir StructField<'hir>),
AnonConst(&'hir AnonConst),
Expr(&'hir Expr<'hir>),
Stmt(&'hir Stmt<'hir>),
PathSegment(&'hir PathSegment<'hir>),
Ty(&'hir Ty<'hir>),
TraitRef(&'hir TraitRef<'hir>),
Binding(&'hir Pat<'hir>),
Pat(&'hir Pat<'hir>),
Arm(&'hir Arm<'hir>),
Block(&'hir Block<'hir>),
Local(&'hir Local<'hir>),
MacroDef(&'hir MacroDef<'hir>),
Ctor(&'hir VariantData<'hir>),
Lifetime(&'hir Lifetime),
GenericParam(&'hir GenericParam<'hir>),
Visibility(&'hir Visibility<'hir>),
Crate(&'hir CrateItem<'hir>),
}
impl<'hir> Node<'hir> {
pub fn ident(&self) -> Option<Ident> {
match self {
Node::TraitItem(TraitItem { ident, .. })
| Node::ImplItem(ImplItem { ident, .. })
| Node::ForeignItem(ForeignItem { ident, .. })
| Node::Field(StructField { ident, .. })
| Node::Variant(Variant { ident, .. })
| Node::MacroDef(MacroDef { ident, .. })
| Node::Item(Item { ident, .. }) => Some(*ident),
_ => None,
}
}
pub fn fn_decl(&self) -> Option<&FnDecl<'hir>> {
match self {
Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
| Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
| Node::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) => Some(fn_sig.decl),
Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_decl, _, _), .. }) => {
Some(fn_decl)
}
_ => None,
}
}
pub fn body_id(&self) -> Option<BodyId> {
match self {
Node::TraitItem(TraitItem {
kind: TraitItemKind::Fn(_, TraitFn::Provided(body_id)),
..
})
| Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(_, body_id), .. })
| Node::Item(Item { kind: ItemKind::Fn(.., body_id), .. }) => Some(*body_id),
_ => None,
}
}
pub fn generics(&self) -> Option<&'hir Generics<'hir>> {
match self {
Node::TraitItem(TraitItem { generics, .. })
| Node::ImplItem(ImplItem { generics, .. }) => Some(generics),
Node::Item(item) => item.kind.generics(),
_ => None,
}
}
pub fn hir_id(&self) -> Option<HirId> {
match self {
Node::Item(Item { hir_id, .. })
| Node::ForeignItem(ForeignItem { hir_id, .. })
| Node::TraitItem(TraitItem { hir_id, .. })
| Node::ImplItem(ImplItem { hir_id, .. })
| Node::Field(StructField { hir_id, .. })
| Node::AnonConst(AnonConst { hir_id, .. })
| Node::Expr(Expr { hir_id, .. })
| Node::Stmt(Stmt { hir_id, .. })
| Node::Ty(Ty { hir_id, .. })
| Node::Binding(Pat { hir_id, .. })
| Node::Pat(Pat { hir_id, .. })
| Node::Arm(Arm { hir_id, .. })
| Node::Block(Block { hir_id, .. })
| Node::Local(Local { hir_id, .. })
| Node::MacroDef(MacroDef { hir_id, .. })
| Node::Lifetime(Lifetime { hir_id, .. })
| Node::Param(Param { hir_id, .. })
| Node::GenericParam(GenericParam { hir_id, .. }) => Some(*hir_id),
Node::TraitRef(TraitRef { hir_ref_id, .. }) => Some(*hir_ref_id),
Node::PathSegment(PathSegment { hir_id, .. }) => *hir_id,
Node::Variant(Variant { id, .. }) => Some(*id),
Node::Ctor(variant) => variant.ctor_hir_id(),
Node::Crate(_) | Node::Visibility(_) => None,
}
}
}