Skip to content
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

API: Reduce parameters for AstContext::emit_lint and add docs #245

Merged
merged 3 commits into from
Sep 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
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
14 changes: 5 additions & 9 deletions marker_adapter/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,12 @@
#![allow(clippy::needless_lifetimes)]

use marker_api::{
ast::{
item::{Body, ItemKind},
ty::SemTyKind,
BodyId, ExpnId, ExpnInfo, ExprId, FileInfo, FilePos, ItemId, Span, SpanId, SpanPos, SpanSource, SymbolId,
TyDefId,
},
ast::{ty::SemTyKind, ExpnId, ExpnInfo, ExprId, FileInfo, FilePos, SpanId, SpanPos, SpanSource, SymbolId},
context::DriverCallbacks,
diagnostic::{Diagnostic, EmissionNode},
diagnostic::Diagnostic,
ffi::{self, FfiOption},
lint::{Level, Lint},
prelude::*,
};

/// ### Safety
Expand Down Expand Up @@ -59,7 +55,7 @@ impl<'ast> DriverContextWrapper<'ast> {

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

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

pub trait DriverContext<'ast> {
fn lint_level_at(&'ast self, lint: &'static Lint, node: EmissionNode) -> Level;
fn lint_level_at(&'ast self, lint: &'static Lint, node: NodeId) -> Level;
fn emit_diag(&'ast self, diag: &Diagnostic<'_, 'ast>);

fn item(&'ast self, api_id: ItemId) -> Option<ItemKind<'ast>>;
Expand Down
62 changes: 62 additions & 0 deletions marker_api/src/ast/common/id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ macro_rules! new_id {

use new_id;

use crate::private::Sealed;

new_id!(
/// This ID uniquely identifies a crate during linting.
pub CrateId: u32
Expand Down Expand Up @@ -144,3 +146,63 @@ new_id! {
/// This ID uniquely identifies a statement during linting.
pub StmtId: u64
}

#[repr(C)]
#[non_exhaustive]
#[derive(Debug, Clone, Copy)]
pub enum NodeId {
Expr(ExprId),
Item(ItemId),
Stmt(StmtId),
Body(BodyId),
Field(FieldId),
Variant(VariantId),
}

macro_rules! impl_into_node_id_for {
($variant:ident, $ty:ty) => {
impl From<$ty> for NodeId {
fn from(value: $ty) -> Self {
NodeId::$variant(value)
}
}

impl From<&$ty> for NodeId {
fn from(value: &$ty) -> Self {
NodeId::$variant(*value)
}
}
};
}

impl_into_node_id_for!(Expr, ExprId);
impl_into_node_id_for!(Item, ItemId);
impl_into_node_id_for!(Stmt, StmtId);
impl_into_node_id_for!(Body, BodyId);
impl_into_node_id_for!(Field, FieldId);
impl_into_node_id_for!(Variant, VariantId);

pub trait HasNodeId: Sealed {
/// Returns the [`NodeId`] of the identifiable node
fn node_id(&self) -> NodeId;
}

impl<N: HasNodeId> HasNodeId for &N {
fn node_id(&self) -> NodeId {
(*self).node_id()
}
}

macro_rules! impl_identifiable_for {
($ty:ty$(, use $data_trait:path)?) => {
impl<'ast> $crate::ast::HasNodeId for $ty {
fn node_id(&self) -> $crate::ast::NodeId {
$(
use $data_trait;
)*
self.id().into()
}
}
};
}
pub(crate) use impl_identifiable_for;
39 changes: 37 additions & 2 deletions marker_api/src/ast/common/span.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::marker::PhantomData;

use crate::{context::with_cx, diagnostic::Applicability, ffi};
use crate::{context::with_cx, diagnostic::Applicability, ffi, private::Sealed};

use super::{ExpnId, MacroId, SpanId, SpanSrcId, SymbolId};

Expand Down Expand Up @@ -386,6 +386,13 @@ impl<'ast> Span<'ast> {
}
}

impl<'ast> HasSpan<'ast> for Span<'ast> {
fn span(&self) -> &Span<'ast> {
self
}
}
impl Sealed for Span<'_> {}

#[cfg(feature = "driver-api")]
impl<'ast> Span<'ast> {
#[must_use]
Expand Down Expand Up @@ -509,11 +516,14 @@ impl<'ast> Ident<'ast> {
pub fn name(&self) -> &str {
with_cx(self, |cx| cx.symbol_str(self.sym))
}
}

pub fn span(&self) -> &Span<'ast> {
impl<'ast> HasSpan<'ast> for Ident<'ast> {
fn span(&self) -> &Span<'ast> {
with_cx(self, |cx| cx.span(self.span))
}
}
impl<'ast> crate::private::Sealed for Ident<'ast> {}

#[cfg(feature = "driver-api")]
impl<'ast> Ident<'ast> {
Expand Down Expand Up @@ -570,3 +580,28 @@ impl_ident_eq_for!(
std::ffi::OsString,
std::borrow::Cow<'_, str>
);

/// A trait for nodes, that provide a [`Span`].
xFrednet marked this conversation as resolved.
Show resolved Hide resolved
pub trait HasSpan<'ast>: Sealed {
/// This returns the [`Span`] of the implementing AST node.
fn span(&self) -> &Span<'ast>;
}

/// This macro implements the [`HasSpan`] trait for data types, that provide a
/// `span()` method.
macro_rules! impl_spanned_for {
($ty:ty) => {
impl<'ast> $crate::ast::HasSpan<'ast> for $ty {
fn span(&self) -> &$crate::ast::Span<'ast> {
self.span()
}
}
};
}
pub(crate) use impl_spanned_for;

impl<'ast, N: HasSpan<'ast>> HasSpan<'ast> for &N {
fn span(&self) -> &Span<'ast> {
(*self).span()
}
}
26 changes: 16 additions & 10 deletions marker_api/src/ast/expr.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{private::Sealed, CtorBlocker};
use crate::{prelude::EmissionNode, private::Sealed, CtorBlocker};

use super::{ty::SemTyKind, ExprId, Span, SpanId};
use super::{ty::SemTyKind, ExprId, HasNodeId, HasSpan, Span, SpanId};

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

Expand All @@ -27,13 +27,10 @@ pub use unstable_expr::*;
///
/// This trait is only meant to be implemented inside this crate. The `Sealed`
/// super trait prevents external implementations.
pub trait ExprData<'ast>: Debug + Sealed {
pub trait ExprData<'ast>: Debug + EmissionNode<'ast> + HasSpan<'ast> + HasNodeId + Sealed {
/// Returns the [`ExprId`] of this expression.
fn id(&self) -> ExprId;

/// Returns the [`Span`] of this expression.
fn span(&self) -> &Span<'ast>;

/// Returns the semantic type of this expression.
fn ty(&self) -> SemTyKind<'ast>;

Expand Down Expand Up @@ -93,6 +90,8 @@ impl<'ast> ExprKind<'ast> {
impl_expr_kind_fn!(ExprKind: precedence() -> ExprPrecedence);
}

crate::ast::impl_spanned_for!(ExprKind<'ast>);
crate::ast::impl_identifiable_for!(ExprKind<'ast>);
impl Sealed for ExprKind<'_> {}

#[repr(C)]
Expand All @@ -117,6 +116,10 @@ impl<'ast> LitExprKind<'ast> {
impl_expr_kind_fn!(LitExprKind: precedence() -> ExprPrecedence);
}

crate::ast::impl_spanned_for!(LitExprKind<'ast>);
crate::ast::impl_identifiable_for!(LitExprKind<'ast>);
impl Sealed for LitExprKind<'_> {}

impl<'ast> From<LitExprKind<'ast>> for ExprKind<'ast> {
fn from(value: LitExprKind<'ast>) -> Self {
match value {
Expand Down Expand Up @@ -313,10 +316,6 @@ macro_rules! impl_expr_data {
self.data.id
}

fn span(&self) -> &crate::ast::Span<'ast> {
$crate::context::with_cx(self, |cx| cx.span(self.data.span))
}

fn ty(&self) -> $crate::ast::ty::SemTyKind<'ast> {
$crate::context::with_cx(self, |cx| cx.expr_ty(self.data.id))
}
Expand All @@ -328,6 +327,13 @@ macro_rules! impl_expr_data {
}
}

impl<'ast> $crate::ast::HasSpan<'ast> for $self_ty {
fn span(&self) -> &crate::ast::Span<'ast> {
$crate::context::with_cx(self, |cx| cx.span(self.data.span))
}
}
$crate::ast::impl_identifiable_for!($self_ty, use $crate::ast::expr::ExprData);

impl<'ast> $crate::private::Sealed for $self_ty {}

impl<'ast> From<&'ast $self_ty> for $crate::ast::expr::ExprKind<'ast> {
Expand Down
2 changes: 1 addition & 1 deletion marker_api/src/ast/expr/lit_expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ impl<'ast> CharLitExpr<'ast> {
/// can be hardware-dependent. For exact value checks, it might be better to check
/// the written float literal by getting the code snipped from the expression span.
/// See:
/// * [`ExprData::span()`](`super::ExprData::span`)
/// * [`HasSpan::span()`](`super::HasSpan::span`)
/// * [`Span::snippet()`](`crate::ast::Span::snippet`)
///
/// All integer literals are unsigned, negative numbers have a unary negation
Expand Down
36 changes: 24 additions & 12 deletions marker_api/src/ast/item.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use std::{fmt::Debug, marker::PhantomData};

use crate::diagnostic::EmissionNode;
use crate::private::Sealed;
use crate::CtorBlocker;

use super::expr::ExprKind;
use super::{Ident, ItemId, Span, SpanId};
use super::{HasNodeId, HasSpan, Ident, ItemId, Span, SpanId};

// Item implementations
mod extern_crate_item;
Expand Down Expand Up @@ -36,15 +37,11 @@ pub use unstable_item::*;
///
/// This trait is only meant to be implemented inside this crate. The `Sealed`
/// super trait prevents external implementations.
pub trait ItemData<'ast>: Debug + Sealed {
pub trait ItemData<'ast>: Debug + EmissionNode<'ast> + HasSpan<'ast> + HasNodeId + Sealed {
/// Returns the [`ItemId`] of this item. This is a unique identifier used for comparison
/// and to request items from the [`AstContext`](`crate::context::AstContext`).
fn id(&self) -> ItemId;

/// The [`Span`] of the entire item. This span should be used for general item related
/// diagnostics.
fn span(&self) -> &Span<'ast>;

/// The [`Visibility`] of this item.
fn visibility(&self) -> &Visibility<'ast>;

Expand Down Expand Up @@ -93,8 +90,12 @@ impl<'ast> ItemKind<'ast> {
impl_item_type_fn!(ItemKind: attrs() -> ());
}

crate::ast::impl_spanned_for!(ItemKind<'ast>);
crate::ast::impl_identifiable_for!(ItemKind<'ast>);
impl<'ast> crate::private::Sealed for ItemKind<'ast> {}

#[non_exhaustive]
#[derive(Debug)]
#[derive(Debug, Copy, Clone)]
pub enum AssocItemKind<'ast> {
TyAlias(&'ast TyAliasItem<'ast>, CtorBlocker),
Const(&'ast ConstItem<'ast>, CtorBlocker),
Expand All @@ -111,6 +112,10 @@ impl<'ast> AssocItemKind<'ast> {
// FIXME: Potentially add a field to the items to optionally store the owner id
}

crate::ast::impl_spanned_for!(AssocItemKind<'ast>);
crate::ast::impl_identifiable_for!(AssocItemKind<'ast>);
impl<'ast> crate::private::Sealed for AssocItemKind<'ast> {}

impl<'ast> From<AssocItemKind<'ast>> for ItemKind<'ast> {
fn from(value: AssocItemKind<'ast>) -> Self {
match value {
Expand All @@ -122,7 +127,7 @@ impl<'ast> From<AssocItemKind<'ast>> for ItemKind<'ast> {
}

#[non_exhaustive]
#[derive(Debug)]
#[derive(Debug, Copy, Clone)]
pub enum ExternItemKind<'ast> {
Static(&'ast StaticItem<'ast>, CtorBlocker),
Fn(&'ast FnItem<'ast>, CtorBlocker),
Expand All @@ -137,6 +142,10 @@ impl<'ast> ExternItemKind<'ast> {
impl_item_type_fn!(ExternItemKind: as_item() -> ItemKind<'ast>);
}

crate::ast::impl_spanned_for!(ExternItemKind<'ast>);
crate::ast::impl_identifiable_for!(ExternItemKind<'ast>);
impl<'ast> crate::private::Sealed for ExternItemKind<'ast> {}

impl<'ast> From<ExternItemKind<'ast>> for ItemKind<'ast> {
fn from(value: ExternItemKind<'ast>) -> Self {
match value {
Expand Down Expand Up @@ -193,10 +202,6 @@ macro_rules! impl_item_data {
self.data.id
}

fn span(&self) -> &crate::ast::Span<'ast> {
$crate::context::with_cx(self, |cx| cx.span(self.data.span))
}

fn visibility(&self) -> &crate::ast::item::Visibility<'ast> {
&self.data.vis
}
Expand All @@ -212,6 +217,13 @@ macro_rules! impl_item_data {
fn attrs(&self) {}
}

impl<'ast> $crate::ast::HasSpan<'ast> for $self_name<'ast> {
fn span(&self) -> &crate::ast::Span<'ast> {
$crate::context::with_cx(self, |cx| cx.span(self.data.span))
}
}

$crate::ast::impl_identifiable_for!($self_name<'ast>, use $crate::ast::item::ItemData);
impl $crate::private::Sealed for $self_name<'_> {}

impl<'ast> From<&'ast $self_name<'ast>> for crate::ast::item::ItemKind<'ast> {
Expand Down
Loading