Skip to content

Commit 3b83a5e

Browse files
committed
API: Add new Identifiable trait
1 parent e7217ca commit 3b83a5e

File tree

12 files changed

+136
-121
lines changed

12 files changed

+136
-121
lines changed

marker_adapter/src/context.rs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,12 @@
22
#![allow(clippy::needless_lifetimes)]
33

44
use marker_api::{
5-
ast::{
6-
item::{Body, ItemKind},
7-
ty::SemTyKind,
8-
BodyId, ExpnId, ExpnInfo, ExprId, FileInfo, FilePos, ItemId, Span, SpanId, SpanPos, SpanSource, SymbolId,
9-
TyDefId,
10-
},
5+
ast::{ty::SemTyKind, ExpnId, ExpnInfo, ExprId, FileInfo, FilePos, SpanId, SpanPos, SpanSource, SymbolId},
116
context::DriverCallbacks,
12-
diagnostic::{Diagnostic, EmissionNodeId},
7+
diagnostic::Diagnostic,
138
ffi::{self, FfiOption},
149
lint::{Level, Lint},
10+
prelude::*,
1511
};
1612

1713
/// ### Safety
@@ -59,7 +55,7 @@ impl<'ast> DriverContextWrapper<'ast> {
5955

6056
// False positive because `EmissionNode` are non-exhaustive
6157
#[allow(improper_ctypes_definitions)]
62-
extern "C" fn lint_level_at<'ast>(data: &'ast (), lint: &'static Lint, node: EmissionNodeId) -> Level {
58+
extern "C" fn lint_level_at<'ast>(data: &'ast (), lint: &'static Lint, node: NodeId) -> Level {
6359
unsafe { as_driver_cx(data) }.lint_level_at(lint, node)
6460
}
6561

@@ -129,7 +125,7 @@ unsafe fn as_driver_cx<'ast>(data: &'ast ()) -> &'ast dyn DriverContext<'ast> {
129125
}
130126

131127
pub trait DriverContext<'ast> {
132-
fn lint_level_at(&'ast self, lint: &'static Lint, node: EmissionNodeId) -> Level;
128+
fn lint_level_at(&'ast self, lint: &'static Lint, node: NodeId) -> Level;
133129
fn emit_diag(&'ast self, diag: &Diagnostic<'_, 'ast>);
134130

135131
fn item(&'ast self, api_id: ItemId) -> Option<ItemKind<'ast>>;

marker_api/src/ast/common/id.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ macro_rules! new_id {
3939

4040
use new_id;
4141

42+
use crate::private::Sealed;
43+
4244
new_id!(
4345
/// This ID uniquely identifies a crate during linting.
4446
pub CrateId: u32
@@ -144,3 +146,63 @@ new_id! {
144146
/// This ID uniquely identifies a statement during linting.
145147
pub StmtId: u64
146148
}
149+
150+
#[repr(C)]
151+
#[non_exhaustive]
152+
#[derive(Debug, Clone, Copy)]
153+
pub enum NodeId {
154+
Expr(ExprId),
155+
Item(ItemId),
156+
Stmt(StmtId),
157+
Body(BodyId),
158+
Field(FieldId),
159+
Variant(VariantId),
160+
}
161+
162+
macro_rules! impl_into_node_id_for {
163+
($variant:ident, $ty:ty) => {
164+
impl From<$ty> for NodeId {
165+
fn from(value: $ty) -> Self {
166+
NodeId::$variant(value)
167+
}
168+
}
169+
170+
impl From<&$ty> for NodeId {
171+
fn from(value: &$ty) -> Self {
172+
NodeId::$variant(*value)
173+
}
174+
}
175+
};
176+
}
177+
178+
impl_into_node_id_for!(Expr, ExprId);
179+
impl_into_node_id_for!(Item, ItemId);
180+
impl_into_node_id_for!(Stmt, StmtId);
181+
impl_into_node_id_for!(Body, BodyId);
182+
impl_into_node_id_for!(Field, FieldId);
183+
impl_into_node_id_for!(Variant, VariantId);
184+
185+
pub trait Identifiable: Sealed {
186+
/// Returns the [`NodeId`] of the identifiable node
187+
fn node_id(&self) -> NodeId;
188+
}
189+
190+
impl<N: Identifiable> Identifiable for &N {
191+
fn node_id(&self) -> NodeId {
192+
(*self).node_id()
193+
}
194+
}
195+
196+
macro_rules! impl_identifiable_for {
197+
($ty:ty$(, use $data_trait:path)?) => {
198+
impl<'ast> $crate::ast::Identifiable for $ty {
199+
fn node_id(&self) -> $crate::ast::NodeId {
200+
$(
201+
use $data_trait;
202+
)*
203+
self.id().into()
204+
}
205+
}
206+
};
207+
}
208+
pub(crate) use impl_identifiable_for;

marker_api/src/ast/common/span.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,8 @@ pub trait Spanned<'ast>: Sealed {
577577
fn span(&self) -> &Span<'ast>;
578578
}
579579

580+
/// This macro implements the [`Spanned`] trait for data types, that provide a
581+
/// `span()` method.
580582
macro_rules! impl_spanned_for {
581583
($ty:ty) => {
582584
impl<'ast> $crate::ast::Spanned<'ast> for $ty {

marker_api/src/ast/expr.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::{prelude::EmissionNode, private::Sealed, CtorBlocker};
22

3-
use super::{ty::SemTyKind, ExprId, Span, SpanId, Spanned};
3+
use super::{ty::SemTyKind, ExprId, Identifiable, Span, SpanId, Spanned};
44

55
use std::{fmt::Debug, marker::PhantomData};
66

@@ -27,7 +27,7 @@ pub use unstable_expr::*;
2727
///
2828
/// This trait is only meant to be implemented inside this crate. The `Sealed`
2929
/// super trait prevents external implementations.
30-
pub trait ExprData<'ast>: Debug + EmissionNode<'ast> + Spanned<'ast> + Sealed {
30+
pub trait ExprData<'ast>: Debug + EmissionNode<'ast> + Spanned<'ast> + Identifiable + Sealed {
3131
/// Returns the [`ExprId`] of this expression.
3232
fn id(&self) -> ExprId;
3333

@@ -90,9 +90,10 @@ impl<'ast> ExprKind<'ast> {
9090
impl_expr_kind_fn!(ExprKind: precedence() -> ExprPrecedence);
9191
}
9292

93-
impl Sealed for ExprKind<'_> {}
94-
crate::diagnostic::impl_emission_node_for_node!(ExprKind<'ast>);
9593
crate::ast::impl_spanned_for!(ExprKind<'ast>);
94+
crate::ast::impl_identifiable_for!(ExprKind<'ast>);
95+
impl<'ast> EmissionNode<'ast> for ExprKind<'ast> {}
96+
impl Sealed for ExprKind<'_> {}
9697

9798
#[repr(C)]
9899
#[non_exhaustive]
@@ -116,8 +117,9 @@ impl<'ast> LitExprKind<'ast> {
116117
impl_expr_kind_fn!(LitExprKind: precedence() -> ExprPrecedence);
117118
}
118119

119-
crate::diagnostic::impl_emission_node_for_node!(LitExprKind<'ast>);
120120
crate::ast::impl_spanned_for!(LitExprKind<'ast>);
121+
crate::ast::impl_identifiable_for!(LitExprKind<'ast>);
122+
impl<'ast> EmissionNode<'ast> for LitExprKind<'ast> {}
121123
impl Sealed for LitExprKind<'_> {}
122124

123125
impl<'ast> From<LitExprKind<'ast>> for ExprKind<'ast> {
@@ -332,9 +334,10 @@ macro_rules! impl_expr_data {
332334
$crate::context::with_cx(self, |cx| cx.span(self.data.span))
333335
}
334336
}
337+
impl<'ast> $crate::diagnostic::EmissionNode<'ast> for $self_ty {}
338+
$crate::ast::impl_identifiable_for!($self_ty, use $crate::ast::expr::ExprData);
335339

336340
impl<'ast> $crate::private::Sealed for $self_ty {}
337-
$crate::diagnostic::impl_emission_node_for_node!($self_ty, use super::ExprData);
338341

339342
impl<'ast> From<&'ast $self_ty> for $crate::ast::expr::ExprKind<'ast> {
340343
fn from(from: &'ast $self_ty) -> Self {

marker_api/src/ast/item.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::private::Sealed;
55
use crate::CtorBlocker;
66

77
use super::expr::ExprKind;
8-
use super::{Ident, ItemId, Span, SpanId, Spanned};
8+
use super::{Ident, Identifiable, ItemId, Span, SpanId, Spanned};
99

1010
// Item implementations
1111
mod extern_crate_item;
@@ -37,7 +37,7 @@ pub use unstable_item::*;
3737
///
3838
/// This trait is only meant to be implemented inside this crate. The `Sealed`
3939
/// super trait prevents external implementations.
40-
pub trait ItemData<'ast>: Debug + EmissionNode<'ast> + Spanned<'ast> + Sealed {
40+
pub trait ItemData<'ast>: Debug + EmissionNode<'ast> + Spanned<'ast> + Identifiable + Sealed {
4141
/// Returns the [`ItemId`] of this item. This is a unique identifier used for comparison
4242
/// and to request items from the [`AstContext`](`crate::context::AstContext`).
4343
fn id(&self) -> ItemId;
@@ -90,8 +90,9 @@ impl<'ast> ItemKind<'ast> {
9090
impl_item_type_fn!(ItemKind: attrs() -> ());
9191
}
9292

93-
crate::diagnostic::impl_emission_node_for_node!(ItemKind<'ast>);
9493
crate::ast::impl_spanned_for!(ItemKind<'ast>);
94+
crate::ast::impl_identifiable_for!(ItemKind<'ast>);
95+
impl<'ast> EmissionNode<'ast> for ItemKind<'ast> {}
9596
impl<'ast> crate::private::Sealed for ItemKind<'ast> {}
9697

9798
#[non_exhaustive]
@@ -112,8 +113,9 @@ impl<'ast> AssocItemKind<'ast> {
112113
// FIXME: Potentially add a field to the items to optionally store the owner id
113114
}
114115

115-
crate::diagnostic::impl_emission_node_for_node!(AssocItemKind<'ast>);
116116
crate::ast::impl_spanned_for!(AssocItemKind<'ast>);
117+
crate::ast::impl_identifiable_for!(AssocItemKind<'ast>);
118+
impl<'ast> EmissionNode<'ast> for AssocItemKind<'ast> {}
117119
impl<'ast> crate::private::Sealed for AssocItemKind<'ast> {}
118120

119121
impl<'ast> From<AssocItemKind<'ast>> for ItemKind<'ast> {
@@ -142,8 +144,9 @@ impl<'ast> ExternItemKind<'ast> {
142144
impl_item_type_fn!(ExternItemKind: as_item() -> ItemKind<'ast>);
143145
}
144146

145-
crate::diagnostic::impl_emission_node_for_node!(ExternItemKind<'ast>);
146147
crate::ast::impl_spanned_for!(ExternItemKind<'ast>);
148+
crate::ast::impl_identifiable_for!(ExternItemKind<'ast>);
149+
impl<'ast> EmissionNode<'ast> for ExternItemKind<'ast> {}
147150
impl<'ast> crate::private::Sealed for ExternItemKind<'ast> {}
148151

149152
impl<'ast> From<ExternItemKind<'ast>> for ItemKind<'ast> {
@@ -223,8 +226,9 @@ macro_rules! impl_item_data {
223226
}
224227
}
225228

229+
$crate::ast::impl_identifiable_for!($self_name<'ast>, use $crate::ast::item::ItemData);
230+
impl<'ast> $crate::diagnostic::EmissionNode<'ast> for $self_name<'ast> {}
226231
impl $crate::private::Sealed for $self_name<'_> {}
227-
$crate::diagnostic::impl_emission_node_for_node!($self_name<'ast>, use super::ItemData);
228232

229233
impl<'ast> From<&'ast $self_name<'ast>> for crate::ast::item::ItemKind<'ast> {
230234
fn from(value: &'ast $self_name<'ast>) -> Self {

marker_api/src/ast/item/adt_item.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::ast::ty::SynTyKind;
44
use crate::ast::{FieldId, Span, SpanId, SymbolId, VariantId};
55
use crate::context::with_cx;
66
use crate::ffi::{FfiOption, FfiSlice};
7-
use crate::prelude::Spanned;
7+
use crate::prelude::{EmissionNode, Spanned};
88

99
use super::{CommonItemData, Visibility};
1010

@@ -172,7 +172,8 @@ impl<'ast> Spanned<'ast> for EnumVariant<'ast> {
172172
}
173173
}
174174

175-
crate::diagnostic::impl_emission_node_for_node!(&EnumVariant<'ast>);
175+
crate::ast::impl_identifiable_for!(EnumVariant<'ast>);
176+
impl<'ast> EmissionNode<'ast> for EnumVariant<'ast> {}
176177
impl<'ast> crate::private::Sealed for EnumVariant<'ast> {}
177178

178179
#[cfg(feature = "driver-api")]
@@ -323,7 +324,8 @@ impl<'ast> Spanned<'ast> for Field<'ast> {
323324
}
324325
}
325326

326-
crate::diagnostic::impl_emission_node_for_node!(&Field<'ast>);
327+
crate::ast::impl_identifiable_for!(Field<'ast>);
328+
impl<'ast> EmissionNode<'ast> for Field<'ast> {}
327329
impl<'ast> crate::private::Sealed for Field<'ast> {}
328330

329331
#[cfg(feature = "driver-api")]

marker_api/src/ast/stmt.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
use std::fmt::Debug;
22
use std::marker::PhantomData;
33

4-
use crate::{ffi::FfiOption, private::Sealed};
4+
use crate::{ffi::FfiOption, prelude::EmissionNode, private::Sealed};
55

6-
use super::{expr::ExprKind, item::ItemKind, pat::PatKind, ty::SynTyKind, Span, SpanId, Spanned, StmtId};
6+
use super::{expr::ExprKind, item::ItemKind, pat::PatKind, ty::SynTyKind, Identifiable, Span, SpanId, Spanned, StmtId};
77

88
/// This trait combines methods, which all statements have in common.
99
///
1010
/// This trait is only meant to be implemented inside this crate. The `Sealed`
1111
/// super trait prevents external implementations.
12-
pub trait StmtData<'ast>: Debug + Spanned<'ast> + Sealed {
12+
pub trait StmtData<'ast>: Debug + Spanned<'ast> + Identifiable + Sealed {
1313
/// Returns the [`StmtId`] of this statement
1414
fn id(&self) -> StmtId;
1515
}
@@ -48,8 +48,9 @@ impl<'ast> StmtKind<'ast> {
4848
pub fn attrs(&self) {}
4949
}
5050

51-
crate::diagnostic::impl_emission_node_for_node!(StmtKind<'ast>);
5251
crate::ast::impl_spanned_for!(StmtKind<'ast>);
52+
crate::ast::impl_identifiable_for!(StmtKind<'ast>);
53+
impl<'ast> EmissionNode<'ast> for StmtKind<'ast> {}
5354
impl<'ast> crate::private::Sealed for StmtKind<'ast> {}
5455

5556
#[repr(C)]
@@ -82,6 +83,8 @@ macro_rules! impl_stmt_data {
8283
}
8384
}
8485

86+
$crate::ast::impl_identifiable_for!($self_ty, use StmtData);
87+
8588
impl<'ast> From<&'ast $self_ty> for $crate::ast::stmt::StmtKind<'ast> {
8689
fn from(from: &'ast $self_ty) -> Self {
8790
$crate::ast::stmt::StmtKind::$enum_name(from)
@@ -131,7 +134,7 @@ impl<'ast> LetStmt<'ast> {
131134
}
132135

133136
impl_stmt_data!(LetStmt<'ast>, Let);
134-
crate::diagnostic::impl_emission_node_for_node!(LetStmt<'ast>);
137+
impl<'ast> EmissionNode<'ast> for LetStmt<'ast> {}
135138

136139
#[repr(C)]
137140
#[derive(Debug)]
@@ -148,7 +151,7 @@ impl<'ast> ExprStmt<'ast> {
148151
}
149152

150153
impl_stmt_data!(ExprStmt<'ast>, Expr);
151-
crate::diagnostic::impl_emission_node_for_node!(ExprStmt<'ast>);
154+
impl<'ast> EmissionNode<'ast> for ExprStmt<'ast> {}
152155

153156
#[repr(C)]
154157
#[derive(Debug)]
@@ -165,4 +168,4 @@ impl<'ast> ItemStmt<'ast> {
165168
}
166169

167170
impl_stmt_data!(ItemStmt<'ast>, Item);
168-
crate::diagnostic::impl_emission_node_for_node!(ItemStmt<'ast>);
171+
impl<'ast> EmissionNode<'ast> for ItemStmt<'ast> {}

marker_api/src/context.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ use crate::{
88
ast::{
99
item::{Body, ItemKind},
1010
ty::SemTyKind,
11-
BodyId, ExpnId, ExpnInfo, ExprId, FileInfo, FilePos, ItemId, Span, SpanId, SpanPos, SpanSource, SymbolId,
12-
TyDefId,
11+
BodyId, ExpnId, ExpnInfo, ExprId, FileInfo, FilePos, Identifiable, ItemId, NodeId, Span, SpanId, SpanPos,
12+
SpanSource, SymbolId, TyDefId,
1313
},
14-
diagnostic::{Diagnostic, DiagnosticBuilder, EmissionNode, EmissionNodeId},
14+
diagnostic::{Diagnostic, DiagnosticBuilder, EmissionNode},
1515
ffi,
1616
lint::{Level, Lint, MacroReport},
1717
};
@@ -101,8 +101,8 @@ impl<'ast> AstContext<'ast> {
101101
}
102102

103103
impl<'ast> AstContext<'ast> {
104-
pub fn lint_level_at(&self, lint: &'static Lint, node: impl EmissionNode<'ast>) -> Level {
105-
self.driver.call_lint_level_at(lint, node.emission_node_id())
104+
pub fn lint_level_at(&self, lint: &'static Lint, node: impl Identifiable) -> Level {
105+
self.driver.call_lint_level_at(lint, node.node_id())
106106
}
107107

108108
/// This function is used to emit a lint.
@@ -214,7 +214,7 @@ impl<'ast> AstContext<'ast> {
214214
node: impl EmissionNode<'ast>,
215215
msg: impl Into<String>,
216216
) -> DiagnosticBuilder<'ast> {
217-
let id = node.emission_node_id();
217+
let id = node.node_id();
218218
let span = node.span();
219219
if matches!(lint.report_in_macro, MacroReport::No) && span.is_from_expansion() {
220220
return DiagnosticBuilder::new_dummy(lint, id);
@@ -335,7 +335,7 @@ struct DriverCallbacks<'ast> {
335335
// can't call them in safe Rust passing a &() pointer. This will trigger UB.
336336

337337
// Lint emission and information
338-
pub lint_level_at: extern "C" fn(&'ast (), &'static Lint, EmissionNodeId) -> Level,
338+
pub lint_level_at: extern "C" fn(&'ast (), &'static Lint, NodeId) -> Level,
339339
pub emit_diag: for<'a> extern "C" fn(&'ast (), &'a Diagnostic<'a, 'ast>),
340340

341341
// Public utility
@@ -356,7 +356,7 @@ struct DriverCallbacks<'ast> {
356356
}
357357

358358
impl<'ast> DriverCallbacks<'ast> {
359-
fn call_lint_level_at(&self, lint: &'static Lint, node: EmissionNodeId) -> Level {
359+
fn call_lint_level_at(&self, lint: &'static Lint, node: NodeId) -> Level {
360360
(self.lint_level_at)(self.driver_context, lint, node)
361361
}
362362

0 commit comments

Comments
 (0)