diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 2dc9b51a37ea0..b62c52a8c3377 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -402,8 +402,8 @@ impl server::FreeFunctions for Rustc<'_, '_> { .insert((Symbol::intern(var), value.map(Symbol::intern))); } - fn track_path(&mut self, path: &str) { - self.sess().file_depinfo.borrow_mut().insert(Symbol::intern(path)); + fn track_path(&mut self, path: std::path::PathBuf) { + self.sess().file_depinfo.borrow_mut().insert(path); } fn literal_from_str(&mut self, s: &str) -> Result, ()> { diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 0e8f93cef173f..830aa2201184b 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -469,13 +469,12 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P // (e.g. accessed in proc macros). let file_depinfo = sess.parse_sess.file_depinfo.borrow(); - let normalize_path = |path: PathBuf| { + let normalize_path = |path: PathBuf| -> String { let file = FileName::from(path); escape_dep_filename(&file.prefer_local().to_string()) }; - let extra_tracked_files = - file_depinfo.iter().map(|path_sym| normalize_path(PathBuf::from(path_sym.as_str()))); + let extra_tracked_files = file_depinfo.iter().map(|path| normalize_path(path.to_owned())); files.extend(extra_tracked_files); // We also need to track used PGO profile files diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 671204c0d8efa..8e7b8a4fbebe7 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -214,7 +214,8 @@ pub struct ParseSess { /// Environment variables accessed during the build and their values when they exist. pub env_depinfo: Lock)>>, /// File paths accessed during the build. - pub file_depinfo: Lock>, + /// Paths are relative to ???. + pub file_depinfo: Lock>, /// Whether cfg(version) should treat the current release as incomplete pub assume_incomplete_release: bool, /// Spans passed to `proc_macro::quote_span`. Each span has a numerical diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs index 86ce5d9c6d5fe..ded6fc09ed9ff 100644 --- a/library/proc_macro/src/bridge/mod.rs +++ b/library/proc_macro/src/bridge/mod.rs @@ -16,6 +16,7 @@ use std::mem; use std::ops::Bound; use std::ops::Range; use std::panic; +use std::path; use std::sync::atomic::AtomicUsize; use std::sync::Once; use std::thread; @@ -56,7 +57,7 @@ macro_rules! with_api { FreeFunctions { fn drop($self: $S::FreeFunctions); fn track_env_var(var: &str, value: Option<&str>); - fn track_path(path: &str); + fn track_path(path: std::path::PathBuf); fn literal_from_str(s: &str) -> Result, ()>; fn emit_diagnostic(diagnostic: Diagnostic<$S::Span>); }, @@ -300,6 +301,7 @@ mark_noop! { LitKind, Level, Spacing, + path::PathBuf, } rpc_encode_decode!( diff --git a/library/proc_macro/src/bridge/rpc.rs b/library/proc_macro/src/bridge/rpc.rs index 5b1bfb30983b2..a4d719cd00b4c 100644 --- a/library/proc_macro/src/bridge/rpc.rs +++ b/library/proc_macro/src/bridge/rpc.rs @@ -3,6 +3,7 @@ use std::any::Any; use std::io::Write; use std::num::NonZeroU32; +use std::path; use std::str; pub(super) type Writer = super::buffer::Buffer; @@ -244,6 +245,18 @@ impl<'a, S, T: for<'s> DecodeMut<'a, 's, S>> DecodeMut<'a, '_, S> for Vec { } } +impl Encode for path::PathBuf { + fn encode(self, w: &mut Writer, s: &mut S) { + self.to_str().expect("`PathBuf`s must be valid UTF-8 for now!").encode(w, s); + } +} + +impl DecodeMut<'_, '_, S> for path::PathBuf { + fn decode(r: &mut Reader<'_>, s: &mut S) -> Self { + path::PathBuf::from(<&str>::decode(r, s)) + } +} + /// Simplified version of panic payloads, ignoring /// types other than `&'static str` and `String`. pub enum PanicMessage { diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 0a70c488aec91..d7177831d77b7 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -1489,8 +1489,8 @@ impl fmt::Debug for Literal { } } -/// Tracked access to environment variables. -#[unstable(feature = "proc_macro_tracked_env", issue = "99515")] +#[unstable(feature = "proc_macro_tracked_env", issue = "74690")] +/// Tracked access to env variables. pub mod tracked_env { use std::env::{self, VarError}; use std::ffi::OsStr; @@ -1500,7 +1500,7 @@ pub mod tracked_env { /// compilation, and will be able to rerun the build when the value of that variable changes. /// Besides the dependency tracking this function should be equivalent to `env::var` from the /// standard library, except that the argument must be UTF-8. - #[unstable(feature = "proc_macro_tracked_env", issue = "99515")] + #[unstable(feature = "proc_macro_tracked_env", issue = "74690")] pub fn var + AsRef>(key: K) -> Result { let key: &str = key.as_ref(); let value = env::var(key); @@ -1510,15 +1510,23 @@ pub mod tracked_env { } /// Tracked access to additional files. -#[unstable(feature = "track_path", issue = "99515")] +#[unstable(feature = "proc_macro_tracked_path", issue = "99515")] pub mod tracked_path { + use std::path::{Path, PathBuf}; - /// Track a file explicitly. + /// Track a file as if it was a dependency. + /// + /// The file is located relative to the current file where the proc-macro + /// is used (similarly to how modules are found). The provided path is + /// interpreted in a platform-specific way at compile time. So, for + /// instance, an invocation with a Windows path + /// containing backslashes `\` would not compile correctly on Unix. + /// + /// Errors if the provided `Path` cannot be encoded as a `str` /// /// Commonly used for tracking asset preprocessing. - #[unstable(feature = "track_path", issue = "99515")] - pub fn path>(path: P) { - let path: &str = path.as_ref(); + pub fn path>(path: P) { + let path = PathBuf::from(path.as_ref()); crate::bridge::client::FreeFunctions::track_path(path); } } diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs index d47767faed9ed..cb274876bb369 100644 --- a/src/tools/clippy/src/driver.rs +++ b/src/tools/clippy/src/driver.rs @@ -80,7 +80,7 @@ fn track_files(parse_sess: &mut ParseSess) { // Used by `clippy::cargo` lints and to determine the MSRV. `cargo clippy` executes `clippy-driver` // with the current directory set to `CARGO_MANIFEST_DIR` so a relative path is fine if Path::new("Cargo.toml").exists() { - file_depinfo.insert(Symbol::intern("Cargo.toml")); + file_depinfo.insert(std::path::PathBuf::from("Cargo.toml")); } // `clippy.toml` will be automatically tracked as it's loaded with `sess.source_map().load_file()` @@ -95,7 +95,7 @@ fn track_files(parse_sess: &mut ParseSess) { if let Ok(current_exe) = env::current_exe() && let Some(current_exe) = current_exe.to_str() { - file_depinfo.insert(Symbol::intern(current_exe)); + file_depinfo.insert(std::path::PathBuf::from(current_exe)); } } } diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server.rs index fe18451d38482..d9e3384c52c7b 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server.rs @@ -58,7 +58,7 @@ impl server::FreeFunctions for RustAnalyzer { // FIXME: track env var accesses // https://github.com/rust-lang/rust/pull/71858 } - fn track_path(&mut self, _path: &str) {} + fn track_path(&mut self, _path: std::path::PathBuf) {} fn literal_from_str( &mut self, diff --git a/tests/run-make/env-dep-info/macro_def.rs b/tests/run-make/env-dep-info/macro_def.rs index e328eae48326d..a38d40554b406 100644 --- a/tests/run-make/env-dep-info/macro_def.rs +++ b/tests/run-make/env-dep-info/macro_def.rs @@ -1,5 +1,5 @@ -#![feature(proc_macro_tracked_env)] #![crate_type = "proc-macro"] +#![feature(proc_macro_tracked_env)] extern crate proc_macro; use proc_macro::*; diff --git a/tests/run-make/track-path-dep-info/macro_def.rs b/tests/run-make/track-path-dep-info/macro_def.rs index 8777ce21f8b82..216f9ecec9e8a 100644 --- a/tests/run-make/track-path-dep-info/macro_def.rs +++ b/tests/run-make/track-path-dep-info/macro_def.rs @@ -1,11 +1,23 @@ -#![feature(track_path)] #![crate_type = "proc-macro"] +#![feature(proc_macro_tracked_path)] extern crate proc_macro; use proc_macro::*; +use std::str; + #[proc_macro] pub fn access_tracked_paths(_: TokenStream) -> TokenStream { tracked_path::path("emojis.txt"); + + // currently only valid utf-8 paths are supported + if false { + let invalid = [1_u8, 2,123, 254, 0, 0, 1, 1]; + let invalid: &str = unsafe { + str::from_utf8_unchecked(&invalid[..]) + }; + tracked_path::path(invalid); + } + TokenStream::new() }