Skip to content

Add and use expect methods to hir. #107125

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
343 changes: 340 additions & 3 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2263,7 +2263,7 @@ pub struct TraitItem<'hir> {
pub defaultness: Defaultness,
}

impl TraitItem<'_> {
impl<'hir> TraitItem<'hir> {
#[inline]
pub fn hir_id(&self) -> HirId {
// Items are always HIR owners.
Expand All @@ -2273,6 +2273,27 @@ impl TraitItem<'_> {
pub fn trait_item_id(&self) -> TraitItemId {
TraitItemId { owner_id: self.owner_id }
}

/// Expect an [`TraitItemKind::Const`] or panic.
#[track_caller]
pub fn expect_const(&self) -> (&'hir Ty<'hir>, Option<BodyId>) {
let TraitItemKind::Const(ty, body) = self.kind else { unreachable!() };
(ty, body)
}

/// Expect an [`TraitItemKind::Fn`] or panic.
#[track_caller]
pub fn expect_fn(&self) -> (&FnSig<'hir>, &TraitFn<'hir>) {
let TraitItemKind::Fn(ty, trfn) = &self.kind else { unreachable!() };
(ty, trfn)
}

/// Expect an [`TraitItemKind::ExternCrate`] or panic.
#[track_caller]
pub fn expect_type(&self) -> (GenericBounds<'hir>, Option<&'hir Ty<'hir>>) {
let TraitItemKind::Type(bounds, ty) = self.kind else { unreachable!() };
(bounds, ty)
}
}

/// Represents a trait method's body (or just argument names).
Expand Down Expand Up @@ -2325,7 +2346,7 @@ pub struct ImplItem<'hir> {
pub vis_span: Span,
}

impl ImplItem<'_> {
impl<'hir> ImplItem<'hir> {
#[inline]
pub fn hir_id(&self) -> HirId {
// Items are always HIR owners.
Expand All @@ -2335,6 +2356,27 @@ impl ImplItem<'_> {
pub fn impl_item_id(&self) -> ImplItemId {
ImplItemId { owner_id: self.owner_id }
}

/// Expect an [`ImplItemKind::Const`] or panic.
#[track_caller]
pub fn expect_const(&self) -> (&'hir Ty<'hir>, BodyId) {
let ImplItemKind::Const(ty, body) = self.kind else { unreachable!() };
(ty, body)
}

/// Expect an [`ImplItemKind::Fn`] or panic.
#[track_caller]
pub fn expect_fn(&self) -> (&FnSig<'hir>, BodyId) {
let ImplItemKind::Fn(ty, body) = &self.kind else { unreachable!() };
(ty, *body)
}

/// Expect an [`ImplItemKind::ExternCrate`] or panic.
#[track_caller]
pub fn expect_type(&self) -> &'hir Ty<'hir> {
let ImplItemKind::Type(ty) = self.kind else { unreachable!() };
ty
}
}

/// Represents various kinds of content within an `impl`.
Expand Down Expand Up @@ -2995,7 +3037,7 @@ pub struct Item<'hir> {
pub vis_span: Span,
}

impl Item<'_> {
impl<'hir> Item<'hir> {
#[inline]
pub fn hir_id(&self) -> HirId {
// Items are always HIR owners.
Expand All @@ -3005,6 +3047,127 @@ impl Item<'_> {
pub fn item_id(&self) -> ItemId {
ItemId { owner_id: self.owner_id }
}

/// Expect an [`ItemKind::ExternCrate`] or panic.
#[track_caller]
pub fn expect_extern_crate(&self) -> Option<Symbol> {
let ItemKind::ExternCrate(s) = self.kind else { unreachable!() };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these should probably be bug!s

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

even more ideally, they'd say "expected an extern crate, got {:?}" or something -- makes it much easier at a glance (or a stack trace submitted on an issue) to know what's up

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think bug!s are available at this point in the crate graph :(

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nooooooo

ok well can u at least improve the panic message?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I'll improve the messages (not today tho, I'm tired and tired)

s
}

/// Expect an [`ItemKind::Use`] or panic.
#[track_caller]
pub fn expect_use(&self) -> (&'hir UsePath<'hir>, UseKind) {
let ItemKind::Use(p, uk) = self.kind else { unreachable!() };
(p, uk)
}

/// Expect an [`ItemKind::Static`] or panic.
#[track_caller]
pub fn expect_static(&self) -> (&'hir Ty<'hir>, Mutability, BodyId) {
let ItemKind::Static(ty, mutbl, body) = self.kind else { unreachable!() };
(ty, mutbl, body)
}
/// Expect an [`ItemKind::Const`] or panic.
#[track_caller]
pub fn expect_const(&self) -> (&'hir Ty<'hir>, BodyId) {
let ItemKind::Const(ty, body) = self.kind else { unreachable!() };
(ty, body)
}
/// Expect an [`ItemKind::Fn`] or panic.
#[track_caller]
pub fn expect_fn(&self) -> (&FnSig<'hir>, &'hir Generics<'hir>, BodyId) {
let ItemKind::Fn(sig, gen, body) = &self.kind else { unreachable!() };
(sig, gen, *body)
}

/// Expect an [`ItemKind::Macro`] or panic.
#[track_caller]
pub fn expect_macro(&self) -> (&ast::MacroDef, MacroKind) {
let ItemKind::Macro(def, mk) = &self.kind else { unreachable!() };
(def, *mk)
}

/// Expect an [`ItemKind::Mod`] or panic.
#[track_caller]
pub fn expect_mod(&self) -> &'hir Mod<'hir> {
let ItemKind::Mod(m) = self.kind else { unreachable!() };
m
}

/// Expect an [`ItemKind::ForeignMod`] or panic.
#[track_caller]
pub fn expect_foreign_mod(&self) -> (Abi, &'hir [ForeignItemRef]) {
let ItemKind::ForeignMod { abi, items } = self.kind else { unreachable!() };
(abi, items)
}

/// Expect an [`ItemKind::GlobalAsm`] or panic.
#[track_caller]
pub fn expect_global_asm(&self) -> &'hir InlineAsm<'hir> {
let ItemKind::GlobalAsm(asm) = self.kind else { unreachable!() };
asm
}

/// Expect an [`ItemKind::TyAlias`] or panic.
#[track_caller]
pub fn expect_ty_alias(&self) -> (&'hir Ty<'hir>, &'hir Generics<'hir>) {
let ItemKind::TyAlias(ty, gen) = self.kind else { unreachable!() };
(ty, gen)
}

/// An opaque `impl Trait` type alias, e.g., `type Foo = impl Bar;`.
/// Expect an [`ItemKind::OpaqueTy`] or panic.
#[track_caller]
pub fn expect_opaque_ty(&self) -> &OpaqueTy<'hir> {
let ItemKind::OpaqueTy(ty) = &self.kind else { unreachable!() };
ty
}

/// Expect an [`ItemKind::Enum`] or panic.
#[track_caller]
pub fn expect_enum(&self) -> (&EnumDef<'hir>, &'hir Generics<'hir>) {
let ItemKind::Enum(def, gen) = &self.kind else { unreachable!() };
(def, gen)
}

/// Expect an [`ItemKind::Struct`] or panic.
#[track_caller]
pub fn expect_struct(&self) -> (&VariantData<'hir>, &'hir Generics<'hir>) {
let ItemKind::Struct(data, gen) = &self.kind else { unreachable!() };
(data, gen)
}

/// A union definition, e.g., `union Foo<A, B> {x: A, y: B}`.
/// Expect an [`ItemKind::Union`] or panic.
#[track_caller]
pub fn expect_union(&self) -> (&VariantData<'hir>, &'hir Generics<'hir>) {
let ItemKind::Union(data, gen) = &self.kind else { unreachable!() };
(data, gen)
}

/// Expect an [`ItemKind::Trait`] or panic.
#[track_caller]
pub fn expect_trait(
self,
) -> (IsAuto, Unsafety, &'hir Generics<'hir>, GenericBounds<'hir>, &'hir [TraitItemRef]) {
let ItemKind::Trait(is_auto, unsafety, gen, bounds, items) = self.kind else { unreachable!() };
(is_auto, unsafety, gen, bounds, items)
}

/// Expect an [`ItemKind::TraitAlias`] or panic.
#[track_caller]
pub fn expect_trait_alias(&self) -> (&'hir Generics<'hir>, GenericBounds<'hir>) {
let ItemKind::TraitAlias(gen, bounds) = self.kind else { unreachable!() };
(gen, bounds)
}

/// Expect an [`ItemKind::Impl`] or panic.
#[track_caller]
pub fn expect_impl(&self) -> &'hir Impl<'hir> {
let ItemKind::Impl(imp) = self.kind else { unreachable!() };
imp
}
}

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
Expand Down Expand Up @@ -3590,6 +3753,180 @@ impl<'hir> Node<'hir> {
pub fn tuple_fields(&self) -> Option<&'hir [FieldDef<'hir>]> {
if let Node::Ctor(&VariantData::Tuple(fields, _, _)) = self { Some(fields) } else { None }
}

/// Expect a [`Node::Param`] or panic.
#[track_caller]
pub fn expect_param(self) -> &'hir Param<'hir> {
let Node::Param(this) = self else { unreachable!() };
this
}

/// Expect a [`Node::Item`] or panic.
#[track_caller]
pub fn expect_item(self) -> &'hir Item<'hir> {
let Node::Item(this) = self else { unreachable!() };
this
}

/// Expect a [`Node::ForeignItem`] or panic.
#[track_caller]
pub fn expect_foreign_item(self) -> &'hir ForeignItem<'hir> {
let Node::ForeignItem(this) = self else { unreachable!() };
this
}

/// Expect a [`Node::TraitItem`] or panic.
#[track_caller]
pub fn expect_trait_item(self) -> &'hir TraitItem<'hir> {
let Node::TraitItem(this) = self else { unreachable!() };
this
}

/// Expect a [`Node::ImplItem`] or panic.
#[track_caller]
pub fn expect_impl_item(self) -> &'hir ImplItem<'hir> {
let Node::ImplItem(this) = self else { unreachable!() };
this
}

/// Expect a [`Node::Variant`] or panic.
#[track_caller]
pub fn expect_variant(self) -> &'hir Variant<'hir> {
let Node::Variant(this) = self else { unreachable!() };
this
}

/// Expect a [`Node::Field`] or panic.
#[track_caller]
pub fn expect_field(self) -> &'hir FieldDef<'hir> {
let Node::Field(this) = self else { unreachable!() };
this
}

/// Expect a [`Node::AnonConst`] or panic.
#[track_caller]
pub fn expect_anon_const(self) -> &'hir AnonConst {
let Node::AnonConst(this) = self else { unreachable!() };
this
}

/// Expect a [`Node::Expr`] or panic.
#[track_caller]
pub fn expect_expr(self) -> &'hir Expr<'hir> {
let Node::Expr(this) = self else { unreachable!() };
this
}
/// Expect a [`Node::ExprField`] or panic.
#[track_caller]
pub fn expect_expr_field(self) -> &'hir ExprField<'hir> {
let Node::ExprField(this) = self else { unreachable!() };
this
}

/// Expect a [`Node::Stmt`] or panic.
#[track_caller]
pub fn expect_stmt(self) -> &'hir Stmt<'hir> {
let Node::Stmt(this) = self else { unreachable!() };
this
}

/// Expect a [`Node::PathSegment`] or panic.
#[track_caller]
pub fn expect_path_segment(self) -> &'hir PathSegment<'hir> {
let Node::PathSegment(this) = self else { unreachable!() };
this
}

/// Expect a [`Node::Ty`] or panic.
#[track_caller]
pub fn expect_ty(self) -> &'hir Ty<'hir> {
let Node::Ty(this) = self else { unreachable!() };
this
}

/// Expect a [`Node::TypeBinding`] or panic.
#[track_caller]
pub fn expect_type_binding(self) -> &'hir TypeBinding<'hir> {
let Node::TypeBinding(this) = self else { unreachable!() };
this
}

/// Expect a [`Node::TraitRef`] or panic.
#[track_caller]
pub fn expect_trait_ref(self) -> &'hir TraitRef<'hir> {
let Node::TraitRef(this) = self else { unreachable!() };
this
}

/// Expect a [`Node::Pat`] or panic.
#[track_caller]
pub fn expect_pat(self) -> &'hir Pat<'hir> {
let Node::Pat(this) = self else { unreachable!() };
this
}

/// Expect a [`Node::PatField`] or panic.
#[track_caller]
pub fn expect_pat_field(self) -> &'hir PatField<'hir> {
let Node::PatField(this) = self else { unreachable!() };
this
}

/// Expect a [`Node::Arm`] or panic.
#[track_caller]
pub fn expect_arm(self) -> &'hir Arm<'hir> {
let Node::Arm(this) = self else { unreachable!() };
this
}

/// Expect a [`Node::Block`] or panic.
#[track_caller]
pub fn expect_block(self) -> &'hir Block<'hir> {
let Node::Block(this) = self else { unreachable!() };
this
}

/// Expect a [`Node::Local`] or panic.
#[track_caller]
pub fn expect_local(self) -> &'hir Local<'hir> {
let Node::Local(this) = self else { unreachable!() };
this
}

/// Expect a [`Node::Ctor`] or panic.
#[track_caller]
pub fn expect_ctor(self) -> &'hir VariantData<'hir> {
let Node::Ctor(this) = self else { unreachable!() };
this
}

/// Expect a [`Node::Lifetime`] or panic.
#[track_caller]
pub fn expect_lifetime(self) -> &'hir Lifetime {
let Node::Lifetime(this) = self else { unreachable!() };
this
}

/// Expect a [`Node::GenericParam`] or panic.
#[track_caller]
pub fn expect_generic_param(self) -> &'hir GenericParam<'hir> {
let Node::GenericParam(this) = self else { unreachable!() };
this
}

/// Expect a [`Node::Crate`] or panic.
#[track_caller]
pub fn expect_crate(self) -> &'hir Mod<'hir> {
let Node::Crate(this) = self else { unreachable!() };
this
}

/// Expect a [`Node::Infer`] or panic.
#[track_caller]
pub fn expect_infer(self) -> &'hir InferArg {
let Node::Infer(this) = self else { unreachable!() };
this
}
}

// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
Expand Down
Loading