Skip to content

Proc macro span API redesign: Replace proc_macro::SourceFile by Span::{file, local_file} #139671

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
merged 4 commits into from
Apr 15, 2025
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
51 changes: 24 additions & 27 deletions compiler/rustc_expand/src/proc_macro_server.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use std::ops::{Bound, Range};
use std::sync::Arc;

use ast::token::IdentIsRaw;
use pm::bridge::{
Expand All @@ -18,7 +17,7 @@ use rustc_parse::parser::Parser;
use rustc_parse::{exp, new_parser_from_source_str, source_str_to_stream, unwrap_or_emit_fatal};
use rustc_session::parse::ParseSess;
use rustc_span::def_id::CrateNum;
use rustc_span::{BytePos, FileName, Pos, SourceFile, Span, Symbol, sym};
use rustc_span::{BytePos, FileName, Pos, Span, Symbol, sym};
use smallvec::{SmallVec, smallvec};

use crate::base::ExtCtxt;
Expand Down Expand Up @@ -467,7 +466,6 @@ impl<'a, 'b> Rustc<'a, 'b> {
impl server::Types for Rustc<'_, '_> {
type FreeFunctions = FreeFunctions;
type TokenStream = TokenStream;
type SourceFile = Arc<SourceFile>;
type Span = Span;
type Symbol = Symbol;
}
Expand Down Expand Up @@ -673,28 +671,6 @@ impl server::TokenStream for Rustc<'_, '_> {
}
}

impl server::SourceFile for Rustc<'_, '_> {
fn eq(&mut self, file1: &Self::SourceFile, file2: &Self::SourceFile) -> bool {
Arc::ptr_eq(file1, file2)
}

fn path(&mut self, file: &Self::SourceFile) -> String {
match &file.name {
FileName::Real(name) => name
.local_path()
.expect("attempting to get a file path in an imported file in `proc_macro::SourceFile::path`")
.to_str()
.expect("non-UTF8 file path in `proc_macro::SourceFile::path`")
.to_string(),
_ => file.name.prefer_local().to_string(),
}
}

fn is_real(&mut self, file: &Self::SourceFile) -> bool {
file.is_real_file()
}
}

impl server::Span for Rustc<'_, '_> {
fn debug(&mut self, span: Self::Span) -> String {
if self.ecx.ecfg.span_debug {
Expand All @@ -704,8 +680,29 @@ impl server::Span for Rustc<'_, '_> {
}
}

fn source_file(&mut self, span: Self::Span) -> Self::SourceFile {
self.psess().source_map().lookup_char_pos(span.lo()).file
fn file(&mut self, span: Self::Span) -> String {
self.psess()
.source_map()
.lookup_char_pos(span.lo())
.file
.name
.prefer_remapped_unconditionaly()
.to_string()
}

fn local_file(&mut self, span: Self::Span) -> Option<String> {
self.psess()
.source_map()
.lookup_char_pos(span.lo())
.file
.name
.clone()
.into_local_path()
.map(|p| {
p.to_str()
.expect("non-UTF8 file path in `proc_macro::SourceFile::path`")
.to_string()
})
}

fn parent(&mut self, span: Self::Span) -> Option<Self::Span> {
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_fluent_macro/src/fluent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ fn invocation_relative_path_to_absolute(span: Span, path: &str) -> PathBuf {
path.to_path_buf()
} else {
// `/a/b/c/foo/bar.rs` contains the current macro invocation
#[cfg(bootstrap)]
let mut source_file_path = span.source_file().path();
#[cfg(not(bootstrap))]
let mut source_file_path = span.local_file().unwrap();
// `/a/b/c/foo/`
source_file_path.pop();
// `/a/b/c/foo/../locales/en-US/example.ftl`
Expand Down
6 changes: 0 additions & 6 deletions library/proc_macro/src/bridge/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,12 +111,6 @@ impl Clone for TokenStream {
}
}

impl Clone for SourceFile {
fn clone(&self) -> Self {
self.clone()
}
}

impl Span {
pub(crate) fn def_site() -> Span {
Bridge::with(|bridge| bridge.globals.def_site)
Expand Down
11 changes: 2 additions & 9 deletions library/proc_macro/src/bridge/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,23 +81,17 @@ macro_rules! with_api {
$self: $S::TokenStream
) -> Vec<TokenTree<$S::TokenStream, $S::Span, $S::Symbol>>;
},
SourceFile {
fn drop($self: $S::SourceFile);
fn clone($self: &$S::SourceFile) -> $S::SourceFile;
fn eq($self: &$S::SourceFile, other: &$S::SourceFile) -> bool;
fn path($self: &$S::SourceFile) -> String;
fn is_real($self: &$S::SourceFile) -> bool;
},
Span {
fn debug($self: $S::Span) -> String;
fn source_file($self: $S::Span) -> $S::SourceFile;
fn parent($self: $S::Span) -> Option<$S::Span>;
fn source($self: $S::Span) -> $S::Span;
fn byte_range($self: $S::Span) -> Range<usize>;
fn start($self: $S::Span) -> $S::Span;
fn end($self: $S::Span) -> $S::Span;
fn line($self: $S::Span) -> usize;
fn column($self: $S::Span) -> usize;
fn file($self: $S::Span) -> String;
fn local_file($self: $S::Span) -> Option<String>;
fn join($self: $S::Span, other: $S::Span) -> Option<$S::Span>;
fn subspan($self: $S::Span, start: Bound<usize>, end: Bound<usize>) -> Option<$S::Span>;
fn resolved_at($self: $S::Span, at: $S::Span) -> $S::Span;
Expand All @@ -120,7 +114,6 @@ macro_rules! with_api_handle_types {
'owned:
FreeFunctions,
TokenStream,
SourceFile,

'interned:
Span,
Expand Down
1 change: 0 additions & 1 deletion library/proc_macro/src/bridge/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ with_api_handle_types!(define_server_handles);
pub trait Types {
type FreeFunctions: 'static;
type TokenStream: 'static + Clone;
type SourceFile: 'static + Clone;
type Span: 'static + Copy + Eq + Hash;
type Symbol: 'static;
}
Expand Down
77 changes: 19 additions & 58 deletions library/proc_macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -491,12 +491,6 @@ impl Span {
Span(bridge::client::Span::mixed_site())
}

/// The original source file into which this span points.
#[unstable(feature = "proc_macro_span", issue = "54725")]
pub fn source_file(&self) -> SourceFile {
SourceFile(self.0.source_file())
}

/// The `Span` for the tokens in the previous macro expansion from which
/// `self` was generated from, if any.
#[unstable(feature = "proc_macro_span", issue = "54725")]
Expand Down Expand Up @@ -546,6 +540,25 @@ impl Span {
self.0.column()
}

/// The path to the source file in which this span occurs, for display purposes.
///
/// This might not correspond to a valid file system path.
/// It might be remapped, or might be an artificial path such as `"<macro expansion>"`.
#[unstable(feature = "proc_macro_span", issue = "54725")]
pub fn file(&self) -> String {
self.0.file()
}

/// The path to the source file in which this span occurs on disk.
///
/// This is the actual path on disk. It is unaffected by path remapping.
///
/// This path should not be embedded in the output of the macro; prefer `file()` instead.
#[unstable(feature = "proc_macro_span", issue = "54725")]
pub fn local_file(&self) -> Option<PathBuf> {
self.0.local_file().map(|s| PathBuf::from(s))
}

/// Creates a new span encompassing `self` and `other`.
///
/// Returns `None` if `self` and `other` are from different files.
Expand Down Expand Up @@ -614,58 +627,6 @@ impl fmt::Debug for Span {
}
}

/// The source file of a given `Span`.
#[unstable(feature = "proc_macro_span", issue = "54725")]
#[derive(Clone)]
pub struct SourceFile(bridge::client::SourceFile);

impl SourceFile {
/// Gets the path to this source file.
///
/// ### Note
/// If the code span associated with this `SourceFile` was generated by an external macro, this
/// macro, this might not be an actual path on the filesystem. Use [`is_real`] to check.
///
/// Also note that even if `is_real` returns `true`, if `--remap-path-prefix` was passed on
/// the command line, the path as given might not actually be valid.
///
/// [`is_real`]: Self::is_real
#[unstable(feature = "proc_macro_span", issue = "54725")]
pub fn path(&self) -> PathBuf {
PathBuf::from(self.0.path())
}

/// Returns `true` if this source file is a real source file, and not generated by an external
/// macro's expansion.
#[unstable(feature = "proc_macro_span", issue = "54725")]
pub fn is_real(&self) -> bool {
// This is a hack until intercrate spans are implemented and we can have real source files
// for spans generated in external macros.
// https://github.com/rust-lang/rust/pull/43604#issuecomment-333334368
self.0.is_real()
}
}

#[unstable(feature = "proc_macro_span", issue = "54725")]
impl fmt::Debug for SourceFile {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SourceFile")
.field("path", &self.path())
.field("is_real", &self.is_real())
.finish()
}
}

#[unstable(feature = "proc_macro_span", issue = "54725")]
impl PartialEq for SourceFile {
fn eq(&self, other: &Self) -> bool {
self.0.eq(&other.0)
}
}

#[unstable(feature = "proc_macro_span", issue = "54725")]
impl Eq for SourceFile {}

/// A single token or a delimited sequence of token trees (e.g., `[1, (), ..]`).
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
#[derive(Clone)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use std::{

use intern::Symbol;
use proc_macro::bridge::{self, server};
use span::{FileId, Span, FIXUP_ERASED_FILE_AST_ID_MARKER};
use span::{Span, FIXUP_ERASED_FILE_AST_ID_MARKER};
use tt::{TextRange, TextSize};

use crate::server_impl::{literal_kind_to_internal, token_stream::TokenStreamBuilder, TopSubtree};
Expand All @@ -27,10 +27,6 @@ mod tt {

type TokenStream = crate::server_impl::TokenStream<Span>;

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct SourceFile {
file_id: FileId,
}
pub struct FreeFunctions;

pub struct RaSpanServer {
Expand All @@ -46,7 +42,6 @@ pub struct RaSpanServer {
impl server::Types for RaSpanServer {
type FreeFunctions = FreeFunctions;
type TokenStream = TokenStream;
type SourceFile = SourceFile;
type Span = Span;
type Symbol = Symbol;
}
Expand Down Expand Up @@ -245,25 +240,17 @@ impl server::TokenStream for RaSpanServer {
}
}

impl server::SourceFile for RaSpanServer {
fn eq(&mut self, file1: &Self::SourceFile, file2: &Self::SourceFile) -> bool {
file1 == file2
}
fn path(&mut self, _file: &Self::SourceFile) -> String {
// FIXME
String::new()
}
fn is_real(&mut self, _file: &Self::SourceFile) -> bool {
true
}
}

impl server::Span for RaSpanServer {
fn debug(&mut self, span: Self::Span) -> String {
format!("{:?}", span)
}
fn source_file(&mut self, span: Self::Span) -> Self::SourceFile {
SourceFile { file_id: span.anchor.file_id.file_id() }
fn file(&mut self, _: Self::Span) -> String {
// FIXME
String::new()
}
fn local_file(&mut self, _: Self::Span) -> Option<String> {
// FIXME
None
}
fn save_span(&mut self, _span: Self::Span) -> usize {
// FIXME, quote is incompatible with third-party tools
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ type Literal = tt::Literal;
type Span = tt::TokenId;
type TokenStream = crate::server_impl::TokenStream<Span>;

#[derive(Clone)]
pub struct SourceFile;
pub struct FreeFunctions;

pub struct TokenIdServer {
Expand All @@ -37,7 +35,6 @@ pub struct TokenIdServer {
impl server::Types for TokenIdServer {
type FreeFunctions = FreeFunctions;
type TokenStream = TokenStream;
type SourceFile = SourceFile;
type Span = Span;
type Symbol = Symbol;
}
Expand Down Expand Up @@ -223,24 +220,15 @@ impl server::TokenStream for TokenIdServer {
}
}

impl server::SourceFile for TokenIdServer {
fn eq(&mut self, _file1: &Self::SourceFile, _file2: &Self::SourceFile) -> bool {
true
}
fn path(&mut self, _file: &Self::SourceFile) -> String {
String::new()
}
fn is_real(&mut self, _file: &Self::SourceFile) -> bool {
true
}
}

impl server::Span for TokenIdServer {
fn debug(&mut self, span: Self::Span) -> String {
format!("{:?}", span.0)
}
fn source_file(&mut self, _span: Self::Span) -> Self::SourceFile {
SourceFile {}
fn file(&mut self, _span: Self::Span) -> String {
String::new()
}
fn local_file(&mut self, _span: Self::Span) -> Option<String> {
None
}
fn save_span(&mut self, _span: Self::Span) -> usize {
0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ fn test_fn_like_macro_clone_raw_ident() {
}

#[test]
#[cfg(not(bootstrap))]
fn test_fn_like_fn_like_span_join() {
assert_expand(
"fn_like_span_join",
Expand All @@ -111,6 +112,7 @@ fn test_fn_like_fn_like_span_join() {
}

#[test]
#[cfg(not(bootstrap))]
fn test_fn_like_fn_like_span_ops() {
assert_expand(
"fn_like_span_ops",
Expand Down
8 changes: 4 additions & 4 deletions tests/ui/proc-macro/auxiliary/expand-expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@

extern crate proc_macro;

use proc_macro::*;
use std::str::FromStr;

use proc_macro::*;

// Flatten the TokenStream, removing any toplevel `Delimiter::None`s for
// comparison.
fn flatten(ts: TokenStream) -> Vec<TokenTree> {
Expand Down Expand Up @@ -136,9 +137,8 @@ pub fn check_expand_expr_file(ts: TokenStream) -> TokenStream {
.to_string();
assert_eq!(input_t, parse_t);

// Check that the literal matches `Span::call_site().source_file().path()`
let expect_t =
Literal::string(&Span::call_site().source_file().path().to_string_lossy()).to_string();
// Check that the literal matches `Span::call_site().file()`
let expect_t = Literal::string(&Span::call_site().file()).to_string();
assert_eq!(input_t, expect_t);

TokenStream::new()
Expand Down
Loading
Loading