Skip to content
Open
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
8 changes: 8 additions & 0 deletions compiler/rustc_ast_passes/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1325,3 +1325,11 @@ pub(crate) struct AbiCustomCannotBeCold {
#[label("`extern \"custom\"` because of this")]
pub abi_span: Span,
}

#[derive(Diagnostic)]
#[diag("showing the spans of the {$kind}")]
pub(crate) struct ShowSpan {
#[primary_span]
pub span: Span,
pub kind: &'static str,
}
1 change: 1 addition & 0 deletions compiler/rustc_ast_passes/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@
pub mod ast_validation;
mod diagnostics;
pub mod feature_gate;
pub mod show_spans;
67 changes: 67 additions & 0 deletions compiler/rustc_ast_passes/src/show_spans.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
use rustc_ast::visit::{self, Visitor};
use rustc_ast::{self as ast, ItemKind};
use rustc_attr_ir::{Attribute, AttributeKind, RustcShowSpansKind};
use rustc_attr_parsing::AttributeParser;
use rustc_session::Session;
use rustc_span::sym;

use crate::diagnostics;

struct ShowSpans<'a> {
sess: &'a Session,
expr: bool,
ty: bool,
path: bool,
}

impl<'a> Visitor<'a> for ShowSpans<'a> {
fn visit_item(&mut self, item: &'a ast::Item) {
let saved = (self.expr, self.ty, self.path);
(self.expr, self.ty, self.path) = (false, false, false);

@FranciscoTGouveia FranciscoTGouveia Oct 11, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Before visiting a new item, I saved the current state of ShowSpans and reset it to support nested items.
Is this necessary, or is it redundant?

View changes since the review

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

That depends on whether this should print the path. I'd, perhaps naively, expect it to do print it, in which case resetting is wrong.

#[rustc_show_spans(path)]
fn bar() {
    fn foo() {
        let _ = a::b::c;
    }
}

(this is also something that should have a test)


if let ItemKind::Fn(_) = &item.kind
&& let Some(Attribute::Parsed(AttributeKind::RustcShowSpans(kinds))) =
AttributeParser::parse_limited_sym(self.sess, &item.attrs, &[sym::rustc_show_spans])
{
for kind in kinds {
match kind {
RustcShowSpansKind::Expr => self.expr = true,
RustcShowSpansKind::Ty => self.ty = true,
RustcShowSpansKind::Path => self.path = true,
}
}
}
visit::walk_item(self, item);

// Recover the state. Needed if we are looking into nested items.
(self.expr, self.ty, self.path) = saved;
}

// We override it as to not report attribute paths as paths.
fn visit_attribute(&mut self, _: &'a ast::Attribute) {}

fn visit_expr(&mut self, e: &'a ast::Expr) {
if self.expr {
self.sess.dcx().emit_note(diagnostics::ShowSpan { span: e.span, kind: "expr" });
}
visit::walk_expr(self, e);
}

fn visit_ty(&mut self, t: &'a ast::Ty) {
if self.ty {
self.sess.dcx().emit_note(diagnostics::ShowSpan { span: t.span, kind: "ty" });
}
visit::walk_ty(self, t);
}

fn visit_path(&mut self, p: &'a ast::Path) {
if self.path {
self.sess.dcx().emit_note(diagnostics::ShowSpan { span: p.span, kind: "path" });
}
visit::walk_path(self, p);
}
}

pub fn check_crate(sess: &Session, krate: &ast::Crate) {
visit::walk_crate(&mut ShowSpans { sess, expr: false, ty: false, path: false }, krate);
}
10 changes: 10 additions & 0 deletions compiler/rustc_attr_ir/src/data_structures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,13 @@ impl<E: rustc_span::SpanEncoder> rustc_serialize::Encodable<E> for DocAttribute
}
}

#[derive(Clone, Debug, StableHash, Encodable, Decodable, PrintAttribute)]
pub enum RustcShowSpansKind {
Expr,
Ty,
Path,
}

#[derive(Clone, Debug, StableHash, Encodable, Decodable, PrintAttribute)]
pub enum RustcDumpLayoutKind {
Align,
Expand Down Expand Up @@ -1407,6 +1414,9 @@ pub enum AttributeKind {
/// Represents `#[rustc_should_not_be_called_on_const_items]`
RustcShouldNotBeCalledOnConstItems,

/// Represents `#[rustc_show_spans]`
RustcShowSpans(ThinVec<RustcShowSpansKind>),

/// Represents `#[rustc_simd_monomorphize_lane_limit = "N"]`.
RustcSimdMonomorphizeLaneLimit(Limit),

Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_attr_ir/src/encode_cross_crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ impl AttributeKind {
RustcRegions => No,
RustcScalableVector { .. } => Yes,
RustcShouldNotBeCalledOnConstItems => Yes,
RustcShowSpans(_) => No,
RustcSimdMonomorphizeLaneLimit(..) => Yes, // Affects layout computation, which needs to work cross-crate
RustcSkipDuringMethodDispatch { .. } => No,
RustcSpecializationTrait => No,
Expand Down Expand Up @@ -401,6 +402,7 @@ impl AttributeKind {
RustcRegions => false,
RustcScalableVector { .. } => false,
RustcShouldNotBeCalledOnConstItems => false,
RustcShowSpans(_) => false,
RustcSimdMonomorphizeLaneLimit(..) => false,
RustcSkipDuringMethodDispatch { .. } => false,
RustcSpecializationTrait => false,
Expand Down
43 changes: 42 additions & 1 deletion compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use rustc_attr_ir::target::{AssocCtxt, MethodKind, Target};
use rustc_attr_ir::{AttributeKind, RustcDumpLayoutKind};
use rustc_attr_ir::{AttributeKind, RustcDumpLayoutKind, RustcShowSpansKind};
use rustc_feature::AttributeStability;
use rustc_span::{Span, Symbol, sym};

Expand Down Expand Up @@ -301,3 +301,44 @@ impl NoArgsAttributeParser for RustcDumpVtableParser {
const STABILITY: AttributeStability = unstable!(rustc_attrs);
const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcDumpVtable;
}

pub(crate) struct RustcShowSpans;

impl SingleAttributeParser for RustcShowSpans {
Comment thread
FranciscoTGouveia marked this conversation as resolved.
const PATH: &[Symbol] = &[sym::rustc_show_spans];

const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn)]);

const TEMPLATE: AttributeTemplate = template!(List: &["expr", "ty", "path"]);
const STABILITY: AttributeStability = unstable!(rustc_attrs);

fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {
let Some(items) = cx.expect_list(args, cx.attr_span) else {
return None;
};

let mut result = ThinVec::new();
for item in items.mixed() {
let Some(arg) = item.meta_item_no_args() else {
cx.adcx().expected_not_literal(item.span());
continue;
};
let Some(ident) = arg.ident() else {
cx.adcx().expected_identifier(arg.span());
return None;
};
let kind = match ident.name {
sym::expr => RustcShowSpansKind::Expr,
sym::ty => RustcShowSpansKind::Ty,
sym::path => RustcShowSpansKind::Path,
_ => {
cx.adcx()
.expected_specific_argument(ident.span, &[sym::expr, sym::ty, sym::path]);
continue;
}
};
result.push(kind);
}
Some(AttributeKind::RustcShowSpans(result))
}
}
1 change: 1 addition & 0 deletions compiler/rustc_attr_parsing/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ attribute_parsers!(
Single<RustcObjcClassParser>,
Single<RustcObjcSelectorParser>,
Single<RustcScalableVectorParser>,
Single<RustcShowSpans>,
Single<RustcSimdMonomorphizeLaneLimitParser>,
Single<RustcSkipDuringMethodDispatchParser>,
Single<RustcTestMarkerParser>,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_feature/src/builtin_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,7 @@ pub static BUILTIN_ATTRIBUTES: &[Symbol] = &[
// Internal attributes, Testing:
// ==========================================================================

sym::rustc_show_spans,

@FranciscoTGouveia FranciscoTGouveia Oct 11, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I was undecided about whether to consider this new attribute as Testing or Misc.
Since it seems to be temporary for the migration to the new span combining scheme, I went with the former.

View changes since the review

sym::rustc_effective_visibility,
sym::rustc_dump_inferred_outlives,
sym::rustc_capture_analysis,
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_interface/src/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,10 @@ fn configure_and_expand(
)
});

if features.rustc_attrs() {
rustc_ast_passes::show_spans::check_crate(sess, &krate);
}

let crate_types = tcx.crate_types();
let is_executable_crate = crate_types.contains(&CrateType::Executable);
let is_proc_macro_crate = crate_types.contains(&CrateType::ProcMacro);
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
AttributeKind::RustcRegions => (),
AttributeKind::RustcScalableVector { .. } => (),
AttributeKind::RustcShouldNotBeCalledOnConstItems => (),
AttributeKind::RustcShowSpans(_) => (),
AttributeKind::RustcSimdMonomorphizeLaneLimit(..) => (),
AttributeKind::RustcSkipDuringMethodDispatch { .. } => (),

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1913,6 +1913,7 @@ symbols! {
rustc_regions,
rustc_scalable_vector,
rustc_should_not_be_called_on_const_items,
rustc_show_spans,
rustc_simd_monomorphize_lane_limit,
rustc_skip_during_method_dispatch,
rustc_specialization_trait,
Expand Down
Loading