From f8a7fd5a4d7a0319226bf9ac79e9deced4afe1bf Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sat, 29 Nov 2025 20:54:34 +0100 Subject: [PATCH] internal: Ensure proc-macro-api version check works with postcard across protocol versions --- crates/hir-def/src/lang_item.rs | 5 +++-- .../proc-macro-api/src/legacy_protocol/msg.rs | 22 ++++++++++++------- crates/proc-macro-srv/src/lib.rs | 8 ++++++- .../src/server_impl/token_id.rs | 18 ++++++++++++--- 4 files changed, 39 insertions(+), 14 deletions(-) diff --git a/crates/hir-def/src/lang_item.rs b/crates/hir-def/src/lang_item.rs index 31e9d8749d71..9feca9fd7987 100644 --- a/crates/hir-def/src/lang_item.rs +++ b/crates/hir-def/src/lang_item.rs @@ -161,11 +161,12 @@ pub enum GenericRequirement { macro_rules! language_item_table { ( + $LangItems:ident => $( $(#[$attr:meta])* $lang_item:ident, $module:ident :: $name:ident, $method:ident, $target:ident, $generics:expr; )* ) => { #[allow(non_snake_case)] // FIXME: Should we remove this? #[derive(Debug, Default, Clone, PartialEq, Eq, Hash)] - pub struct LangItems { + pub struct $LangItems { $( $(#[$attr])* pub $lang_item: Option<$target>, @@ -219,7 +220,7 @@ macro_rules! language_item_table { } } -language_item_table! { +language_item_table! { LangItems => // Variant name, Name, Getter method name, Target Generic requirements; Sized, sym::sized, sized_trait, TraitId, GenericRequirement::Exact(0); MetaSized, sym::meta_sized, sized_trait, TraitId, GenericRequirement::Exact(0); diff --git a/crates/proc-macro-api/src/legacy_protocol/msg.rs b/crates/proc-macro-api/src/legacy_protocol/msg.rs index b0e80dedcde6..680372210a25 100644 --- a/crates/proc-macro-api/src/legacy_protocol/msg.rs +++ b/crates/proc-macro-api/src/legacy_protocol/msg.rs @@ -13,6 +13,13 @@ use crate::{ProcMacroKind, codec::Codec}; /// Represents requests sent from the client to the proc-macro-srv. #[derive(Debug, Serialize, Deserialize)] pub enum Request { + // IMPORTANT: Keep his first, otherwise postcard will break as its not a self describing format + // As such, this is the only request that needs to be supported across all protocol versions + // and by keeping it first, we ensure it always has the same discriminant encoding in postcard + /// Performs an API version check between the client and the server. + /// Since [`VERSION_CHECK_VERSION`] + ApiVersionCheck {}, + /// Retrieves a list of macros from a given dynamic library. /// Since [`NO_VERSION_CHECK_VERSION`] ListMacros { dylib_path: Utf8PathBuf }, @@ -21,10 +28,6 @@ pub enum Request { /// Since [`NO_VERSION_CHECK_VERSION`] ExpandMacro(Box), - /// Performs an API version check between the client and the server. - /// Since [`VERSION_CHECK_VERSION`] - ApiVersionCheck {}, - /// Sets server-specific configurations. /// Since [`RUST_ANALYZER_SPAN_SUPPORT`] SetConfig(ServerConfig), @@ -44,6 +47,13 @@ pub enum SpanMode { /// Represents responses sent from the proc-macro-srv to the client. #[derive(Debug, Serialize, Deserialize)] pub enum Response { + // IMPORTANT: Keep his first, otherwise postcard will break as its not a self describing format + // As such, this is the only request that needs to be supported across all protocol versions + // and by keeping it first, we ensure it always has the same discriminant encoding in postcard + /// Returns the API version supported by the server. + /// Since [`NO_VERSION_CHECK_VERSION`] + ApiVersionCheck(u32), + /// Returns a list of available macros in a dynamic library. /// Since [`NO_VERSION_CHECK_VERSION`] ListMacros(Result, String>), @@ -52,10 +62,6 @@ pub enum Response { /// Since [`NO_VERSION_CHECK_VERSION`] ExpandMacro(Result), - /// Returns the API version supported by the server. - /// Since [`NO_VERSION_CHECK_VERSION`] - ApiVersionCheck(u32), - /// Confirms the application of a configuration update. /// Since [`RUST_ANALYZER_SPAN_SUPPORT`] SetConfig(ServerConfig), diff --git a/crates/proc-macro-srv/src/lib.rs b/crates/proc-macro-srv/src/lib.rs index 0ac58d740e54..c3838a8e613b 100644 --- a/crates/proc-macro-srv/src/lib.rs +++ b/crates/proc-macro-srv/src/lib.rs @@ -198,7 +198,13 @@ impl ProcMacroSrvSpan for SpanId { type Server = server_impl::token_id::SpanIdServer; fn make_server(call_site: Self, def_site: Self, mixed_site: Self) -> Self::Server { - Self::Server { call_site, def_site, mixed_site } + Self::Server { + call_site, + def_site, + mixed_site, + tracked_env_vars: Default::default(), + tracked_paths: Default::default(), + } } } impl ProcMacroSrvSpan for Span { diff --git a/crates/proc-macro-srv/src/server_impl/token_id.rs b/crates/proc-macro-srv/src/server_impl/token_id.rs index 3814320cbe96..5ac263b9d5f6 100644 --- a/crates/proc-macro-srv/src/server_impl/token_id.rs +++ b/crates/proc-macro-srv/src/server_impl/token_id.rs @@ -1,6 +1,9 @@ //! proc-macro server backend based on [`proc_macro_api::msg::SpanId`] as the backing span. //! This backend is rather inflexible, used by RustRover and older rust-analyzer versions. -use std::ops::{Bound, Range}; +use std::{ + collections::{HashMap, HashSet}, + ops::{Bound, Range}, +}; use intern::Symbol; use proc_macro::bridge::server; @@ -24,6 +27,10 @@ type Span = SpanId; pub struct FreeFunctions; pub struct SpanIdServer { + // FIXME: Report this back to the caller to track as dependencies + pub tracked_env_vars: HashMap, Option>>, + // FIXME: Report this back to the caller to track as dependencies + pub tracked_paths: HashSet>, pub call_site: Span, pub def_site: Span, pub mixed_site: Span, @@ -40,8 +47,13 @@ impl server::FreeFunctions for SpanIdServer { fn injected_env_var(&mut self, _: &str) -> Option { None } - fn track_env_var(&mut self, _var: &str, _value: Option<&str>) {} - fn track_path(&mut self, _path: &str) {} + fn track_env_var(&mut self, var: &str, value: Option<&str>) { + self.tracked_env_vars.insert(var.into(), value.map(Into::into)); + } + fn track_path(&mut self, path: &str) { + self.tracked_paths.insert(path.into()); + } + fn literal_from_str(&mut self, s: &str) -> Result, ()> { literal_from_str(s, self.call_site) }