From 66368aa629ff844aa6e92ed49dc6ed12bc65f4e5 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 27 Feb 2025 16:49:37 +0100 Subject: [PATCH 01/53] Allow unsetting default cfgs --- .../rust-analyzer/crates/cfg/src/cfg_expr.rs | 19 +++++++ src/tools/rust-analyzer/crates/cfg/src/dnf.rs | 19 ++----- src/tools/rust-analyzer/crates/cfg/src/lib.rs | 20 ++++--- .../crates/project-model/src/tests.rs | 4 +- .../crates/project-model/src/workspace.rs | 8 +-- .../rust-analyzer/src/cli/analysis_stats.rs | 2 +- .../crates/rust-analyzer/src/config.rs | 56 +++++++++++-------- .../crates/rust-analyzer/src/flycheck.rs | 26 +++++---- .../docs/book/src/configuration_generated.md | 4 ++ .../rust-analyzer/editors/code/package.json | 2 +- 10 files changed, 96 insertions(+), 64 deletions(-) diff --git a/src/tools/rust-analyzer/crates/cfg/src/cfg_expr.rs b/src/tools/rust-analyzer/crates/cfg/src/cfg_expr.rs index 84b91a527f055..0ec082dfa7fcb 100644 --- a/src/tools/rust-analyzer/crates/cfg/src/cfg_expr.rs +++ b/src/tools/rust-analyzer/crates/cfg/src/cfg_expr.rs @@ -18,6 +18,25 @@ pub enum CfgAtom { KeyValue { key: Symbol, value: Symbol }, } +impl PartialOrd for CfgAtom { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for CfgAtom { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + match (self, other) { + (CfgAtom::Flag(a), CfgAtom::Flag(b)) => a.as_str().cmp(b.as_str()), + (CfgAtom::Flag(_), CfgAtom::KeyValue { .. }) => std::cmp::Ordering::Less, + (CfgAtom::KeyValue { .. }, CfgAtom::Flag(_)) => std::cmp::Ordering::Greater, + (CfgAtom::KeyValue { key, value }, CfgAtom::KeyValue { key: key2, value: value2 }) => { + key.as_str().cmp(key2.as_str()).then(value.as_str().cmp(value2.as_str())) + } + } + } +} + impl fmt::Display for CfgAtom { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { diff --git a/src/tools/rust-analyzer/crates/cfg/src/dnf.rs b/src/tools/rust-analyzer/crates/cfg/src/dnf.rs index f3ebca0465098..424672a275e5b 100644 --- a/src/tools/rust-analyzer/crates/cfg/src/dnf.rs +++ b/src/tools/rust-analyzer/crates/cfg/src/dnf.rs @@ -66,9 +66,9 @@ impl DnfExpr { } } - res.enabled.sort_unstable_by(compare); + res.enabled.sort_unstable(); res.enabled.dedup(); - res.disabled.sort_unstable_by(compare); + res.disabled.sort_unstable(); res.disabled.dedup(); Some(res) } @@ -114,25 +114,14 @@ impl DnfExpr { }; // Undo the FxHashMap randomization for consistent output. - diff.enable.sort_unstable_by(compare); - diff.disable.sort_unstable_by(compare); + diff.enable.sort_unstable(); + diff.disable.sort_unstable(); Some(diff) }) } } -fn compare(a: &CfgAtom, b: &CfgAtom) -> std::cmp::Ordering { - match (a, b) { - (CfgAtom::Flag(a), CfgAtom::Flag(b)) => a.as_str().cmp(b.as_str()), - (CfgAtom::Flag(_), CfgAtom::KeyValue { .. }) => std::cmp::Ordering::Less, - (CfgAtom::KeyValue { .. }, CfgAtom::Flag(_)) => std::cmp::Ordering::Greater, - (CfgAtom::KeyValue { key, value }, CfgAtom::KeyValue { key: key2, value: value2 }) => { - key.as_str().cmp(key2.as_str()).then(value.as_str().cmp(value2.as_str())) - } - } -} - impl fmt::Display for DnfExpr { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if self.conjunctions.len() != 1 { diff --git a/src/tools/rust-analyzer/crates/cfg/src/lib.rs b/src/tools/rust-analyzer/crates/cfg/src/lib.rs index 6a6213a871fda..08545b685119d 100644 --- a/src/tools/rust-analyzer/crates/cfg/src/lib.rs +++ b/src/tools/rust-analyzer/crates/cfg/src/lib.rs @@ -148,16 +148,20 @@ pub struct CfgDiff { } impl CfgDiff { - /// Create a new CfgDiff. Will return None if the same item appears more than once in the set - /// of both. - pub fn new(enable: Vec, disable: Vec) -> Option { - let mut occupied = FxHashSet::default(); - if enable.iter().chain(disable.iter()).any(|item| !occupied.insert(item)) { - // was present - return None; + /// Create a new CfgDiff. + pub fn new(mut enable: Vec, mut disable: Vec) -> CfgDiff { + enable.sort(); + enable.dedup(); + disable.sort(); + disable.dedup(); + for i in (0..enable.len()).rev() { + if let Some(j) = disable.iter().position(|atom| *atom == enable[i]) { + enable.remove(i); + disable.remove(j); + } } - Some(CfgDiff { enable, disable }) + CfgDiff { enable, disable } } /// Returns the total number of atoms changed by this diff. diff --git a/src/tools/rust-analyzer/crates/project-model/src/tests.rs b/src/tools/rust-analyzer/crates/project-model/src/tests.rs index cfc666970bd6a..837406227323e 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/tests.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/tests.rs @@ -166,7 +166,7 @@ fn check_crate_graph(crate_graph: CrateGraph, expect: ExpectFile) { #[test] fn cargo_hello_world_project_model_with_wildcard_overrides() { let cfg_overrides = CfgOverrides { - global: CfgDiff::new(Vec::new(), vec![CfgAtom::Flag(sym::test.clone())]).unwrap(), + global: CfgDiff::new(Vec::new(), vec![CfgAtom::Flag(sym::test.clone())]), selective: Default::default(), }; let (crate_graph, _proc_macros) = @@ -185,7 +185,7 @@ fn cargo_hello_world_project_model_with_selective_overrides() { global: Default::default(), selective: std::iter::once(( "libc".to_owned(), - CfgDiff::new(Vec::new(), vec![CfgAtom::Flag(sym::test.clone())]).unwrap(), + CfgDiff::new(Vec::new(), vec![CfgAtom::Flag(sym::test.clone())]), )) .collect(), }; diff --git a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs index 6b6fb5f9ec1f0..8321d41466ebb 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs @@ -1522,7 +1522,7 @@ fn extend_crate_graph_with_sysroot( ) -> (SysrootPublicDeps, Option) { let mut pub_deps = vec![]; let mut libproc_macro = None; - let diff = CfgDiff::new(vec![], vec![CfgAtom::Flag(sym::test.clone())]).unwrap(); + let diff = CfgDiff::new(vec![], vec![CfgAtom::Flag(sym::test.clone())]); for (cid, c) in sysroot_crate_graph.iter_mut() { // uninject `test` flag so `core` keeps working. Arc::make_mut(&mut c.cfg_options).apply_diff(diff.clone()); @@ -1596,8 +1596,7 @@ fn sysroot_to_crate_graph( CfgAtom::Flag(sym::miri.clone()), ], vec![], - ) - .unwrap(), + ), ..Default::default() }, &WorkspaceBuildScripts::default(), @@ -1620,8 +1619,7 @@ fn sysroot_to_crate_graph( CfgAtom::Flag(sym::miri.clone()), ], vec![], - ) - .unwrap(), + ), ..Default::default() }, false, diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs index 4fc6180920f5f..b9e4457fc98d8 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -69,7 +69,7 @@ impl flags::AnalysisStats { all_targets: true, set_test: !self.no_test, cfg_overrides: CfgOverrides { - global: CfgDiff::new(vec![CfgAtom::Flag(hir::sym::miri.clone())], vec![]).unwrap(), + global: CfgDiff::new(vec![CfgAtom::Flag(hir::sym::miri.clone())], vec![]), selective: Default::default(), }, ..Default::default() diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index 713e28c87cbe9..45ac68339b38c 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -18,7 +18,7 @@ use ide_db::{ imports::insert_use::{ImportGranularity, InsertUseConfig, PrefixKind}, SnippetCap, }; -use itertools::Itertools; +use itertools::{Either, Itertools}; use paths::{Utf8Path, Utf8PathBuf}; use project_model::{ CargoConfig, CargoFeatures, ProjectJson, ProjectJsonData, ProjectJsonFromCommand, @@ -589,6 +589,10 @@ config_data! { /// avoid checking unnecessary things. cargo_buildScripts_useRustcWrapper: bool = true, /// List of cfg options to enable with the given values. + /// + /// To enable a name without a value, use `"key"`. + /// To enable a name with a value, use `"key=value"`. + /// To disable, prefix the entry with a `!`. cargo_cfgs: Vec = { vec!["debug_assertions".into(), "miri".into()] }, @@ -1980,27 +1984,35 @@ impl Config { rustc_source, extra_includes, cfg_overrides: project_model::CfgOverrides { - global: CfgDiff::new( - self.cargo_cfgs(source_root) - .iter() - // parse any cfg setting formatted as key=value or just key (without value) - .filter_map(|s| { - let mut sp = s.splitn(2, "="); - let key = sp.next(); - let val = sp.next(); - key.map(|key| (key, val)) - }) - .map(|(key, val)| match val { - Some(val) => CfgAtom::KeyValue { - key: Symbol::intern(key), - value: Symbol::intern(val), - }, - None => CfgAtom::Flag(Symbol::intern(key)), - }) - .collect(), - vec![], - ) - .unwrap(), + global: { + let (enabled, disabled): (Vec<_>, Vec<_>) = + self.cargo_cfgs(source_root).iter().partition_map(|s| { + s.strip_prefix("!").map_or(Either::Left(s), Either::Right) + }); + CfgDiff::new( + enabled + .into_iter() + // parse any cfg setting formatted as key=value or just key (without value) + .map(|s| match s.split_once("=") { + Some((key, val)) => CfgAtom::KeyValue { + key: Symbol::intern(key), + value: Symbol::intern(val), + }, + None => CfgAtom::Flag(Symbol::intern(s)), + }) + .collect(), + disabled + .into_iter() + .map(|s| match s.split_once("=") { + Some((key, val)) => CfgAtom::KeyValue { + key: Symbol::intern(key), + value: Symbol::intern(val), + }, + None => CfgAtom::Flag(Symbol::intern(s)), + }) + .collect(), + ) + }, selective: Default::default(), }, wrap_rustc_in_build_scripts: *self.cargo_buildScripts_useRustcWrapper(source_root), diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs index 2309f94a7429b..7529e7c188f8a 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs @@ -244,8 +244,14 @@ struct FlycheckActor { /// The receiver side of the channel mentioned above. command_receiver: Option>, diagnostics_cleared_for: FxHashSet>, - diagnostics_cleared_for_all: bool, - diagnostics_received: bool, + diagnostics_received: DiagnosticsReceived, +} + +#[derive(PartialEq)] +enum DiagnosticsReceived { + Yes, + No, + YesAndClearedForAll, } #[allow(clippy::large_enum_variant)] @@ -276,8 +282,7 @@ impl FlycheckActor { command_handle: None, command_receiver: None, diagnostics_cleared_for: Default::default(), - diagnostics_cleared_for_all: false, - diagnostics_received: false, + diagnostics_received: DiagnosticsReceived::No, } } @@ -354,7 +359,7 @@ impl FlycheckActor { error ); } - if !self.diagnostics_received { + if self.diagnostics_received == DiagnosticsReceived::No { tracing::trace!(flycheck_id = self.id, "clearing diagnostics"); // We finished without receiving any diagnostics. // Clear everything for good measure @@ -396,7 +401,7 @@ impl FlycheckActor { package_id = package_id.as_ref().map(|it| &it.repr), "diagnostic received" ); - self.diagnostics_received = true; + self.diagnostics_received = DiagnosticsReceived::Yes; if let Some(package_id) = &package_id { if self.diagnostics_cleared_for.insert(package_id.clone()) { tracing::trace!( @@ -409,8 +414,10 @@ impl FlycheckActor { package_id: Some(package_id.clone()), }); } - } else if !self.diagnostics_cleared_for_all { - self.diagnostics_cleared_for_all = true; + } else if self.diagnostics_received + != DiagnosticsReceived::YesAndClearedForAll + { + self.diagnostics_received = DiagnosticsReceived::YesAndClearedForAll; self.send(FlycheckMessage::ClearDiagnostics { id: self.id, package_id: None, @@ -445,8 +452,7 @@ impl FlycheckActor { fn clear_diagnostics_state(&mut self) { self.diagnostics_cleared_for.clear(); - self.diagnostics_cleared_for_all = false; - self.diagnostics_received = false; + self.diagnostics_received = DiagnosticsReceived::No; } /// Construct a `Command` object for checking the user's code. If the user diff --git a/src/tools/rust-analyzer/docs/book/src/configuration_generated.md b/src/tools/rust-analyzer/docs/book/src/configuration_generated.md index 1cbe51836f470..0a612d20b9cc1 100644 --- a/src/tools/rust-analyzer/docs/book/src/configuration_generated.md +++ b/src/tools/rust-analyzer/docs/book/src/configuration_generated.md @@ -102,6 +102,10 @@ Default: List of cfg options to enable with the given values. +To enable a name without a value, use `"key"`. +To enable a name with a value, use `"key=value"`. +To disable, prefix the entry with a `!`. + **rust-analyzer.cargo.extraArgs** (default: []) diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json index a7c8506a45e6d..df0a9466a56a8 100644 --- a/src/tools/rust-analyzer/editors/code/package.json +++ b/src/tools/rust-analyzer/editors/code/package.json @@ -818,7 +818,7 @@ "title": "cargo", "properties": { "rust-analyzer.cargo.cfgs": { - "markdownDescription": "List of cfg options to enable with the given values.", + "markdownDescription": "List of cfg options to enable with the given values.\n\nTo enable a name without a value, use `\"key\"`.\nTo enable a name with a value, use `\"key=value\"`.\nTo disable, prefix the entry with a `!`.", "default": [ "debug_assertions", "miri" From f19b205df4cf90067c9590a752b3de46df4baf22 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 27 Feb 2025 17:40:10 +0100 Subject: [PATCH 02/53] Warn when the used toolchain looks too old for rust-analyzer --- .../rust-analyzer/src/handlers/request.rs | 2 +- .../crates/rust-analyzer/src/lib.rs | 121 ++---------------- .../crates/rust-analyzer/src/lsp.rs | 113 ++++++++++++++++ .../crates/rust-analyzer/src/lsp/to_proto.rs | 2 +- .../crates/rust-analyzer/src/reload.rs | 16 +++ 5 files changed, 140 insertions(+), 114 deletions(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs index b91a5dbd4166f..4ab96e9e2d58e 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs @@ -32,13 +32,13 @@ use triomphe::Arc; use vfs::{AbsPath, AbsPathBuf, FileId, VfsPath}; use crate::{ - completion_item_hash, config::{Config, RustfmtConfig, WorkspaceSymbolConfig}, diagnostics::convert_diagnostic, global_state::{FetchWorkspaceRequest, GlobalState, GlobalStateSnapshot}, hack_recover_crate_name, line_index::LineEndings, lsp::{ + completion_item_hash, ext::{ InternalTestingFetchConfigOption, InternalTestingFetchConfigParams, InternalTestingFetchConfigResponse, diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs index 27d6225cdb7e2..a0d6a0d6da6f8 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs @@ -9,6 +9,15 @@ //! The `cli` submodule implements some batch-processing analysis, primarily as //! a debugging aid. +/// Any toolchain less than this version will likely not work with rust-analyzer built from this revision. +pub const MINIMUM_SUPPORTED_TOOLCHAIN_VERSION: semver::Version = semver::Version { + major: 1, + minor: 78, + patch: 0, + pre: semver::Prerelease::EMPTY, + build: semver::BuildMetadata::EMPTY, +}; + pub mod cli; mod command; @@ -47,10 +56,7 @@ use self::lsp::ext as lsp_ext; #[cfg(test)] mod integrated_benchmarks; -use hir::Mutability; -use ide::{CompletionItem, CompletionItemRefMode, CompletionRelevance}; use serde::de::DeserializeOwned; -use tenthash::TentHash; pub use crate::{ lsp::capabilities::server_capabilities, main_loop::main_loop, reload::ws_to_crate_graph, @@ -65,115 +71,6 @@ pub fn from_json( .map_err(|e| anyhow::format_err!("Failed to deserialize {what}: {e}; {json}")) } -fn completion_item_hash(item: &CompletionItem, is_ref_completion: bool) -> [u8; 20] { - fn hash_completion_relevance(hasher: &mut TentHash, relevance: &CompletionRelevance) { - use ide_completion::{ - CompletionRelevancePostfixMatch, CompletionRelevanceReturnType, - CompletionRelevanceTypeMatch, - }; - - hasher.update([ - u8::from(relevance.exact_name_match), - u8::from(relevance.is_local), - u8::from(relevance.is_name_already_imported), - u8::from(relevance.requires_import), - u8::from(relevance.is_private_editable), - ]); - - match relevance.type_match { - None => hasher.update([0u8]), - Some(CompletionRelevanceTypeMatch::CouldUnify) => hasher.update([1u8]), - Some(CompletionRelevanceTypeMatch::Exact) => hasher.update([2u8]), - } - - hasher.update([u8::from(relevance.trait_.is_some())]); - if let Some(trait_) = &relevance.trait_ { - hasher.update([u8::from(trait_.is_op_method), u8::from(trait_.notable_trait)]); - } - - match relevance.postfix_match { - None => hasher.update([0u8]), - Some(CompletionRelevancePostfixMatch::NonExact) => hasher.update([1u8]), - Some(CompletionRelevancePostfixMatch::Exact) => hasher.update([2u8]), - } - - hasher.update([u8::from(relevance.function.is_some())]); - if let Some(function) = &relevance.function { - hasher.update([u8::from(function.has_params), u8::from(function.has_self_param)]); - let discriminant: u8 = match function.return_type { - CompletionRelevanceReturnType::Other => 0, - CompletionRelevanceReturnType::DirectConstructor => 1, - CompletionRelevanceReturnType::Constructor => 2, - CompletionRelevanceReturnType::Builder => 3, - }; - hasher.update([discriminant]); - } - } - - let mut hasher = TentHash::new(); - hasher.update([ - u8::from(is_ref_completion), - u8::from(item.is_snippet), - u8::from(item.deprecated), - u8::from(item.trigger_call_info), - ]); - - hasher.update(item.label.primary.len().to_ne_bytes()); - hasher.update(&item.label.primary); - - hasher.update([u8::from(item.label.detail_left.is_some())]); - if let Some(label_detail) = &item.label.detail_left { - hasher.update(label_detail.len().to_ne_bytes()); - hasher.update(label_detail); - } - - hasher.update([u8::from(item.label.detail_right.is_some())]); - if let Some(label_detail) = &item.label.detail_right { - hasher.update(label_detail.len().to_ne_bytes()); - hasher.update(label_detail); - } - - // NB: do not hash edits or source range, as those may change between the time the client sends the resolve request - // and the time it receives it: some editors do allow changing the buffer between that, leading to ranges being different. - // - // Documentation hashing is skipped too, as it's a large blob to process, - // while not really making completion properties more unique as they are already. - - let kind_tag = item.kind.tag(); - hasher.update(kind_tag.len().to_ne_bytes()); - hasher.update(kind_tag); - - hasher.update(item.lookup.len().to_ne_bytes()); - hasher.update(&item.lookup); - - hasher.update([u8::from(item.detail.is_some())]); - if let Some(detail) = &item.detail { - hasher.update(detail.len().to_ne_bytes()); - hasher.update(detail); - } - - hash_completion_relevance(&mut hasher, &item.relevance); - - hasher.update([u8::from(item.ref_match.is_some())]); - if let Some((ref_mode, text_size)) = &item.ref_match { - let discriminant = match ref_mode { - CompletionItemRefMode::Reference(Mutability::Shared) => 0u8, - CompletionItemRefMode::Reference(Mutability::Mut) => 1u8, - CompletionItemRefMode::Dereference => 2u8, - }; - hasher.update([discriminant]); - hasher.update(u32::from(*text_size).to_ne_bytes()); - } - - hasher.update(item.import_to_add.len().to_ne_bytes()); - for import_path in &item.import_to_add { - hasher.update(import_path.len().to_ne_bytes()); - hasher.update(import_path); - } - - hasher.finalize() -} - #[doc(hidden)] macro_rules! try_default_ { ($it:expr $(,)?) => { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp.rs index 122ad20d65ee6..c7a5a95e66bbf 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp.rs @@ -2,6 +2,10 @@ use core::fmt; +use hir::Mutability; +use ide::{CompletionItem, CompletionItemRefMode, CompletionRelevance}; +use tenthash::TentHash; + pub mod ext; pub(crate) mod capabilities; @@ -29,3 +33,112 @@ impl fmt::Display for LspError { } impl std::error::Error for LspError {} + +pub(crate) fn completion_item_hash(item: &CompletionItem, is_ref_completion: bool) -> [u8; 20] { + fn hash_completion_relevance(hasher: &mut TentHash, relevance: &CompletionRelevance) { + use ide_completion::{ + CompletionRelevancePostfixMatch, CompletionRelevanceReturnType, + CompletionRelevanceTypeMatch, + }; + + hasher.update([ + u8::from(relevance.exact_name_match), + u8::from(relevance.is_local), + u8::from(relevance.is_name_already_imported), + u8::from(relevance.requires_import), + u8::from(relevance.is_private_editable), + ]); + + match relevance.type_match { + None => hasher.update([0u8]), + Some(CompletionRelevanceTypeMatch::CouldUnify) => hasher.update([1u8]), + Some(CompletionRelevanceTypeMatch::Exact) => hasher.update([2u8]), + } + + hasher.update([u8::from(relevance.trait_.is_some())]); + if let Some(trait_) = &relevance.trait_ { + hasher.update([u8::from(trait_.is_op_method), u8::from(trait_.notable_trait)]); + } + + match relevance.postfix_match { + None => hasher.update([0u8]), + Some(CompletionRelevancePostfixMatch::NonExact) => hasher.update([1u8]), + Some(CompletionRelevancePostfixMatch::Exact) => hasher.update([2u8]), + } + + hasher.update([u8::from(relevance.function.is_some())]); + if let Some(function) = &relevance.function { + hasher.update([u8::from(function.has_params), u8::from(function.has_self_param)]); + let discriminant: u8 = match function.return_type { + CompletionRelevanceReturnType::Other => 0, + CompletionRelevanceReturnType::DirectConstructor => 1, + CompletionRelevanceReturnType::Constructor => 2, + CompletionRelevanceReturnType::Builder => 3, + }; + hasher.update([discriminant]); + } + } + + let mut hasher = TentHash::new(); + hasher.update([ + u8::from(is_ref_completion), + u8::from(item.is_snippet), + u8::from(item.deprecated), + u8::from(item.trigger_call_info), + ]); + + hasher.update(item.label.primary.len().to_ne_bytes()); + hasher.update(&item.label.primary); + + hasher.update([u8::from(item.label.detail_left.is_some())]); + if let Some(label_detail) = &item.label.detail_left { + hasher.update(label_detail.len().to_ne_bytes()); + hasher.update(label_detail); + } + + hasher.update([u8::from(item.label.detail_right.is_some())]); + if let Some(label_detail) = &item.label.detail_right { + hasher.update(label_detail.len().to_ne_bytes()); + hasher.update(label_detail); + } + + // NB: do not hash edits or source range, as those may change between the time the client sends the resolve request + // and the time it receives it: some editors do allow changing the buffer between that, leading to ranges being different. + // + // Documentation hashing is skipped too, as it's a large blob to process, + // while not really making completion properties more unique as they are already. + + let kind_tag = item.kind.tag(); + hasher.update(kind_tag.len().to_ne_bytes()); + hasher.update(kind_tag); + + hasher.update(item.lookup.len().to_ne_bytes()); + hasher.update(&item.lookup); + + hasher.update([u8::from(item.detail.is_some())]); + if let Some(detail) = &item.detail { + hasher.update(detail.len().to_ne_bytes()); + hasher.update(detail); + } + + hash_completion_relevance(&mut hasher, &item.relevance); + + hasher.update([u8::from(item.ref_match.is_some())]); + if let Some((ref_mode, text_size)) = &item.ref_match { + let discriminant = match ref_mode { + CompletionItemRefMode::Reference(Mutability::Shared) => 0u8, + CompletionItemRefMode::Reference(Mutability::Mut) => 1u8, + CompletionItemRefMode::Dereference => 2u8, + }; + hasher.update([discriminant]); + hasher.update(u32::from(*text_size).to_ne_bytes()); + } + + hasher.update(item.import_to_add.len().to_ne_bytes()); + for import_path in &item.import_to_add { + hasher.update(import_path.len().to_ne_bytes()); + hasher.update(import_path); + } + + hasher.finalize() +} diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs index 446549c907007..3c206f47db5e5 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs @@ -24,11 +24,11 @@ use serde_json::to_value; use vfs::AbsPath; use crate::{ - completion_item_hash, config::{CallInfoConfig, Config}, global_state::GlobalStateSnapshot, line_index::{LineEndings, LineIndex, PositionEncoding}, lsp::{ + completion_item_hash, ext::ShellRunnableArgs, semantic_tokens::{self, standard_fallback_type}, utils::invalid_params_error, diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs index 56dcad0eb18b7..733a7c359b8e7 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs @@ -182,6 +182,22 @@ impl GlobalState { self.proc_macro_clients.iter().map(Some).chain(iter::repeat_with(|| None)); for (ws, proc_macro_client) in self.workspaces.iter().zip(proc_macro_clients) { + if let Some(toolchain) = &ws.toolchain { + if *toolchain < crate::MINIMUM_SUPPORTED_TOOLCHAIN_VERSION { + status.health |= lsp_ext::Health::Warning; + format_to!( + message, + "Workspace `{}` is using an outdated toolchain version `{}` but \ + rust-analyzer only supports `{}` and higher.\n\ + Consider using the rust-analyzer rustup component for your toolchain or + upgrade your toolchain to a supported version.\n\n", + ws.manifest_or_root(), + toolchain, + crate::MINIMUM_SUPPORTED_TOOLCHAIN_VERSION, + ); + } + } + if let ProjectWorkspaceKind::Cargo { error: Some(error), .. } | ProjectWorkspaceKind::DetachedFile { cargo: Some((_, _, Some(error))), .. From 43c5e95af9ce0c4315ec44c00eeabe2de0a5c826 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sun, 2 Mar 2025 09:09:12 +0100 Subject: [PATCH 03/53] Normalize some assist names --- ...t.rs => add_explicit_enum_discriminant.rs} | 23 ++- ...ool_to_enum.rs => convert_bool_to_enum.rs} | 96 +++++----- ...ttern_fields.rs => expand_rest_pattern.rs} | 46 +++-- ...c.rs => introduce_named_type_parameter.rs} | 36 ++-- .../crates/ide-assists/src/lib.rs | 60 +++--- .../crates/ide-assists/src/tests/generated.rs | 148 +++++++-------- .../docs/book/src/assists_generated.md | 178 +++++++++--------- 7 files changed, 299 insertions(+), 288 deletions(-) rename src/tools/rust-analyzer/crates/ide-assists/src/handlers/{explicit_enum_discriminant.rs => add_explicit_enum_discriminant.rs} (87%) rename src/tools/rust-analyzer/crates/ide-assists/src/handlers/{bool_to_enum.rs => convert_bool_to_enum.rs} (95%) rename src/tools/rust-analyzer/crates/ide-assists/src/handlers/{fill_record_pattern_fields.rs => expand_rest_pattern.rs} (84%) rename src/tools/rust-analyzer/crates/ide-assists/src/handlers/{introduce_named_generic.rs => introduce_named_type_parameter.rs} (84%) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/explicit_enum_discriminant.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_explicit_enum_discriminant.rs similarity index 87% rename from src/tools/rust-analyzer/crates/ide-assists/src/handlers/explicit_enum_discriminant.rs rename to src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_explicit_enum_discriminant.rs index fafc3448a87ca..1a5de9cb071bb 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/explicit_enum_discriminant.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_explicit_enum_discriminant.rs @@ -8,7 +8,7 @@ use syntax::{ast, AstNode}; use crate::{AssistContext, Assists}; -// Assist: explicit_enum_discriminant +// Assist: add_explicit_enum_discriminant // // Adds explicit discriminant to all enum variants. // @@ -29,7 +29,10 @@ use crate::{AssistContext, Assists}; // Quux = 43, // } // ``` -pub(crate) fn explicit_enum_discriminant(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { +pub(crate) fn add_explicit_enum_discriminant( + acc: &mut Assists, + ctx: &AssistContext<'_>, +) -> Option<()> { let enum_node = ctx.find_node_at_offset::()?; let enum_def = ctx.sema.to_def(&enum_node)?; @@ -50,7 +53,7 @@ pub(crate) fn explicit_enum_discriminant(acc: &mut Assists, ctx: &AssistContext< } acc.add( - AssistId("explicit_enum_discriminant", AssistKind::RefactorRewrite), + AssistId("add_explicit_enum_discriminant", AssistKind::RefactorRewrite), "Add explicit enum discriminants", enum_node.syntax().text_range(), |builder| { @@ -88,12 +91,12 @@ fn add_variant_discriminant( mod tests { use crate::tests::{check_assist, check_assist_not_applicable}; - use super::explicit_enum_discriminant; + use super::add_explicit_enum_discriminant; #[test] fn non_primitive_repr_non_data_bearing_add_discriminant() { check_assist( - explicit_enum_discriminant, + add_explicit_enum_discriminant, r#" enum TheEnum$0 { Foo, @@ -120,7 +123,7 @@ enum TheEnum { #[test] fn primitive_repr_data_bearing_add_discriminant() { check_assist( - explicit_enum_discriminant, + add_explicit_enum_discriminant, r#" #[repr(u8)] $0enum TheEnum { @@ -145,7 +148,7 @@ enum TheEnum { #[test] fn non_primitive_repr_data_bearing_not_applicable() { check_assist_not_applicable( - explicit_enum_discriminant, + add_explicit_enum_discriminant, r#" enum TheEnum$0 { Foo, @@ -159,7 +162,7 @@ enum TheEnum$0 { #[test] fn primitive_repr_non_data_bearing_add_discriminant() { check_assist( - explicit_enum_discriminant, + add_explicit_enum_discriminant, r#" #[repr(i64)] enum TheEnum { @@ -184,7 +187,7 @@ enum TheEnum { #[test] fn discriminants_already_explicit_not_applicable() { check_assist_not_applicable( - explicit_enum_discriminant, + add_explicit_enum_discriminant, r#" enum TheEnum$0 { Foo = 0, @@ -197,7 +200,7 @@ enum TheEnum$0 { #[test] fn empty_enum_not_applicable() { check_assist_not_applicable( - explicit_enum_discriminant, + add_explicit_enum_discriminant, r#" enum TheEnum$0 {} "#, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/bool_to_enum.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_to_enum.rs similarity index 95% rename from src/tools/rust-analyzer/crates/ide-assists/src/handlers/bool_to_enum.rs rename to src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_to_enum.rs index cbd39796241b9..7716e99e604b3 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/bool_to_enum.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_to_enum.rs @@ -26,7 +26,7 @@ use crate::{ utils, }; -// Assist: bool_to_enum +// Assist: convert_bool_to_enum // // This converts boolean local variables, fields, constants, and statics into a new // enum with two variants `Bool::True` and `Bool::False`, as well as replacing @@ -55,14 +55,14 @@ use crate::{ // } // } // ``` -pub(crate) fn bool_to_enum(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { +pub(crate) fn convert_bool_to_enum(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { let BoolNodeData { target_node, name, ty_annotation, initializer, definition } = find_bool_node(ctx)?; let target_module = ctx.sema.scope(&target_node)?.module().nearest_non_block_module(ctx.db()); let target = name.syntax().text_range(); acc.add( - AssistId("bool_to_enum", AssistKind::RefactorRewrite), + AssistId("convert_bool_to_enum", AssistKind::RefactorRewrite), "Convert boolean to enum", target, |edit| { @@ -549,7 +549,7 @@ mod tests { #[test] fn parameter_with_first_param_usage() { check_assist( - bool_to_enum, + convert_bool_to_enum, r#" fn function($0foo: bool, bar: bool) { if foo { @@ -573,7 +573,7 @@ fn function(foo: Bool, bar: bool) { #[test] fn no_duplicate_enums() { check_assist( - bool_to_enum, + convert_bool_to_enum, r#" #[derive(PartialEq, Eq)] enum Bool { True, False } @@ -600,7 +600,7 @@ fn function(foo: bool, bar: Bool) { #[test] fn parameter_with_last_param_usage() { check_assist( - bool_to_enum, + convert_bool_to_enum, r#" fn function(foo: bool, $0bar: bool) { if bar { @@ -624,7 +624,7 @@ fn function(foo: bool, bar: Bool) { #[test] fn parameter_with_middle_param_usage() { check_assist( - bool_to_enum, + convert_bool_to_enum, r#" fn function(foo: bool, $0bar: bool, baz: bool) { if bar { @@ -648,7 +648,7 @@ fn function(foo: bool, bar: Bool, baz: bool) { #[test] fn parameter_with_closure_usage() { check_assist( - bool_to_enum, + convert_bool_to_enum, r#" fn main() { let foo = |$0bar: bool| bar; @@ -668,7 +668,7 @@ fn main() { #[test] fn local_variable_with_usage() { check_assist( - bool_to_enum, + convert_bool_to_enum, r#" fn main() { let $0foo = true; @@ -697,7 +697,7 @@ fn main() { fn local_variable_with_usage_negated() { cov_mark::check!(replaces_negation); check_assist( - bool_to_enum, + convert_bool_to_enum, r#" fn main() { let $0foo = true; @@ -726,7 +726,7 @@ fn main() { fn local_variable_with_type_annotation() { cov_mark::check!(replaces_ty_annotation); check_assist( - bool_to_enum, + convert_bool_to_enum, r#" fn main() { let $0foo: bool = false; @@ -746,7 +746,7 @@ fn main() { #[test] fn local_variable_with_non_literal_initializer() { check_assist( - bool_to_enum, + convert_bool_to_enum, r#" fn main() { let $0foo = 1 == 2; @@ -766,7 +766,7 @@ fn main() { #[test] fn local_variable_binexpr_usage() { check_assist( - bool_to_enum, + convert_bool_to_enum, r#" fn main() { let $0foo = false; @@ -796,7 +796,7 @@ fn main() { #[test] fn local_variable_unop_usage() { check_assist( - bool_to_enum, + convert_bool_to_enum, r#" fn main() { let $0foo = true; @@ -825,7 +825,7 @@ fn main() { fn local_variable_assigned_later() { cov_mark::check!(replaces_assignment); check_assist( - bool_to_enum, + convert_bool_to_enum, r#" fn main() { let $0foo: bool; @@ -847,7 +847,7 @@ fn main() { #[test] fn local_variable_does_not_apply_recursively() { check_assist( - bool_to_enum, + convert_bool_to_enum, r#" fn main() { let $0foo = true; @@ -878,7 +878,7 @@ fn main() { fn local_variable_nested_in_negation() { cov_mark::check!(dont_overwrite_expression_inside_negation); check_assist( - bool_to_enum, + convert_bool_to_enum, r#" fn main() { if !"foo".chars().any(|c| { @@ -909,7 +909,7 @@ fn main() { fn local_variable_non_bool() { cov_mark::check!(not_applicable_non_bool_local); check_assist_not_applicable( - bool_to_enum, + convert_bool_to_enum, r#" fn main() { let $0foo = 1; @@ -921,7 +921,7 @@ fn main() { #[test] fn local_variable_cursor_not_on_ident() { check_assist_not_applicable( - bool_to_enum, + convert_bool_to_enum, r#" fn main() { let foo = $0true; @@ -933,7 +933,7 @@ fn main() { #[test] fn local_variable_non_ident_pat() { check_assist_not_applicable( - bool_to_enum, + convert_bool_to_enum, r#" fn main() { let ($0foo, bar) = (true, false); @@ -945,7 +945,7 @@ fn main() { #[test] fn local_var_init_struct_usage() { check_assist( - bool_to_enum, + convert_bool_to_enum, r#" struct Foo { foo: bool, @@ -975,7 +975,7 @@ fn main() { #[test] fn local_var_init_struct_usage_in_macro() { check_assist( - bool_to_enum, + convert_bool_to_enum, r#" struct Struct { boolean: bool, @@ -1018,7 +1018,7 @@ fn new() -> Struct { fn field_struct_basic() { cov_mark::check!(replaces_record_expr); check_assist( - bool_to_enum, + convert_bool_to_enum, r#" struct Foo { $0bar: bool, @@ -1057,7 +1057,7 @@ fn main() { fn field_enum_basic() { cov_mark::check!(replaces_record_pat); check_assist( - bool_to_enum, + convert_bool_to_enum, r#" enum Foo { Foo, @@ -1100,7 +1100,7 @@ fn main() { fn field_enum_cross_file() { // FIXME: The import is missing check_assist( - bool_to_enum, + convert_bool_to_enum, r#" //- /foo.rs pub enum Foo { @@ -1151,7 +1151,7 @@ fn main() { fn field_enum_shorthand() { cov_mark::check!(replaces_record_pat_shorthand); check_assist( - bool_to_enum, + convert_bool_to_enum, r#" enum Foo { Foo, @@ -1200,7 +1200,7 @@ fn main() { fn field_enum_replaces_literal_patterns() { cov_mark::check!(replaces_literal_pat); check_assist( - bool_to_enum, + convert_bool_to_enum, r#" enum Foo { Foo, @@ -1238,7 +1238,7 @@ fn main() { #[test] fn field_enum_keeps_wildcard_patterns() { check_assist( - bool_to_enum, + convert_bool_to_enum, r#" enum Foo { Foo, @@ -1276,7 +1276,7 @@ fn main() { #[test] fn field_union_basic() { check_assist( - bool_to_enum, + convert_bool_to_enum, r#" union Foo { $0foo: bool, @@ -1314,7 +1314,7 @@ fn main() { #[test] fn field_negated() { check_assist( - bool_to_enum, + convert_bool_to_enum, r#" struct Foo { $0bar: bool, @@ -1350,7 +1350,7 @@ fn main() { #[test] fn field_in_mod_properly_indented() { check_assist( - bool_to_enum, + convert_bool_to_enum, r#" mod foo { struct Bar { @@ -1386,7 +1386,7 @@ mod foo { #[test] fn field_multiple_initializations() { check_assist( - bool_to_enum, + convert_bool_to_enum, r#" struct Foo { $0bar: bool, @@ -1427,7 +1427,7 @@ fn main() { fn field_assigned_to_another() { cov_mark::check!(dont_assign_incorrect_ref); check_assist( - bool_to_enum, + convert_bool_to_enum, r#" struct Foo { $0foo: bool, @@ -1469,7 +1469,7 @@ fn main() { #[test] fn field_initialized_with_other() { check_assist( - bool_to_enum, + convert_bool_to_enum, r#" struct Foo { $0foo: bool, @@ -1507,7 +1507,7 @@ fn main() { #[test] fn field_method_chain_usage() { check_assist( - bool_to_enum, + convert_bool_to_enum, r#" struct Foo { $0bool: bool, @@ -1539,7 +1539,7 @@ fn main() { #[test] fn field_in_macro() { check_assist( - bool_to_enum, + convert_bool_to_enum, r#" struct Struct { $0boolean: bool, @@ -1580,7 +1580,7 @@ fn new() -> Struct { fn field_non_bool() { cov_mark::check!(not_applicable_non_bool_field); check_assist_not_applicable( - bool_to_enum, + convert_bool_to_enum, r#" struct Foo { $0bar: usize, @@ -1596,7 +1596,7 @@ fn main() { #[test] fn const_basic() { check_assist( - bool_to_enum, + convert_bool_to_enum, r#" const $0FOO: bool = false; @@ -1624,7 +1624,7 @@ fn main() { #[test] fn const_in_module() { check_assist( - bool_to_enum, + convert_bool_to_enum, r#" fn main() { if foo::FOO { @@ -1658,7 +1658,7 @@ mod foo { #[test] fn const_in_module_with_import() { check_assist( - bool_to_enum, + convert_bool_to_enum, r#" fn main() { use foo::FOO; @@ -1696,7 +1696,7 @@ mod foo { #[test] fn const_cross_file() { check_assist( - bool_to_enum, + convert_bool_to_enum, r#" //- /main.rs mod foo; @@ -1734,7 +1734,7 @@ pub const FOO: Bool = Bool::True; #[test] fn const_cross_file_and_module() { check_assist( - bool_to_enum, + convert_bool_to_enum, r#" //- /main.rs mod foo; @@ -1780,7 +1780,7 @@ pub mod bar { #[test] fn const_in_impl_cross_file() { check_assist( - bool_to_enum, + convert_bool_to_enum, r#" //- /main.rs mod foo; @@ -1824,7 +1824,7 @@ fn foo() -> bool { #[test] fn const_in_trait() { check_assist( - bool_to_enum, + convert_bool_to_enum, r#" trait Foo { const $0BOOL: bool; @@ -1865,7 +1865,7 @@ fn main() { fn const_non_bool() { cov_mark::check!(not_applicable_non_bool_const); check_assist_not_applicable( - bool_to_enum, + convert_bool_to_enum, r#" const $0FOO: &str = "foo"; @@ -1879,7 +1879,7 @@ fn main() { #[test] fn static_basic() { check_assist( - bool_to_enum, + convert_bool_to_enum, r#" static mut $0BOOL: bool = true; @@ -1910,7 +1910,7 @@ fn main() { fn static_non_bool() { cov_mark::check!(not_applicable_non_bool_static); check_assist_not_applicable( - bool_to_enum, + convert_bool_to_enum, r#" static mut $0FOO: usize = 0; @@ -1925,6 +1925,6 @@ fn main() { #[test] fn not_applicable_to_other_names() { - check_assist_not_applicable(bool_to_enum, "fn $0main() {}") + check_assist_not_applicable(convert_bool_to_enum, "fn $0main() {}") } } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/fill_record_pattern_fields.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_rest_pattern.rs similarity index 84% rename from src/tools/rust-analyzer/crates/ide-assists/src/handlers/fill_record_pattern_fields.rs rename to src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_rest_pattern.rs index ee321864805e7..315d7e727b41b 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/fill_record_pattern_fields.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_rest_pattern.rs @@ -1,11 +1,11 @@ use syntax::{ ast::{self, make}, - AstNode, ToSmolStr, + match_ast, AstNode, ToSmolStr, }; use crate::{AssistContext, AssistId, Assists}; -// Assist: fill_record_pattern_fields +// Assist: expand_rest_pattern // // Fills fields by replacing rest pattern in record patterns. // @@ -24,14 +24,20 @@ use crate::{AssistContext, AssistId, Assists}; // let Bar { y, z } = bar; // } // ``` -pub(crate) fn fill_record_pattern_fields(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { - let record_pat = ctx.find_node_at_offset::()?; +pub(crate) fn expand_rest_pattern(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { + let rest_pat = ctx.find_node_at_offset::()?; + let parent = rest_pat.syntax().parent()?; + let record_pat = match_ast! { + match parent { + ast::RecordPatFieldList(it) => ast::RecordPat::cast(it.syntax().parent()?)?, + // ast::TupleStructPat(it) => (), + // ast::TuplePat(it) => (), + // ast::SlicePat(it) => (), + _ => return None, + } + }; let ellipsis = record_pat.record_pat_field_list().and_then(|r| r.rest_pat())?; - if !ellipsis.syntax().text_range().contains_inclusive(ctx.offset()) { - return None; - } - let target_range = ellipsis.syntax().text_range(); let missing_fields = ctx.sema.record_pattern_missing_fields(&record_pat); @@ -58,7 +64,7 @@ pub(crate) fn fill_record_pattern_fields(acc: &mut Assists, ctx: &AssistContext< } acc.add( - AssistId("fill_record_pattern_fields", crate::AssistKind::RefactorRewrite), + AssistId("expand_rest_pattern", crate::AssistKind::RefactorRewrite), "Fill structure fields", target_range, move |builder| builder.replace_ast(old_field_list, new_field_list), @@ -73,7 +79,7 @@ mod tests { #[test] fn fill_fields_enum_with_only_ellipsis() { check_assist( - fill_record_pattern_fields, + expand_rest_pattern, r#" enum Foo { A(X), @@ -106,7 +112,7 @@ fn bar(foo: Foo) { #[test] fn fill_fields_enum_with_fields() { check_assist( - fill_record_pattern_fields, + expand_rest_pattern, r#" enum Foo { A(X), @@ -139,7 +145,7 @@ fn bar(foo: Foo) { #[test] fn fill_fields_struct_with_only_ellipsis() { check_assist( - fill_record_pattern_fields, + expand_rest_pattern, r#" struct Bar { y: Y, @@ -166,7 +172,7 @@ fn foo(bar: Bar) { #[test] fn fill_fields_struct_with_fields() { check_assist( - fill_record_pattern_fields, + expand_rest_pattern, r#" struct Bar { y: Y, @@ -193,7 +199,7 @@ fn foo(bar: Bar) { #[test] fn fill_fields_struct_generated_by_macro() { check_assist( - fill_record_pattern_fields, + expand_rest_pattern, r#" macro_rules! position { ($t: ty) => { @@ -226,7 +232,7 @@ fn macro_call(pos: Pos) { #[test] fn fill_fields_enum_generated_by_macro() { check_assist( - fill_record_pattern_fields, + expand_rest_pattern, r#" macro_rules! enum_gen { ($t: ty) => { @@ -271,7 +277,7 @@ fn macro_call(foo: Foo) { #[test] fn not_applicable_when_not_in_ellipsis() { check_assist_not_applicable( - fill_record_pattern_fields, + expand_rest_pattern, r#" enum Foo { A(X), @@ -287,7 +293,7 @@ fn bar(foo: Foo) { "#, ); check_assist_not_applicable( - fill_record_pattern_fields, + expand_rest_pattern, r#" enum Foo { A(X), @@ -303,7 +309,7 @@ fn bar(foo: Foo) { "#, ); check_assist_not_applicable( - fill_record_pattern_fields, + expand_rest_pattern, r#" enum Foo { A(X), @@ -325,7 +331,7 @@ fn bar(foo: Foo) { // This is still possible even though it's meaningless cov_mark::check!(no_missing_fields); check_assist_not_applicable( - fill_record_pattern_fields, + expand_rest_pattern, r#" enum Foo { A(X), @@ -341,7 +347,7 @@ fn bar(foo: Foo) { "#, ); check_assist_not_applicable( - fill_record_pattern_fields, + expand_rest_pattern, r#" struct Bar { y: Y, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/introduce_named_generic.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/introduce_named_type_parameter.rs similarity index 84% rename from src/tools/rust-analyzer/crates/ide-assists/src/handlers/introduce_named_generic.rs rename to src/tools/rust-analyzer/crates/ide-assists/src/handlers/introduce_named_type_parameter.rs index 8c276415bb1fb..994e4a0eddaf6 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/introduce_named_generic.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/introduce_named_type_parameter.rs @@ -4,7 +4,7 @@ use syntax::ast::{self, syntax_factory::SyntaxFactory, AstNode, HasGenericParams use crate::{AssistContext, AssistId, AssistKind, Assists}; -// Assist: introduce_named_generic +// Assist: introduce_named_type_parameter // // Replaces `impl Trait` function argument with the named generic. // @@ -15,18 +15,20 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; // ``` // fn foo<$0B: Bar>(bar: B) {} // ``` -pub(crate) fn introduce_named_generic(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { +pub(crate) fn introduce_named_type_parameter( + acc: &mut Assists, + ctx: &AssistContext<'_>, +) -> Option<()> { let impl_trait_type = ctx.find_node_at_offset::()?; let param = impl_trait_type.syntax().ancestors().find_map(ast::Param::cast)?; - let fn_ = param.syntax().ancestors().find_map(ast::Fn::cast)?; - + let fn_ = param.syntax().ancestors().nth(2).and_then(ast::Fn::cast)?; let type_bound_list = impl_trait_type.type_bound_list()?; let make = SyntaxFactory::new(); let target = fn_.syntax().text_range(); acc.add( - AssistId("introduce_named_generic", AssistKind::RefactorRewrite), - "Replace impl trait with generic", + AssistId("introduce_named_type_parameter", AssistKind::RefactorRewrite), + "Replace impl trait with type parameter", target, |builder| { let mut editor = builder.make_editor(fn_.syntax()); @@ -71,7 +73,7 @@ mod tests { #[test] fn introduce_named_generic_params() { check_assist( - introduce_named_generic, + introduce_named_type_parameter, r#"fn foo(bar: $0impl Bar) {}"#, r#"fn foo(bar: B) {}"#, ); @@ -80,7 +82,7 @@ mod tests { #[test] fn replace_impl_trait_without_generic_params() { check_assist( - introduce_named_generic, + introduce_named_type_parameter, r#"fn foo(bar: $0impl Bar) {}"#, r#"fn foo<$0B: Bar>(bar: B) {}"#, ); @@ -89,7 +91,7 @@ mod tests { #[test] fn replace_two_impl_trait_with_generic_params() { check_assist( - introduce_named_generic, + introduce_named_type_parameter, r#"fn foo(foo: impl Foo, bar: $0impl Bar) {}"#, r#"fn foo(foo: impl Foo, bar: B) {}"#, ); @@ -98,7 +100,7 @@ mod tests { #[test] fn replace_impl_trait_with_empty_generic_params() { check_assist( - introduce_named_generic, + introduce_named_type_parameter, r#"fn foo<>(bar: $0impl Bar) {}"#, r#"fn foo<$0B: Bar>(bar: B) {}"#, ); @@ -107,7 +109,7 @@ mod tests { #[test] fn replace_impl_trait_with_empty_multiline_generic_params() { check_assist( - introduce_named_generic, + introduce_named_type_parameter, r#" fn foo< >(bar: $0impl Bar) {} @@ -122,7 +124,7 @@ fn foo<$0B: Bar #[test] fn replace_impl_trait_with_exist_generic_letter() { check_assist( - introduce_named_generic, + introduce_named_type_parameter, r#"fn foo(bar: $0impl Bar) {}"#, r#"fn foo(bar: B1) {}"#, ); @@ -131,7 +133,7 @@ fn foo<$0B: Bar #[test] fn replace_impl_trait_with_more_exist_generic_letter() { check_assist( - introduce_named_generic, + introduce_named_type_parameter, r#"fn foo(bar: $0impl Bar) {}"#, r#"fn foo(bar: B4) {}"#, ); @@ -140,7 +142,7 @@ fn foo<$0B: Bar #[test] fn replace_impl_trait_with_multiline_generic_params() { check_assist( - introduce_named_generic, + introduce_named_type_parameter, r#" fn foo< G: Foo, @@ -161,7 +163,7 @@ fn foo< #[test] fn replace_impl_trait_multiple() { check_assist( - introduce_named_generic, + introduce_named_type_parameter, r#"fn foo(bar: $0impl Foo + Bar) {}"#, r#"fn foo<$0F: Foo + Bar>(bar: F) {}"#, ); @@ -170,7 +172,7 @@ fn foo< #[test] fn replace_impl_with_mut() { check_assist( - introduce_named_generic, + introduce_named_type_parameter, r#"fn f(iter: &mut $0impl Iterator) {}"#, r#"fn f<$0I: Iterator>(iter: &mut I) {}"#, ); @@ -179,7 +181,7 @@ fn foo< #[test] fn replace_impl_inside() { check_assist( - introduce_named_generic, + introduce_named_type_parameter, r#"fn f(x: &mut Vec<$0impl Iterator>) {}"#, r#"fn f<$0I: Iterator>(x: &mut Vec) {}"#, ); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs index 179742f91b4dc..11d48430a0ada 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs @@ -105,6 +105,7 @@ mod handlers { pub(crate) type Handler = fn(&mut Assists, &AssistContext<'_>) -> Option<()>; mod add_braces; + mod add_explicit_enum_discriminant; mod add_explicit_type; mod add_label_to_loop; mod add_lifetime_to_type; @@ -115,9 +116,9 @@ mod handlers { mod apply_demorgan; mod auto_import; mod bind_unused_param; - mod bool_to_enum; mod change_visibility; mod convert_bool_then; + mod convert_bool_to_enum; mod convert_closure_to_fn; mod convert_comment_block; mod convert_comment_from_or_to_doc; @@ -138,14 +139,13 @@ mod handlers { mod destructure_tuple_binding; mod desugar_doc_comment; mod expand_glob_import; - mod explicit_enum_discriminant; + mod expand_rest_pattern; mod extract_expressions_from_format_string; mod extract_function; mod extract_module; mod extract_struct_from_enum_variant; mod extract_type_alias; mod extract_variable; - mod fill_record_pattern_fields; mod fix_visibility; mod flip_binexpr; mod flip_comma; @@ -176,8 +176,8 @@ mod handlers { mod inline_macro; mod inline_type_alias; mod into_to_qualified_from; - mod introduce_named_generic; mod introduce_named_lifetime; + mod introduce_named_type_parameter; mod invert_if; mod merge_imports; mod merge_match_arms; @@ -233,49 +233,47 @@ mod handlers { &[ // These are alphabetic for the foolish consistency add_braces::add_braces, + add_explicit_enum_discriminant::add_explicit_enum_discriminant, add_explicit_type::add_explicit_type, add_label_to_loop::add_label_to_loop, - add_missing_match_arms::add_missing_match_arms, add_lifetime_to_type::add_lifetime_to_type, + add_missing_match_arms::add_missing_match_arms, add_return_type::add_return_type, add_turbo_fish::add_turbo_fish, - apply_demorgan::apply_demorgan, apply_demorgan::apply_demorgan_iterator, + apply_demorgan::apply_demorgan, auto_import::auto_import, bind_unused_param::bind_unused_param, - bool_to_enum::bool_to_enum, change_visibility::change_visibility, convert_bool_then::convert_bool_then_to_if, convert_bool_then::convert_if_to_bool_then, - toggle_async_sugar::desugar_async_into_impl_future, - toggle_async_sugar::sugar_impl_future_into_async, + convert_bool_to_enum::convert_bool_to_enum, + convert_closure_to_fn::convert_closure_to_fn, convert_comment_block::convert_comment_block, convert_comment_from_or_to_doc::convert_comment_from_or_to_doc, - convert_closure_to_fn::convert_closure_to_fn, convert_from_to_tryfrom::convert_from_to_tryfrom, convert_integer_literal::convert_integer_literal, convert_into_to_from::convert_into_to_from, - convert_iter_for_each_to_for::convert_iter_for_each_to_for, convert_iter_for_each_to_for::convert_for_loop_with_for_each, + convert_iter_for_each_to_for::convert_iter_for_each_to_for, convert_let_else_to_match::convert_let_else_to_match, convert_match_to_let_else::convert_match_to_let_else, - convert_tuple_return_type_to_struct::convert_tuple_return_type_to_struct, convert_named_struct_to_tuple_struct::convert_named_struct_to_tuple_struct, convert_nested_function_to_closure::convert_nested_function_to_closure, convert_to_guarded_return::convert_to_guarded_return, + convert_tuple_return_type_to_struct::convert_tuple_return_type_to_struct, convert_tuple_struct_to_named_struct::convert_tuple_struct_to_named_struct, convert_two_arm_bool_match_to_matches_macro::convert_two_arm_bool_match_to_matches_macro, convert_while_to_loop::convert_while_to_loop, - desugar_doc_comment::desugar_doc_comment, - destructure_tuple_binding::destructure_tuple_binding, destructure_struct_binding::destructure_struct_binding, + destructure_tuple_binding::destructure_tuple_binding, + desugar_doc_comment::desugar_doc_comment, expand_glob_import::expand_glob_import, expand_glob_import::expand_glob_reexport, - explicit_enum_discriminant::explicit_enum_discriminant, + expand_rest_pattern::expand_rest_pattern, extract_expressions_from_format_string::extract_expressions_from_format_string, extract_struct_from_enum_variant::extract_struct_from_enum_variant, extract_type_alias::extract_type_alias, - fill_record_pattern_fields::fill_record_pattern_fields, fix_visibility::fix_visibility, flip_binexpr::flip_binexpr, flip_comma::flip_comma, @@ -285,8 +283,8 @@ mod handlers { generate_default_from_new::generate_default_from_new, generate_delegate_trait::generate_delegate_trait, generate_derive::generate_derive, - generate_documentation_template::generate_documentation_template, generate_documentation_template::generate_doc_example, + generate_documentation_template::generate_documentation_template, generate_enum_is_method::generate_enum_is_method, generate_enum_projection_method::generate_enum_as_method, generate_enum_projection_method::generate_enum_try_into_method, @@ -296,8 +294,8 @@ mod handlers { generate_function::generate_function, generate_impl::generate_impl, generate_impl::generate_trait_impl, - generate_mut_trait_impl::generate_mut_trait_impl, generate_is_empty_from_len::generate_is_empty_from_len, + generate_mut_trait_impl::generate_mut_trait_impl, generate_new::generate_new, generate_trait_from_impl::generate_trait_from_impl, inline_call::inline_call, @@ -305,39 +303,41 @@ mod handlers { inline_const_as_literal::inline_const_as_literal, inline_local_variable::inline_local_variable, inline_macro::inline_macro, - inline_type_alias::inline_type_alias, inline_type_alias::inline_type_alias_uses, + inline_type_alias::inline_type_alias, into_to_qualified_from::into_to_qualified_from, - introduce_named_generic::introduce_named_generic, introduce_named_lifetime::introduce_named_lifetime, + introduce_named_type_parameter::introduce_named_type_parameter, invert_if::invert_if, merge_imports::merge_imports, merge_match_arms::merge_match_arms, merge_nested_if::merge_nested_if, move_bounds::move_bounds_to_where_clause, move_const_to_impl::move_const_to_impl, + move_from_mod_rs::move_from_mod_rs, move_guard::move_arm_cond_to_match_guard, move_guard::move_guard_to_arm_body, move_module_to_file::move_module_to_file, move_to_mod_rs::move_to_mod_rs, - move_from_mod_rs::move_from_mod_rs, normalize_import::normalize_import, number_representation::reformat_number_literal, - pull_assignment_up::pull_assignment_up, promote_local_to_const::promote_local_to_const, - qualify_path::qualify_path, + pull_assignment_up::pull_assignment_up, qualify_method_call::qualify_method_call, + qualify_path::qualify_path, raw_string::add_hash, raw_string::make_usual_string, raw_string::remove_hash, remove_dbg::remove_dbg, remove_mut::remove_mut, + remove_parentheses::remove_parentheses, remove_unused_imports::remove_unused_imports, remove_unused_param::remove_unused_param, - remove_parentheses::remove_parentheses, reorder_fields::reorder_fields, reorder_impl_items::reorder_impl_items, - replace_try_expr_with_match::replace_try_expr_with_match, + replace_arith_op::replace_arith_with_checked, + replace_arith_op::replace_arith_with_saturating, + replace_arith_op::replace_arith_with_wrapping, replace_derive_with_manual_impl::replace_derive_with_manual_impl, replace_if_let_with_match::replace_if_let_with_match, replace_if_let_with_match::replace_match_with_if_let, @@ -346,23 +346,23 @@ mod handlers { replace_method_eager_lazy::replace_with_eager_method, replace_method_eager_lazy::replace_with_lazy_method, replace_named_generic_with_impl::replace_named_generic_with_impl, - replace_turbofish_with_explicit_type::replace_turbofish_with_explicit_type, replace_qualified_name_with_use::replace_qualified_name_with_use, - replace_arith_op::replace_arith_with_wrapping, - replace_arith_op::replace_arith_with_checked, - replace_arith_op::replace_arith_with_saturating, + replace_try_expr_with_match::replace_try_expr_with_match, + replace_turbofish_with_explicit_type::replace_turbofish_with_explicit_type, sort_items::sort_items, split_import::split_import, term_search::term_search, + toggle_async_sugar::desugar_async_into_impl_future, + toggle_async_sugar::sugar_impl_future_into_async, toggle_ignore::toggle_ignore, toggle_macro_delimiter::toggle_macro_delimiter, unmerge_match_arm::unmerge_match_arm, unmerge_use::unmerge_use, unnecessary_async::unnecessary_async, + unqualify_method_call::unqualify_method_call, unwrap_block::unwrap_block, unwrap_return_type::unwrap_return_type, unwrap_tuple::unwrap_tuple, - unqualify_method_call::unqualify_method_call, wrap_return_type::wrap_return_type, wrap_unwrap_cfg_attr::wrap_unwrap_cfg_attr, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs index 74ae126adae88..dd994ef4a640c 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs @@ -27,6 +27,29 @@ fn foo(n: i32) -> i32 { ) } +#[test] +fn doctest_add_explicit_enum_discriminant() { + check_doc_test( + "add_explicit_enum_discriminant", + r#####" +enum TheEnum$0 { + Foo, + Bar, + Baz = 42, + Quux, +} +"#####, + r#####" +enum TheEnum { + Foo = 0, + Bar = 1, + Baz = 42, + Quux = 43, +} +"#####, + ) +} + #[test] fn doctest_add_explicit_type() { check_doc_test( @@ -304,34 +327,6 @@ fn some_function(x: i32) { ) } -#[test] -fn doctest_bool_to_enum() { - check_doc_test( - "bool_to_enum", - r#####" -fn main() { - let $0bool = true; - - if bool { - println!("foo"); - } -} -"#####, - r#####" -#[derive(PartialEq, Eq)] -enum Bool { True, False } - -fn main() { - let bool = Bool::True; - - if bool == Bool::True { - println!("foo"); - } -} -"#####, - ) -} - #[test] fn doctest_change_visibility() { check_doc_test( @@ -382,6 +377,34 @@ fn main() { ) } +#[test] +fn doctest_convert_bool_to_enum() { + check_doc_test( + "convert_bool_to_enum", + r#####" +fn main() { + let $0bool = true; + + if bool { + println!("foo"); + } +} +"#####, + r#####" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +fn main() { + let bool = Bool::True; + + if bool == Bool::True { + println!("foo"); + } +} +"#####, + ) +} + #[test] fn doctest_convert_closure_to_fn() { check_doc_test( @@ -933,23 +956,21 @@ pub use foo::{Bar, Baz}; } #[test] -fn doctest_explicit_enum_discriminant() { +fn doctest_expand_rest_pattern() { check_doc_test( - "explicit_enum_discriminant", + "expand_rest_pattern", r#####" -enum TheEnum$0 { - Foo, - Bar, - Baz = 42, - Quux, +struct Bar { y: Y, z: Z } + +fn foo(bar: Bar) { + let Bar { ..$0 } = bar; } "#####, r#####" -enum TheEnum { - Foo = 0, - Bar = 1, - Baz = 42, - Quux = 43, +struct Bar { y: Y, z: Z } + +fn foo(bar: Bar) { + let Bar { y, z } = bar; } "#####, ) @@ -1117,27 +1138,6 @@ fn main() { ) } -#[test] -fn doctest_fill_record_pattern_fields() { - check_doc_test( - "fill_record_pattern_fields", - r#####" -struct Bar { y: Y, z: Z } - -fn foo(bar: Bar) { - let Bar { ..$0 } = bar; -} -"#####, - r#####" -struct Bar { y: Y, z: Z } - -fn foo(bar: Bar) { - let Bar { y, z } = bar; -} -"#####, - ) -} - #[test] fn doctest_fix_visibility() { check_doc_test( @@ -2176,19 +2176,6 @@ fn main() -> () { ) } -#[test] -fn doctest_introduce_named_generic() { - check_doc_test( - "introduce_named_generic", - r#####" -fn foo(bar: $0impl Bar) {} -"#####, - r#####" -fn foo<$0B: Bar>(bar: B) {} -"#####, - ) -} - #[test] fn doctest_introduce_named_lifetime() { check_doc_test( @@ -2214,6 +2201,19 @@ impl<'a> Cursor<'a> { ) } +#[test] +fn doctest_introduce_named_type_parameter() { + check_doc_test( + "introduce_named_type_parameter", + r#####" +fn foo(bar: $0impl Bar) {} +"#####, + r#####" +fn foo<$0B: Bar>(bar: B) {} +"#####, + ) +} + #[test] fn doctest_invert_if() { check_doc_test( diff --git a/src/tools/rust-analyzer/docs/book/src/assists_generated.md b/src/tools/rust-analyzer/docs/book/src/assists_generated.md index 2d233ca62ad60..743e5c5e10d40 100644 --- a/src/tools/rust-analyzer/docs/book/src/assists_generated.md +++ b/src/tools/rust-analyzer/docs/book/src/assists_generated.md @@ -28,6 +28,32 @@ fn foo(n: i32) -> i32 { ``` +### `add_explicit_enum_discriminant` +**Source:** [add_explicit_enum_discriminant.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/add_explicit_enum_discriminant.rs#L11) + +Adds explicit discriminant to all enum variants. + +#### Before +```rust +enum TheEnum┃ { + Foo, + Bar, + Baz = 42, + Quux, +} +``` + +#### After +```rust +enum TheEnum { + Foo = 0, + Bar = 1, + Baz = 42, + Quux = 43, +} +``` + + ### `add_explicit_type` **Source:** [add_explicit_type.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/add_explicit_type.rs#L7) @@ -257,7 +283,7 @@ fn main() { ### `apply_demorgan` -**Source:** [apply_demorgan.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/apply_demorgan.rs#L16) +**Source:** [apply_demorgan.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/apply_demorgan.rs#L23) Apply [De Morgan's law](https://en.wikipedia.org/wiki/De_Morgan%27s_laws). This transforms expressions of the form `!l || !r` into `!(l && r)`. @@ -280,7 +306,7 @@ fn main() { ### `apply_demorgan_iterator` -**Source:** [apply_demorgan.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/apply_demorgan.rs#L147) +**Source:** [apply_demorgan.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/apply_demorgan.rs#L154) Apply [De Morgan's law](https://en.wikipedia.org/wiki/De_Morgan%27s_laws) to `Iterator::all` and `Iterator::any`. @@ -350,40 +376,6 @@ fn some_function(x: i32) { ``` -### `bool_to_enum` -**Source:** [bool_to_enum.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/bool_to_enum.rs#L29) - -This converts boolean local variables, fields, constants, and statics into a new -enum with two variants `Bool::True` and `Bool::False`, as well as replacing -all assignments with the variants and replacing all usages with `== Bool::True` or -`== Bool::False`. - -#### Before -```rust -fn main() { - let ┃bool = true; - - if bool { - println!("foo"); - } -} -``` - -#### After -```rust -#[derive(PartialEq, Eq)] -enum Bool { True, False } - -fn main() { - let bool = Bool::True; - - if bool == Bool::True { - println!("foo"); - } -} -``` - - ### `change_visibility` **Source:** [change_visibility.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/change_visibility.rs#L13) @@ -442,6 +434,40 @@ fn main() { ``` +### `convert_bool_to_enum` +**Source:** [convert_bool_to_enum.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_bool_to_enum.rs#L29) + +This converts boolean local variables, fields, constants, and statics into a new +enum with two variants `Bool::True` and `Bool::False`, as well as replacing +all assignments with the variants and replacing all usages with `== Bool::True` or +`== Bool::False`. + +#### Before +```rust +fn main() { + let ┃bool = true; + + if bool { + println!("foo"); + } +} +``` + +#### After +```rust +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +fn main() { + let bool = Bool::True; + + if bool == Bool::True { + println!("foo"); + } +} +``` + + ### `convert_closure_to_fn` **Source:** [convert_closure_to_fn.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_closure_to_fn.rs#L25) @@ -1043,28 +1069,26 @@ pub use foo::{Bar, Baz}; ``` -### `explicit_enum_discriminant` -**Source:** [explicit_enum_discriminant.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/explicit_enum_discriminant.rs#L11) +### `expand_rest_pattern` +**Source:** [expand_rest_pattern.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/expand_rest_pattern.rs#L8) -Adds explicit discriminant to all enum variants. +Fills fields by replacing rest pattern in record patterns. #### Before ```rust -enum TheEnum┃ { - Foo, - Bar, - Baz = 42, - Quux, +struct Bar { y: Y, z: Z } + +fn foo(bar: Bar) { + let Bar { ..┃ } = bar; } ``` #### After ```rust -enum TheEnum { - Foo = 0, - Bar = 1, - Baz = 42, - Quux = 43, +struct Bar { y: Y, z: Z } + +fn foo(bar: Bar) { + let Bar { y, z } = bar; } ``` @@ -1255,30 +1279,6 @@ fn main() { ``` -### `fill_record_pattern_fields` -**Source:** [fill_record_pattern_fields.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/fill_record_pattern_fields.rs#L8) - -Fills fields by replacing rest pattern in record patterns. - -#### Before -```rust -struct Bar { y: Y, z: Z } - -fn foo(bar: Bar) { - let Bar { ..┃ } = bar; -} -``` - -#### After -```rust -struct Bar { y: Y, z: Z } - -fn foo(bar: Bar) { - let Bar { y, z } = bar; -} -``` - - ### `fix_visibility` **Source:** [fix_visibility.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/fix_visibility.rs#L14) @@ -2403,22 +2403,6 @@ fn main() -> () { ``` -### `introduce_named_generic` -**Source:** [introduce_named_generic.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/introduce_named_generic.rs#L7) - -Replaces `impl Trait` function argument with the named generic. - -#### Before -```rust -fn foo(bar: ┃impl Bar) {} -``` - -#### After -```rust -fn foo<┃B: Bar>(bar: B) {} -``` - - ### `introduce_named_lifetime` **Source:** [introduce_named_lifetime.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/introduce_named_lifetime.rs#L13) @@ -2447,6 +2431,22 @@ impl<'a> Cursor<'a> { ``` +### `introduce_named_type_parameter` +**Source:** [introduce_named_type_parameter.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/introduce_named_type_parameter.rs#L7) + +Replaces `impl Trait` function argument with the named generic. + +#### Before +```rust +fn foo(bar: ┃impl Bar) {} +``` + +#### After +```rust +fn foo<┃B: Bar>(bar: B) {} +``` + + ### `invert_if` **Source:** [invert_if.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/invert_if.rs#L13) From 2f9e5586a07f8cfa3e533668d0bf7885178659ed Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Sun, 2 Mar 2025 19:41:39 +0530 Subject: [PATCH 04/53] add diagnostic for dangling dyn --- .../crates/syntax/src/validation.rs | 26 ++++++++++++------- .../parser/validation/0224_dangling_dyn.rast | 25 ++++++++++++++++++ .../parser/validation/0224_dangling_dyn.rs | 1 + 3 files changed, 43 insertions(+), 9 deletions(-) create mode 100644 src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0224_dangling_dyn.rast create mode 100644 src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0224_dangling_dyn.rs diff --git a/src/tools/rust-analyzer/crates/syntax/src/validation.rs b/src/tools/rust-analyzer/crates/syntax/src/validation.rs index 13d352d3c691b..2dc86411e427a 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/validation.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/validation.rs @@ -340,17 +340,25 @@ fn validate_trait_object_fn_ptr_ret_ty(ty: ast::FnPtrType, errors: &mut Vec Option { let tbl = ty.type_bound_list()?; - - if tbl.bounds().count() > 1 { - let dyn_token = ty.dyn_token()?; - let potential_parenthesis = - algo::skip_trivia_token(dyn_token.prev_token()?, Direction::Prev)?; - let kind = potential_parenthesis.kind(); - if !matches!(kind, T!['('] | T![<] | T![=]) { - return Some(SyntaxError::new("ambiguous `+` in a type", ty.syntax().text_range())); + let bounds_count = tbl.bounds().count(); + + match bounds_count { + 0 => Some(SyntaxError::new( + "At least one trait is required for an object type", + ty.syntax().text_range(), + )), + _ if bounds_count > 1 => { + let dyn_token = ty.dyn_token()?; + let preceding_token = + algo::skip_trivia_token(dyn_token.prev_token()?, Direction::Prev)?; + + if !matches!(preceding_token.kind(), T!['('] | T![<] | T![=]) { + return Some(SyntaxError::new("ambiguous `+` in a type", ty.syntax().text_range())); + } + None } + _ => None, } - None } fn validate_macro_rules(mac: ast::MacroRules, errors: &mut Vec) { diff --git a/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0224_dangling_dyn.rast b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0224_dangling_dyn.rast new file mode 100644 index 0000000000000..b31af5fbc6a50 --- /dev/null +++ b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0224_dangling_dyn.rast @@ -0,0 +1,25 @@ +SOURCE_FILE@0..16 + FN@0..16 + FN_KW@0..2 "fn" + WHITESPACE@2..3 " " + NAME@3..4 + IDENT@3..4 "f" + PARAM_LIST@4..13 + L_PAREN@4..5 "(" + PARAM@5..12 + WILDCARD_PAT@5..6 + UNDERSCORE@5..6 "_" + COLON@6..7 ":" + WHITESPACE@7..8 " " + REF_TYPE@8..12 + AMP@8..9 "&" + DYN_TRAIT_TYPE@9..12 + DYN_KW@9..12 "dyn" + TYPE_BOUND_LIST@12..12 + R_PAREN@12..13 ")" + WHITESPACE@13..14 " " + BLOCK_EXPR@14..16 + STMT_LIST@14..16 + L_CURLY@14..15 "{" + R_CURLY@15..16 "}" +error 9..12: At least one trait is required for an object type diff --git a/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0224_dangling_dyn.rs b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0224_dangling_dyn.rs new file mode 100644 index 0000000000000..2fdbb42846b67 --- /dev/null +++ b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0224_dangling_dyn.rs @@ -0,0 +1 @@ +fn f(_: &dyn) {} \ No newline at end of file From 1840f57dde794e984e3adabba7763ce2bcb10741 Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Sun, 2 Mar 2025 19:42:42 +0530 Subject: [PATCH 05/53] add diagnostic for dangling impl --- .../crates/syntax/src/validation.rs | 17 ++++++++++--- .../parser/validation/dangling_impl.rast | 25 +++++++++++++++++++ .../parser/validation/dangling_impl.rs | 1 + 3 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl.rast create mode 100644 src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl.rs diff --git a/src/tools/rust-analyzer/crates/syntax/src/validation.rs b/src/tools/rust-analyzer/crates/syntax/src/validation.rs index 2dc86411e427a..0377e7c0e63e1 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/validation.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/validation.rs @@ -315,10 +315,21 @@ fn validate_path_keywords(segment: ast::PathSegment, errors: &mut Vec) { - if let Some(ast::Type::DynTraitType(ty)) = ty.ty() { - if let Some(err) = validate_trait_object_ty(ty) { - errors.push(err); + match ty.ty() { + Some(ast::Type::DynTraitType(ty)) => { + if let Some(err) = validate_trait_object_ty(ty) { + errors.push(err); + } + } + Some(ast::Type::ImplTraitType(ty)) => { + if ty.type_bound_list().map_or(0, |tbl| tbl.bounds().count()) == 0 { + errors.push(SyntaxError::new( + "At least one trait must be specified", + ty.syntax().text_range(), + )); + } } + _ => {} } } diff --git a/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl.rast b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl.rast new file mode 100644 index 0000000000000..dbe6535ac665b --- /dev/null +++ b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl.rast @@ -0,0 +1,25 @@ +SOURCE_FILE@0..17 + FN@0..17 + FN_KW@0..2 "fn" + WHITESPACE@2..3 " " + NAME@3..4 + IDENT@3..4 "f" + PARAM_LIST@4..14 + L_PAREN@4..5 "(" + PARAM@5..13 + WILDCARD_PAT@5..6 + UNDERSCORE@5..6 "_" + COLON@6..7 ":" + WHITESPACE@7..8 " " + REF_TYPE@8..13 + AMP@8..9 "&" + IMPL_TRAIT_TYPE@9..13 + IMPL_KW@9..13 "impl" + TYPE_BOUND_LIST@13..13 + R_PAREN@13..14 ")" + WHITESPACE@14..15 " " + BLOCK_EXPR@15..17 + STMT_LIST@15..17 + L_CURLY@15..16 "{" + R_CURLY@16..17 "}" +error 9..13: At least one trait must be specified diff --git a/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl.rs b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl.rs new file mode 100644 index 0000000000000..0b440b4c5af49 --- /dev/null +++ b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl.rs @@ -0,0 +1 @@ +fn f(_: &impl) {} \ No newline at end of file From c2a630eaa591907315fb8a1f55ec5b9e9b4b2d18 Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Mon, 3 Mar 2025 15:58:33 +0530 Subject: [PATCH 06/53] Add dangling impl - Adds dangling impl diagnostics - Rename validation test from dangling_impl to dangling_iml_ref --- .../crates/syntax/src/validation.rs | 27 ++++++++--------- .../parser/validation/dangling_impl.rast | 30 +++++++++---------- .../parser/validation/dangling_impl.rs | 2 +- .../validation/dangling_impl_reference.rast | 25 ++++++++++++++++ .../validation/dangling_impl_reference.rs | 1 + 5 files changed, 54 insertions(+), 31 deletions(-) create mode 100644 src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl_reference.rast create mode 100644 src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl_reference.rs diff --git a/src/tools/rust-analyzer/crates/syntax/src/validation.rs b/src/tools/rust-analyzer/crates/syntax/src/validation.rs index 0377e7c0e63e1..85eefac734b20 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/validation.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/validation.rs @@ -37,6 +37,7 @@ pub(crate) fn validate(root: &SyntaxNode, errors: &mut Vec) { ast::FnPtrType(it) => validate_trait_object_fn_ptr_ret_ty(it, errors), ast::MacroRules(it) => validate_macro_rules(it, errors), ast::LetExpr(it) => validate_let_expr(it, errors), + ast::ImplTraitType(it) => validate_impl_object_ty(it, errors), _ => (), } } @@ -315,21 +316,10 @@ fn validate_path_keywords(segment: ast::PathSegment, errors: &mut Vec) { - match ty.ty() { - Some(ast::Type::DynTraitType(ty)) => { - if let Some(err) = validate_trait_object_ty(ty) { - errors.push(err); - } - } - Some(ast::Type::ImplTraitType(ty)) => { - if ty.type_bound_list().map_or(0, |tbl| tbl.bounds().count()) == 0 { - errors.push(SyntaxError::new( - "At least one trait must be specified", - ty.syntax().text_range(), - )); - } + if let Some(ast::Type::DynTraitType(ty)) = ty.ty() { + if let Some(err) = validate_trait_object_ty(ty) { + errors.push(err); } - _ => {} } } @@ -372,6 +362,15 @@ fn validate_trait_object_ty(ty: ast::DynTraitType) -> Option { } } +fn validate_impl_object_ty(ty: ast::ImplTraitType, errors: &mut Vec) { + if ty.type_bound_list().map_or(0, |tbl| tbl.bounds().count()) == 0 { + errors.push(SyntaxError::new( + "At least one trait must be specified", + ty.syntax().text_range(), + )); + } +} + fn validate_macro_rules(mac: ast::MacroRules, errors: &mut Vec) { if let Some(vis) = mac.visibility() { errors.push(SyntaxError::new( diff --git a/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl.rast b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl.rast index dbe6535ac665b..2db07ae12a98e 100644 --- a/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl.rast +++ b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl.rast @@ -1,25 +1,23 @@ -SOURCE_FILE@0..17 - FN@0..17 +SOURCE_FILE@0..16 + FN@0..16 FN_KW@0..2 "fn" WHITESPACE@2..3 " " NAME@3..4 IDENT@3..4 "f" - PARAM_LIST@4..14 + PARAM_LIST@4..13 L_PAREN@4..5 "(" - PARAM@5..13 + PARAM@5..12 WILDCARD_PAT@5..6 UNDERSCORE@5..6 "_" COLON@6..7 ":" WHITESPACE@7..8 " " - REF_TYPE@8..13 - AMP@8..9 "&" - IMPL_TRAIT_TYPE@9..13 - IMPL_KW@9..13 "impl" - TYPE_BOUND_LIST@13..13 - R_PAREN@13..14 ")" - WHITESPACE@14..15 " " - BLOCK_EXPR@15..17 - STMT_LIST@15..17 - L_CURLY@15..16 "{" - R_CURLY@16..17 "}" -error 9..13: At least one trait must be specified + IMPL_TRAIT_TYPE@8..12 + IMPL_KW@8..12 "impl" + TYPE_BOUND_LIST@12..12 + R_PAREN@12..13 ")" + WHITESPACE@13..14 " " + BLOCK_EXPR@14..16 + STMT_LIST@14..16 + L_CURLY@14..15 "{" + R_CURLY@15..16 "}" +error 8..12: At least one trait must be specified diff --git a/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl.rs b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl.rs index 0b440b4c5af49..61706d9e41296 100644 --- a/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl.rs +++ b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl.rs @@ -1 +1 @@ -fn f(_: &impl) {} \ No newline at end of file +fn f(_: impl) {} \ No newline at end of file diff --git a/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl_reference.rast b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl_reference.rast new file mode 100644 index 0000000000000..dbe6535ac665b --- /dev/null +++ b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl_reference.rast @@ -0,0 +1,25 @@ +SOURCE_FILE@0..17 + FN@0..17 + FN_KW@0..2 "fn" + WHITESPACE@2..3 " " + NAME@3..4 + IDENT@3..4 "f" + PARAM_LIST@4..14 + L_PAREN@4..5 "(" + PARAM@5..13 + WILDCARD_PAT@5..6 + UNDERSCORE@5..6 "_" + COLON@6..7 ":" + WHITESPACE@7..8 " " + REF_TYPE@8..13 + AMP@8..9 "&" + IMPL_TRAIT_TYPE@9..13 + IMPL_KW@9..13 "impl" + TYPE_BOUND_LIST@13..13 + R_PAREN@13..14 ")" + WHITESPACE@14..15 " " + BLOCK_EXPR@15..17 + STMT_LIST@15..17 + L_CURLY@15..16 "{" + R_CURLY@16..17 "}" +error 9..13: At least one trait must be specified diff --git a/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl_reference.rs b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl_reference.rs new file mode 100644 index 0000000000000..0b440b4c5af49 --- /dev/null +++ b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl_reference.rs @@ -0,0 +1 @@ +fn f(_: &impl) {} \ No newline at end of file From c315ad914fa2755ee8444a12d5ecfa599065b5bd Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sun, 2 Mar 2025 09:49:52 +0100 Subject: [PATCH 07/53] Support tuple struct patterns for expand_rest_pattern assist --- src/tools/rust-analyzer/crates/hir/src/lib.rs | 2 + .../src/handlers/expand_rest_pattern.rs | 187 ++++++++++++++++-- .../crates/ide-assists/src/tests/generated.rs | 25 ++- .../docs/book/src/assists_generated.md | 28 ++- 4 files changed, 217 insertions(+), 25 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 55448d4ae8682..7549d54a544e8 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -296,6 +296,7 @@ pub enum ModuleDef { Function(Function), Adt(Adt), // Can't be directly declared, but can be imported. + // FIXME: Rename to `EnumVariant` Variant(Variant), Const(Const), Static(Static), @@ -1564,6 +1565,7 @@ impl From<&Variant> for DefWithBodyId { } } +// FIXME: Rename to `EnumVariant` #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Variant { pub(crate) id: EnumVariantId, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_rest_pattern.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_rest_pattern.rs index 315d7e727b41b..c79a982c38d09 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_rest_pattern.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_rest_pattern.rs @@ -1,3 +1,5 @@ +use hir::{PathResolution, StructKind}; +use ide_db::syntax_helpers::suggest_name::NameGenerator; use syntax::{ ast::{self, make}, match_ast, AstNode, ToSmolStr, @@ -5,7 +7,23 @@ use syntax::{ use crate::{AssistContext, AssistId, Assists}; -// Assist: expand_rest_pattern +pub(crate) fn expand_rest_pattern(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { + let rest_pat = ctx.find_node_at_offset::()?; + let parent = rest_pat.syntax().parent()?; + match_ast! { + match parent { + ast::RecordPatFieldList(it) => expand_record_rest_pattern(acc, ctx, it.syntax().parent().and_then(ast::RecordPat::cast)?, rest_pat), + ast::TupleStructPat(it) => expand_tuple_struct_rest_pattern(acc, ctx, it, rest_pat), + // FIXME + // ast::TuplePat(it) => (), + // FIXME + // ast::SlicePat(it) => (), + _ => return None, + } + } +} + +// Assist: expand_record_rest_pattern // // Fills fields by replacing rest pattern in record patterns. // @@ -24,22 +42,12 @@ use crate::{AssistContext, AssistId, Assists}; // let Bar { y, z } = bar; // } // ``` -pub(crate) fn expand_rest_pattern(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { - let rest_pat = ctx.find_node_at_offset::()?; - let parent = rest_pat.syntax().parent()?; - let record_pat = match_ast! { - match parent { - ast::RecordPatFieldList(it) => ast::RecordPat::cast(it.syntax().parent()?)?, - // ast::TupleStructPat(it) => (), - // ast::TuplePat(it) => (), - // ast::SlicePat(it) => (), - _ => return None, - } - }; - - let ellipsis = record_pat.record_pat_field_list().and_then(|r| r.rest_pat())?; - let target_range = ellipsis.syntax().text_range(); - +fn expand_record_rest_pattern( + acc: &mut Assists, + ctx: &AssistContext<'_>, + record_pat: ast::RecordPat, + rest_pat: ast::RestPat, +) -> Option<()> { let missing_fields = ctx.sema.record_pattern_missing_fields(&record_pat); if missing_fields.is_empty() { @@ -48,6 +56,11 @@ pub(crate) fn expand_rest_pattern(acc: &mut Assists, ctx: &AssistContext<'_>) -> } let old_field_list = record_pat.record_pat_field_list()?; + let old_range = ctx.sema.original_range_opt(old_field_list.syntax())?; + if old_range.file_id != ctx.file_id() { + return None; + } + let new_field_list = make::record_pat_field_list(old_field_list.fields(), None).clone_for_update(); for (f, _) in missing_fields.iter() { @@ -58,16 +71,93 @@ pub(crate) fn expand_rest_pattern(acc: &mut Assists, ctx: &AssistContext<'_>) -> new_field_list.add_field(field.clone_for_update()); } - let old_range = ctx.sema.original_range_opt(old_field_list.syntax())?; + let target_range = rest_pat.syntax().text_range(); + acc.add( + AssistId("expand_record_rest_pattern", crate::AssistKind::RefactorRewrite), + "Fill struct fields", + target_range, + move |builder| builder.replace_ast(old_field_list, new_field_list), + ) +} +// Assist: expand_tuple_struct_rest_pattern +// +// Fills fields by replacing rest pattern in tuple struct patterns. +// +// ``` +// struct Bar(Y, Z); +// +// fn foo(bar: Bar) { +// let Bar(..$0) = bar; +// } +// ``` +// -> +// ``` +// struct Bar(Y, Z); +// +// fn foo(bar: Bar) { +// let Bar(_0, _1) = bar; +// } +// ``` +fn expand_tuple_struct_rest_pattern( + acc: &mut Assists, + ctx: &AssistContext<'_>, + pat: ast::TupleStructPat, + rest_pat: ast::RestPat, +) -> Option<()> { + let path = pat.path()?; + let fields = match ctx.sema.type_of_pat(&pat.clone().into())?.original.as_adt()? { + hir::Adt::Struct(s) if s.kind(ctx.sema.db) == StructKind::Tuple => s.fields(ctx.sema.db), + hir::Adt::Enum(_) => match ctx.sema.resolve_path(&path)? { + PathResolution::Def(hir::ModuleDef::Variant(v)) + if v.kind(ctx.sema.db) == StructKind::Tuple => + { + v.fields(ctx.sema.db) + } + _ => return None, + }, + _ => return None, + }; + + let rest_pat = rest_pat.into(); + let mut pats = pat.fields(); + let prefix_count = pats.by_ref().position(|p| p == rest_pat)?; + let suffix_count = pats.count(); + + if fields.len().saturating_sub(prefix_count).saturating_sub(suffix_count) == 0 { + cov_mark::hit!(no_missing_fields_tuple_struct); + return None; + } + + let old_range = ctx.sema.original_range_opt(pat.syntax())?; if old_range.file_id != ctx.file_id() { return None; } + let mut name_gen = NameGenerator::new_from_scope_locals(ctx.sema.scope(pat.syntax())); + let new_pat = make::tuple_struct_pat( + path, + pat.fields() + .take(prefix_count) + .chain(fields[prefix_count..fields.len() - suffix_count].iter().map(|f| { + make::ident_pat( + false, + false, + match name_gen.for_type(&f.ty(ctx.sema.db), ctx.sema.db, ctx.edition()) { + Some(name) => make::name(&name), + None => make::name(&format!("_{}", f.index())), + }, + ) + .into() + })) + .chain(pat.fields().skip(prefix_count + 1)), + ); + + let target_range = rest_pat.syntax().text_range(); acc.add( - AssistId("expand_rest_pattern", crate::AssistKind::RefactorRewrite), - "Fill structure fields", + AssistId("expand_tuple_struct_rest_pattern", crate::AssistKind::RefactorRewrite), + "Fill tuple struct fields", target_range, - move |builder| builder.replace_ast(old_field_list, new_field_list), + move |builder| builder.replace_ast(pat, new_pat), ) } @@ -165,6 +255,27 @@ struct Bar { fn foo(bar: Bar) { let Bar { y, z } = bar; } +"#, + ); + check_assist( + expand_rest_pattern, + r#" +struct Y; +struct Z; +struct Bar(Y, Z) + +fn foo(bar: Bar) { + let Bar(..$0) = bar; +} +"#, + r#" +struct Y; +struct Z; +struct Bar(Y, Z) + +fn foo(bar: Bar) { + let Bar(y, z) = bar; +} "#, ) } @@ -192,6 +303,29 @@ struct Bar { fn foo(bar: Bar) { let Bar { y, z } = bar; } +"#, + ); + check_assist( + expand_rest_pattern, + r#" +struct X; +struct Y; +struct Z; +struct Bar(X, Y, Z) + +fn foo(bar: Bar) { + let Bar(x, ..$0, z) = bar; +} +"#, + r#" +struct X; +struct Y; +struct Z; +struct Bar(X, Y, Z) + +fn foo(bar: Bar) { + let Bar(x, y, z) = bar; +} "#, ) } @@ -330,6 +464,7 @@ fn bar(foo: Foo) { fn not_applicable_when_no_missing_fields() { // This is still possible even though it's meaningless cov_mark::check!(no_missing_fields); + cov_mark::check!(no_missing_fields_tuple_struct); check_assist_not_applicable( expand_rest_pattern, r#" @@ -357,6 +492,16 @@ struct Bar { fn foo(bar: Bar) { let Bar { y, z, ..$0 } = bar; } +"#, + ); + check_assist_not_applicable( + expand_rest_pattern, + r#" +struct Bar(Y, Z) + +fn foo(bar: Bar) { + let Bar(y, ..$0, z) = bar; +} "#, ); } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs index dd994ef4a640c..46688a22f3337 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs @@ -956,9 +956,9 @@ pub use foo::{Bar, Baz}; } #[test] -fn doctest_expand_rest_pattern() { +fn doctest_expand_record_rest_pattern() { check_doc_test( - "expand_rest_pattern", + "expand_record_rest_pattern", r#####" struct Bar { y: Y, z: Z } @@ -976,6 +976,27 @@ fn foo(bar: Bar) { ) } +#[test] +fn doctest_expand_tuple_struct_rest_pattern() { + check_doc_test( + "expand_tuple_struct_rest_pattern", + r#####" +struct Bar(Y, Z); + +fn foo(bar: Bar) { + let Bar(..$0) = bar; +} +"#####, + r#####" +struct Bar(Y, Z); + +fn foo(bar: Bar) { + let Bar(_0, _1) = bar; +} +"#####, + ) +} + #[test] fn doctest_extract_constant() { check_doc_test( diff --git a/src/tools/rust-analyzer/docs/book/src/assists_generated.md b/src/tools/rust-analyzer/docs/book/src/assists_generated.md index 743e5c5e10d40..b815cad0a230a 100644 --- a/src/tools/rust-analyzer/docs/book/src/assists_generated.md +++ b/src/tools/rust-analyzer/docs/book/src/assists_generated.md @@ -1069,8 +1069,8 @@ pub use foo::{Bar, Baz}; ``` -### `expand_rest_pattern` -**Source:** [expand_rest_pattern.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/expand_rest_pattern.rs#L8) +### `expand_record_rest_pattern` +**Source:** [expand_rest_pattern.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/expand_rest_pattern.rs#L24) Fills fields by replacing rest pattern in record patterns. @@ -1093,6 +1093,30 @@ fn foo(bar: Bar) { ``` +### `expand_tuple_struct_rest_pattern` +**Source:** [expand_rest_pattern.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/expand_rest_pattern.rs#L80) + +Fills fields by replacing rest pattern in tuple struct patterns. + +#### Before +```rust +struct Bar(Y, Z); + +fn foo(bar: Bar) { + let Bar(..┃) = bar; +} +``` + +#### After +```rust +struct Bar(Y, Z); + +fn foo(bar: Bar) { + let Bar(_0, _1) = bar; +} +``` + + ### `extract_constant` **Source:** [extract_variable.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/extract_variable.rs#L35) From de07b171effdd344c51907998236dd6aafaa5b72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Mon, 3 Mar 2025 16:03:06 +0200 Subject: [PATCH 08/53] Bump minimum supported toolchain to 1.82 --- src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs index a0d6a0d6da6f8..b9e38f2e69176 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs @@ -12,7 +12,7 @@ /// Any toolchain less than this version will likely not work with rust-analyzer built from this revision. pub const MINIMUM_SUPPORTED_TOOLCHAIN_VERSION: semver::Version = semver::Version { major: 1, - minor: 78, + minor: 82, patch: 0, pre: semver::Prerelease::EMPTY, build: semver::BuildMetadata::EMPTY, From 0d6dfc80316ebe20570ea1ecccd8981d82d22610 Mon Sep 17 00:00:00 2001 From: Tongjun Gao Date: Tue, 4 Mar 2025 11:50:11 +0800 Subject: [PATCH 09/53] Improve keyword completion for 'let' and 'let mut' --- .../ide-completion/src/completions/expr.rs | 3 +- .../ide-completion/src/completions/keyword.rs | 30 +++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs index 365d2dde7e943..bb7eb6feab943 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs @@ -365,7 +365,8 @@ pub(crate) fn complete_expr_path( add_keyword("false", "false"); if in_condition || in_block_expr { - add_keyword("let", "let"); + add_keyword("let mut", "let mut $0"); + add_keyword("let", "let $0"); } if after_if_expr { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs index 6541ee502d83d..0a05cf67bd0ee 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs @@ -330,4 +330,34 @@ fn main() { ", ) } + + #[test] + fn completes_let_with_space() { + check_edit( + "let", + r#" +fn main() { + $0 +} +"#, + r#" +fn main() { + let $0 +} +"#, + ); + check_edit( + "let mut", + r#" +fn main() { + $0 +} +"#, + r#" +fn main() { + let mut $0 +} +"#, + ); + } } From 120d5490aa42fca4a0a7dbeb1322edd5fea2bb7d Mon Sep 17 00:00:00 2001 From: Tongjun Gao Date: Tue, 4 Mar 2025 12:04:54 +0800 Subject: [PATCH 10/53] change 'let mut' keyword completion into 'ietm' snippet --- .../rust-analyzer/crates/ide-completion/src/completions/expr.rs | 2 +- .../crates/ide-completion/src/completions/keyword.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs index bb7eb6feab943..b28b6e50e2284 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs @@ -365,7 +365,7 @@ pub(crate) fn complete_expr_path( add_keyword("false", "false"); if in_condition || in_block_expr { - add_keyword("let mut", "let mut $0"); + add_keyword("letm", "let mut $0"); add_keyword("let", "let $0"); } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs index 0a05cf67bd0ee..26c29e0202c0d 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs @@ -347,7 +347,7 @@ fn main() { "#, ); check_edit( - "let mut", + "letm", r#" fn main() { $0 From b9d157c67a681e90968192cf52632028194d1231 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Wed, 5 Mar 2025 07:52:23 +0200 Subject: [PATCH 11/53] Twiddle with the rustup invocation on CI --- src/tools/rust-analyzer/.github/workflows/ci.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/tools/rust-analyzer/.github/workflows/ci.yaml b/src/tools/rust-analyzer/.github/workflows/ci.yaml index bc770dbe71e45..1b011c90d031b 100644 --- a/src/tools/rust-analyzer/.github/workflows/ci.yaml +++ b/src/tools/rust-analyzer/.github/workflows/ci.yaml @@ -67,8 +67,7 @@ jobs: rustup component add --toolchain ${{ env.RUST_CHANNEL }} rust-src # We always use a nightly rustfmt, regardless of channel, because we need # --file-lines. - rustup toolchain add nightly --profile minimal - rustup component add --toolchain nightly rustfmt + rustup toolchain install nightly --profile minimal --component rustfmt # https://github.com/actions-rust-lang/setup-rust-toolchain/blob/main/rust.json - name: Install Rust Problem Matcher if: matrix.os == 'ubuntu-latest' From 0ffef9b5d158ce1954ce7b715e675d50b863bc05 Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Wed, 5 Mar 2025 00:21:02 -0800 Subject: [PATCH 12/53] minicore: Add size_of to prelude and add rust_2024 prelude --- .../crates/ide-completion/src/tests/expression.rs | 1 + src/tools/rust-analyzer/crates/test-utils/src/minicore.rs | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs index 375575128377d..68218ae03fd3d 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs @@ -1920,6 +1920,7 @@ fn bar() { md rust_2015 (use core::prelude::rust_2015) md rust_2018 (use core::prelude::rust_2018) md rust_2021 (use core::prelude::rust_2021) + md rust_2024 (use core::prelude::rust_2024) tt Clone tt Copy tt IntoIterator diff --git a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs index 202afebde70fb..d01db2d04cb76 100644 --- a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs +++ b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs @@ -1874,6 +1874,7 @@ pub mod prelude { marker::Sized, // :sized marker::Sync, // :sync mem::drop, // :drop + mem::size_of, // :size_of ops::Drop, // :drop ops::{AsyncFn, AsyncFnMut, AsyncFnOnce}, // :async_fn ops::{Fn, FnMut, FnOnce}, // :fn @@ -1895,6 +1896,10 @@ pub mod prelude { pub mod rust_2021 { pub use super::v1::*; } + + pub mod rust_2024 { + pub use super::v1::*; + } } #[prelude_import] From 653801b854841fadbbf3bba83779a8ba82a2de8c Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Tue, 4 Mar 2025 20:28:38 -0800 Subject: [PATCH 13/53] Use size_of from the prelude instead of imported Use `std::mem::{size_of, size_of_val, align_of, align_of_val}` from the prelude instead of importing or qualifying them. These functions were added to all preludes in Rust 1.80. --- .../crates/hir-def/src/hir/type_ref.rs | 2 +- .../crates/hir-ty/src/consteval/tests.rs | 3 +- .../crates/hir-ty/src/display.rs | 2 +- .../crates/hir-ty/src/mir/eval.rs | 4 +-- .../crates/hir-ty/src/mir/lower.rs | 2 +- .../crates/ide-db/src/generated/lints.rs | 4 +-- .../crates/ide-db/src/symbol_index.rs | 3 +- .../rust-analyzer/crates/ide/src/status.rs | 3 +- .../rust-analyzer/crates/intern/src/symbol.rs | 31 +++++++------------ .../crates/profile/src/memory_usage.rs | 2 +- .../crates/test-utils/src/minicore.rs | 2 +- 11 files changed, 24 insertions(+), 34 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs index 6d4d519cd2b7c..6de4026dff75b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs @@ -260,7 +260,7 @@ pub enum TypeBound { } #[cfg(target_pointer_width = "64")] -const _: [(); 24] = [(); ::std::mem::size_of::()]; +const _: [(); 24] = [(); size_of::()]; #[derive(Clone, PartialEq, Eq, Hash, Debug)] pub enum UseArgRef { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs index 2d7d4cacd2c56..249170c4f3eec 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs @@ -2713,12 +2713,11 @@ fn const_trait_assoc() { r#" //- minicore: size_of, fn //- /a/lib.rs crate:a - use core::mem::size_of; pub struct S(T); impl S { pub const X: usize = { let k: T; - let f = || core::mem::size_of::(); + let f = || size_of::(); f() }; } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs index 49f061813d101..6ee4780d206fe 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs @@ -4,7 +4,7 @@ use std::{ fmt::{self, Debug}, - mem::{self, size_of}, + mem, }; use base_db::CrateId; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs index 6b20522cf34c4..d0f9f4519caa7 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs @@ -302,7 +302,7 @@ impl Address { } } - fn to_bytes(&self) -> [u8; mem::size_of::()] { + fn to_bytes(&self) -> [u8; size_of::()] { usize::to_le_bytes(self.to_usize()) } @@ -589,7 +589,7 @@ pub fn interpret_mir( let ty = body.locals[return_slot()].ty.clone(); let mut evaluator = Evaluator::new(db, body.owner, assert_placeholder_ty_is_unused, trait_env)?; let it: Result = (|| { - if evaluator.ptr_size() != std::mem::size_of::() { + if evaluator.ptr_size() != size_of::() { not_supported!("targets with different pointer size from host"); } let interval = evaluator.interpret_mir(body.clone(), None.into_iter())?; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs index f88696692e6a7..2fe4ce8319e27 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs @@ -1394,7 +1394,7 @@ impl<'ctx> MirLowerCtx<'ctx> { .layout_of_ty(ty.clone(), self.db.trait_environment_for_body(self.owner)) .map(|it| it.size.bytes_usize()) }; - const USIZE_SIZE: usize = mem::size_of::(); + const USIZE_SIZE: usize = size_of::(); let bytes: Box<[_]> = match l { hir_def::hir::Literal::String(b) => { let b = b.as_str(); diff --git a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs index ed9d6c67501e2..333dbe33059c5 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs @@ -15086,7 +15086,7 @@ cannot be represented as the underlying type without loss."##, }, Lint { label: "clippy::manual_bits", - description: r##"Checks for usage of `std::mem::size_of::() * 8` when + description: r##"Checks for usage of `size_of::() * 8` when `T::BITS` is available."##, default_severity: Severity::Allow, warn_since: None, @@ -17428,7 +17428,7 @@ count of elements of type `T`"##, }, Lint { label: "clippy::size_of_ref", - description: r##"Checks for calls to `std::mem::size_of_val()` where the argument is + description: r##"Checks for calls to `size_of_val()` where the argument is a reference to a reference."##, default_severity: Severity::Allow, warn_since: None, diff --git a/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs b/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs index bb4c289c9084e..2737436993deb 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs @@ -24,7 +24,6 @@ use std::{ cmp::Ordering, fmt, hash::{Hash, Hasher}, - mem, ops::ControlFlow, }; @@ -299,7 +298,7 @@ impl SymbolIndex { } pub fn memory_size(&self) -> usize { - self.map.as_fst().size() + self.symbols.len() * mem::size_of::() + self.map.as_fst().size() + self.symbols.len() * size_of::() } fn range_to_map_value(start: usize, end: usize) -> u64 { diff --git a/src/tools/rust-analyzer/crates/ide/src/status.rs b/src/tools/rust-analyzer/crates/ide/src/status.rs index f8ecaa8fdf25f..a44be67668ce3 100644 --- a/src/tools/rust-analyzer/crates/ide/src/status.rs +++ b/src/tools/rust-analyzer/crates/ide/src/status.rs @@ -268,8 +268,7 @@ struct AttrsStats { impl fmt::Display for AttrsStats { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - let size = - self.entries * std::mem::size_of::() + self.total * std::mem::size_of::(); + let size = self.entries * size_of::() + self.total * size_of::(); let size = Bytes::new(size as _); write!( fmt, diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol.rs b/src/tools/rust-analyzer/crates/intern/src/symbol.rs index b3bf285edfb11..0fa6701ca3fa3 100644 --- a/src/tools/rust-analyzer/crates/intern/src/symbol.rs +++ b/src/tools/rust-analyzer/crates/intern/src/symbol.rs @@ -18,20 +18,17 @@ use triomphe::Arc; pub mod symbols; // some asserts for layout compatibility -const _: () = assert!(std::mem::size_of::>() == std::mem::size_of::<&str>()); -const _: () = assert!(std::mem::align_of::>() == std::mem::align_of::<&str>()); +const _: () = assert!(size_of::>() == size_of::<&str>()); +const _: () = assert!(align_of::>() == align_of::<&str>()); -const _: () = assert!(std::mem::size_of::>>() == std::mem::size_of::<&&str>()); -const _: () = assert!(std::mem::align_of::>>() == std::mem::align_of::<&&str>()); +const _: () = assert!(size_of::>>() == size_of::<&&str>()); +const _: () = assert!(align_of::>>() == align_of::<&&str>()); -const _: () = - assert!(std::mem::size_of::<*const *const str>() == std::mem::size_of::()); -const _: () = - assert!(std::mem::align_of::<*const *const str>() == std::mem::align_of::()); +const _: () = assert!(size_of::<*const *const str>() == size_of::()); +const _: () = assert!(align_of::<*const *const str>() == align_of::()); -const _: () = assert!(std::mem::size_of::>>() == std::mem::size_of::()); -const _: () = - assert!(std::mem::align_of::>>() == std::mem::align_of::()); +const _: () = assert!(size_of::>>() == size_of::()); +const _: () = assert!(align_of::>>() == align_of::()); /// A pointer that points to a pointer to a `str`, it may be backed as a `&'static &'static str` or /// `Arc>` but its size is that of a thin pointer. The active variant is encoded as a tag @@ -49,9 +46,7 @@ impl TaggedArcPtr { const BOOL_BITS: usize = true as usize; const fn non_arc(r: &'static &'static str) -> Self { - assert!( - mem::align_of::<&'static &'static str>().trailing_zeros() as usize > Self::BOOL_BITS - ); + assert!(align_of::<&'static &'static str>().trailing_zeros() as usize > Self::BOOL_BITS); // SAFETY: The pointer is non-null as it is derived from a reference // Ideally we would call out to `pack_arc` but for a `false` tag, unfortunately the // packing stuff requires reading out the pointer to an integer which is not supported @@ -64,9 +59,7 @@ impl TaggedArcPtr { } fn arc(arc: Arc>) -> Self { - assert!( - mem::align_of::<&'static &'static str>().trailing_zeros() as usize > Self::BOOL_BITS - ); + assert!(align_of::<&'static &'static str>().trailing_zeros() as usize > Self::BOOL_BITS); Self { packed: Self::pack_arc( // Safety: `Arc::into_raw` always returns a non null pointer @@ -131,8 +124,8 @@ impl fmt::Debug for Symbol { } } -const _: () = assert!(std::mem::size_of::() == std::mem::size_of::>()); -const _: () = assert!(std::mem::align_of::() == std::mem::align_of::>()); +const _: () = assert!(size_of::() == size_of::>()); +const _: () = assert!(align_of::() == align_of::>()); static MAP: OnceLock>> = OnceLock::new(); diff --git a/src/tools/rust-analyzer/crates/profile/src/memory_usage.rs b/src/tools/rust-analyzer/crates/profile/src/memory_usage.rs index 006748ddb08ea..f5b8eca060f96 100644 --- a/src/tools/rust-analyzer/crates/profile/src/memory_usage.rs +++ b/src/tools/rust-analyzer/crates/profile/src/memory_usage.rs @@ -38,7 +38,7 @@ impl MemoryUsage { // approximate that by using the Commit Charge value. use windows_sys::Win32::System::{Threading::*, ProcessStatus::*}; - use std::mem::{MaybeUninit, size_of}; + use std::mem::MaybeUninit; let proc = unsafe { GetCurrentProcess() }; let mut mem_counters = MaybeUninit::uninit(); diff --git a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs index d01db2d04cb76..bf53e58d70cef 100644 --- a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs +++ b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs @@ -1825,7 +1825,7 @@ macro_rules! impl_int { ($($t:ty)*) => { $( impl $t { - pub const fn from_ne_bytes(bytes: [u8; mem::size_of::()]) -> Self { + pub const fn from_ne_bytes(bytes: [u8; size_of::()]) -> Self { unsafe { mem::transmute(bytes) } } } From 5421fba7469f0669dc61a822deaf34c9b404816a Mon Sep 17 00:00:00 2001 From: Tongjun Gao Date: Wed, 5 Mar 2025 17:26:30 +0800 Subject: [PATCH 14/53] add test cases for 'letm' keyword completion --- .../crates/ide-completion/src/tests/expression.rs | 14 ++++++++++++++ .../crates/ide-completion/src/tests/item.rs | 1 + .../crates/ide-completion/src/tests/special.rs | 4 ++++ 3 files changed, 19 insertions(+) diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs index 375575128377d..e91c399f0bb02 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs @@ -170,6 +170,7 @@ impl Unit { kw if let kw impl kw let + kw letm kw loop kw match kw mod @@ -247,6 +248,7 @@ fn complete_in_block() { kw if let kw impl kw let + kw letm kw loop kw match kw mod @@ -297,6 +299,7 @@ fn complete_after_if_expr() { kw if let kw impl kw let + kw letm kw loop kw match kw mod @@ -370,6 +373,7 @@ fn completes_in_loop_ctx() { kw if let kw impl kw let + kw letm kw loop kw match kw mod @@ -942,6 +946,7 @@ fn foo() { if foo {} $0 } kw if let kw impl kw let + kw letm kw loop kw match kw mod @@ -983,6 +988,7 @@ fn foo() { if foo {} el$0 } kw if let kw impl kw let + kw letm kw loop kw match kw mod @@ -1072,6 +1078,7 @@ fn foo() { if foo {} $0 let x = 92; } kw if let kw impl kw let + kw letm kw loop kw match kw mod @@ -1113,6 +1120,7 @@ fn foo() { if foo {} el$0 let x = 92; } kw if let kw impl kw let + kw letm kw loop kw match kw mod @@ -1154,6 +1162,7 @@ fn foo() { if foo {} el$0 { let x = 92; } } kw if let kw impl kw let + kw letm kw loop kw match kw mod @@ -1205,6 +1214,7 @@ pub struct UnstableThisShouldNotBeListed; kw if let kw impl kw let + kw letm kw loop kw match kw mod @@ -1258,6 +1268,7 @@ pub struct UnstableButWeAreOnNightlyAnyway; kw if let kw impl kw let + kw letm kw loop kw match kw mod @@ -1495,6 +1506,7 @@ fn main() { kw if let kw impl kw let + kw letm kw loop kw match kw mod @@ -1944,6 +1956,7 @@ fn bar() { kw if let kw impl kw let + kw letm kw loop kw match kw mod @@ -2015,6 +2028,7 @@ fn foo() { kw if let kw impl kw let + kw letm kw loop kw match kw mod diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/item.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/item.rs index bea6d60769cc9..be2c37d10162e 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/item.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/item.rs @@ -285,6 +285,7 @@ fn bar() { kw if let kw impl kw let + kw letm kw loop kw match kw mod diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs index 2b05184bdbeba..005263d100a5b 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs @@ -1009,6 +1009,7 @@ fn here_we_go() { kw if let kw impl kw let + kw letm kw loop kw match kw mod @@ -1059,6 +1060,7 @@ fn here_we_go() { kw if let kw impl kw let + kw letm kw loop kw match kw mod @@ -1182,6 +1184,7 @@ fn bar() { qu$0 } kw if let kw impl kw let + kw letm kw loop kw match kw mod @@ -1437,6 +1440,7 @@ fn foo() { kw if let kw impl kw let + kw letm kw loop kw match kw mod From 049f4dbd2b990f46772d07f07d54c7ea6ccca7fd Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Wed, 5 Mar 2025 10:40:11 +0100 Subject: [PATCH 15/53] Add warning and debug information when `cargo metadata` fails The errors are silently dropped elsewhere, which make it really hard to debug issues due to dependency download failures. --- .../crates/project-model/src/cargo_workspace.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs index 40ab8c53faeb8..e7c3bcb5418d7 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs @@ -288,7 +288,22 @@ impl CargoWorkspace { locked: bool, progress: &dyn Fn(String), ) -> anyhow::Result<(cargo_metadata::Metadata, Option)> { - Self::fetch_metadata_(cargo_toml, current_dir, config, sysroot, locked, false, progress) + let res = Self::fetch_metadata_( + cargo_toml, + current_dir, + config, + sysroot, + locked, + false, + progress, + ); + if let Ok((_, Some(ref e))) = res { + tracing::warn!( + "`cargo metadata` failed on `{cargo_toml}`, but retry with `--no-deps` succeeded" + ); + tracing::debug!("{e:?}"); + } + res } fn fetch_metadata_( From 52525bc913c8acce5033250deb3a70ad5107e95c Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Wed, 5 Mar 2025 12:49:42 +0100 Subject: [PATCH 16/53] Improve tracing log format in cargo_workspace.rs --- .../rust-analyzer/crates/project-model/src/cargo_workspace.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs index e7c3bcb5418d7..68a9fba09c722 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs @@ -299,7 +299,9 @@ impl CargoWorkspace { ); if let Ok((_, Some(ref e))) = res { tracing::warn!( - "`cargo metadata` failed on `{cargo_toml}`, but retry with `--no-deps` succeeded" + %cargo_toml, + %e, + "`cargo metadata` failed, but retry with `--no-deps` succeeded" ); tracing::debug!("{e:?}"); } From 87815f7c0bb0735ad5eb375a52e0b72709709466 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 3 Mar 2025 14:45:20 +0100 Subject: [PATCH 17/53] Use HIR unsafety information for unsafe syntax highlightng --- .../crates/hir-ty/src/diagnostics.rs | 5 +- .../hir-ty/src/diagnostics/unsafe_check.rs | 42 ++- .../rust-analyzer/crates/hir/src/semantics.rs | 113 ++---- .../crates/hir/src/source_analyzer.rs | 4 +- .../src/handlers/extract_function.rs | 5 +- .../ide-db/src/syntax_helpers/node_ext.rs | 22 +- .../crates/ide/src/syntax_highlighting.rs | 136 ++++--- .../ide/src/syntax_highlighting/format.rs | 2 +- .../ide/src/syntax_highlighting/highlight.rs | 353 +++++++++++------- .../ide/src/syntax_highlighting/html.rs | 7 +- .../test_data/highlight_asm.html | 33 +- .../test_data/highlight_assoc_functions.html | 7 +- .../test_data/highlight_attributes.html | 7 +- .../test_data/highlight_block_mod_items.html | 9 +- .../test_data/highlight_const.html | 21 +- .../test_data/highlight_crate_root.html | 7 +- .../test_data/highlight_default_library.html | 7 +- .../test_data/highlight_doctest.html | 9 +- .../test_data/highlight_extern_crate.html | 7 +- .../test_data/highlight_general.html | 9 +- .../test_data/highlight_injection.html | 7 +- .../test_data/highlight_issue_18089.html | 7 +- .../test_data/highlight_keywords_2015.html | 7 +- .../test_data/highlight_keywords_2018.html | 7 +- .../test_data/highlight_keywords_2021.html | 7 +- .../test_data/highlight_keywords_2024.html | 7 +- .../test_data/highlight_keywords_macros.html | 7 +- .../test_data/highlight_lifetimes.html | 7 +- .../test_data/highlight_macros.html | 7 +- .../highlight_module_docs_inline.html | 7 +- .../highlight_module_docs_outline.html | 7 +- .../test_data/highlight_operators.html | 7 +- .../test_data/highlight_rainbow.html | 7 +- .../test_data/highlight_strings.html | 11 +- .../test_data/highlight_unsafe.html | 95 +++-- .../ide/src/syntax_highlighting/tests.rs | 76 ++-- .../docs/book/src/assists_generated.md | 6 +- 37 files changed, 547 insertions(+), 537 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics.rs index 30c02a2936dde..845d333335365 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics.rs @@ -9,5 +9,8 @@ pub use crate::diagnostics::{ expr::{ record_literal_missing_fields, record_pattern_missing_fields, BodyValidationDiagnostic, }, - unsafe_check::{missing_unsafe, unsafe_expressions, InsideUnsafeBlock, UnsafetyReason}, + unsafe_check::{ + missing_unsafe, unsafe_operations, unsafe_operations_for_body, InsideUnsafeBlock, + UnsafetyReason, + }, }; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs index ac849b0762d7f..d2b908839c42e 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs @@ -95,7 +95,26 @@ enum UnsafeDiagnostic { DeprecatedSafe2024 { node: ExprId, inside_unsafe_block: InsideUnsafeBlock }, } -pub fn unsafe_expressions( +pub fn unsafe_operations_for_body( + db: &dyn HirDatabase, + infer: &InferenceResult, + def: DefWithBodyId, + body: &Body, + callback: &mut dyn FnMut(ExprOrPatId), +) { + let mut visitor_callback = |diag| { + if let UnsafeDiagnostic::UnsafeOperation { node, .. } = diag { + callback(node); + } + }; + let mut visitor = UnsafeVisitor::new(db, infer, body, def, &mut visitor_callback); + visitor.walk_expr(body.body_expr); + for ¶m in &body.params { + visitor.walk_pat(param); + } +} + +pub fn unsafe_operations( db: &dyn HirDatabase, infer: &InferenceResult, def: DefWithBodyId, @@ -281,13 +300,6 @@ impl<'a> UnsafeVisitor<'a> { self.on_unsafe_op(current.into(), UnsafetyReason::RawPtrDeref); } } - Expr::Unsafe { .. } => { - let old_inside_unsafe_block = - mem::replace(&mut self.inside_unsafe_block, InsideUnsafeBlock::Yes); - self.body.walk_child_exprs_without_pats(current, |child| self.walk_expr(child)); - self.inside_unsafe_block = old_inside_unsafe_block; - return; - } &Expr::Assignment { target, value: _ } => { let old_inside_assignment = mem::replace(&mut self.inside_assignment, true); self.walk_pats_top(std::iter::once(target), current); @@ -306,6 +318,20 @@ impl<'a> UnsafeVisitor<'a> { } } } + Expr::Unsafe { statements, .. } => { + let old_inside_unsafe_block = + mem::replace(&mut self.inside_unsafe_block, InsideUnsafeBlock::Yes); + self.walk_pats_top( + statements.iter().filter_map(|statement| match statement { + &Statement::Let { pat, .. } => Some(pat), + _ => None, + }), + current, + ); + self.body.walk_child_exprs_without_pats(current, |child| self.walk_expr(child)); + self.inside_unsafe_block = old_inside_unsafe_block; + return; + } Expr::Block { statements, .. } | Expr::Async { statements, .. } => { self.walk_pats_top( statements.iter().filter_map(|statement| match statement { diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index bb67fa63a1d18..1b8531209c1b4 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -12,6 +12,7 @@ use std::{ use either::Either; use hir_def::{ + expr_store::ExprOrPatSource, hir::{Expr, ExprOrPatId}, lower::LowerCtx, nameres::{MacroSubNs, ModuleOrigin}, @@ -30,6 +31,7 @@ use hir_expand::{ name::AsName, ExpandResult, FileRange, InMacroFile, MacroCallId, MacroFileId, MacroFileIdExt, }; +use hir_ty::diagnostics::unsafe_operations_for_body; use intern::{sym, Symbol}; use itertools::Itertools; use rustc_hash::{FxHashMap, FxHashSet}; @@ -48,8 +50,8 @@ use crate::{ db::HirDatabase, semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, source_analyzer::{name_hygiene, resolve_hir_path, SourceAnalyzer}, - Access, Adjust, Adjustment, Adt, AutoBorrow, BindingMode, BuiltinAttr, Callable, Const, - ConstParam, Crate, DeriveHelper, Enum, Field, Function, GenericSubstitution, HasSource, + Adjust, Adjustment, Adt, AutoBorrow, BindingMode, BuiltinAttr, Callable, Const, ConstParam, + Crate, DefWithBody, DeriveHelper, Enum, Field, Function, GenericSubstitution, HasSource, HirFileId, Impl, InFile, InlineAsmOperand, ItemInNs, Label, LifetimeParam, Local, Macro, Module, ModuleDef, Name, OverloadedDeref, Path, ScopeDef, Static, Struct, ToolModule, Trait, TraitAlias, TupleField, Type, TypeAlias, TypeParam, Union, Variant, VariantDef, @@ -1555,6 +1557,19 @@ impl<'db> SemanticsImpl<'db> { .matched_arm } + pub fn get_unsafe_ops(&self, def: DefWithBody) -> FxHashSet { + let def = DefWithBodyId::from(def); + let (body, source_map) = self.db.body_with_source_map(def); + let infer = self.db.infer(def); + let mut res = FxHashSet::default(); + unsafe_operations_for_body(self.db, &infer, def, &body, &mut |node| { + if let Ok(node) = source_map.expr_or_pat_syntax(node) { + res.insert(node); + } + }); + res + } + pub fn is_unsafe_macro_call(&self, macro_call: &ast::MacroCall) -> bool { let Some(mac) = self.resolve_macro_call(macro_call) else { return false }; if mac.is_asm_or_global_asm(self.db) { @@ -1682,6 +1697,15 @@ impl<'db> SemanticsImpl<'db> { Some(res) } + pub fn body_for(&self, node: InFile<&SyntaxNode>) -> Option { + let container = self.with_ctx(|ctx| ctx.find_container(node))?; + + match container { + ChildContainer::DefWithBodyId(def) => Some(def.into()), + _ => None, + } + } + /// Returns none if the file of the node is not part of a crate. fn analyze(&self, node: &SyntaxNode) -> Option { let node = self.find_file(node); @@ -1783,91 +1807,6 @@ impl<'db> SemanticsImpl<'db> { InFile::new(file_id, node) } - pub fn is_unsafe_method_call(&self, method_call_expr: &ast::MethodCallExpr) -> bool { - method_call_expr - .receiver() - .and_then(|expr| { - let field_expr = match expr { - ast::Expr::FieldExpr(field_expr) => field_expr, - _ => return None, - }; - let ty = self.type_of_expr(&field_expr.expr()?)?.original; - if !ty.is_packed(self.db) { - return None; - } - - let func = self.resolve_method_call(method_call_expr)?; - let res = match func.self_param(self.db)?.access(self.db) { - Access::Shared | Access::Exclusive => true, - Access::Owned => false, - }; - Some(res) - }) - .unwrap_or(false) - } - - pub fn is_unsafe_ref_expr(&self, ref_expr: &ast::RefExpr) -> bool { - ref_expr - .expr() - .and_then(|expr| { - let field_expr = match expr { - ast::Expr::FieldExpr(field_expr) => field_expr, - _ => return None, - }; - let expr = field_expr.expr()?; - self.type_of_expr(&expr) - }) - // Binding a reference to a packed type is possibly unsafe. - .map(|ty| ty.original.is_packed(self.db)) - .unwrap_or(false) - - // FIXME This needs layout computation to be correct. It will highlight - // more than it should with the current implementation. - } - - pub fn is_unsafe_ident_pat(&self, ident_pat: &ast::IdentPat) -> bool { - if ident_pat.ref_token().is_none() { - return false; - } - - ident_pat - .syntax() - .parent() - .and_then(|parent| { - // `IdentPat` can live under `RecordPat` directly under `RecordPatField` or - // `RecordPatFieldList`. `RecordPatField` also lives under `RecordPatFieldList`, - // so this tries to lookup the `IdentPat` anywhere along that structure to the - // `RecordPat` so we can get the containing type. - let record_pat = ast::RecordPatField::cast(parent.clone()) - .and_then(|record_pat| record_pat.syntax().parent()) - .or_else(|| Some(parent.clone())) - .and_then(|parent| { - ast::RecordPatFieldList::cast(parent)? - .syntax() - .parent() - .and_then(ast::RecordPat::cast) - }); - - // If this doesn't match a `RecordPat`, fallback to a `LetStmt` to see if - // this is initialized from a `FieldExpr`. - if let Some(record_pat) = record_pat { - self.type_of_pat(&ast::Pat::RecordPat(record_pat)) - } else if let Some(let_stmt) = ast::LetStmt::cast(parent) { - let field_expr = match let_stmt.initializer()? { - ast::Expr::FieldExpr(field_expr) => field_expr, - _ => return None, - }; - - self.type_of_expr(&field_expr.expr()?) - } else { - None - } - }) - // Binding a reference to a packed type is possibly unsafe. - .map(|ty| ty.original.is_packed(self.db)) - .unwrap_or(false) - } - /// Returns `true` if the `node` is inside an `unsafe` context. pub fn is_inside_unsafe(&self, expr: &ast::Expr) -> bool { let Some(enclosing_item) = diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs index 9019863f7fdee..d1245f5f7d681 100644 --- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs +++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs @@ -35,7 +35,7 @@ use hir_expand::{ }; use hir_ty::{ diagnostics::{ - record_literal_missing_fields, record_pattern_missing_fields, unsafe_expressions, + record_literal_missing_fields, record_pattern_missing_fields, unsafe_operations, InsideUnsafeBlock, }, from_assoc_type_id, @@ -1160,7 +1160,7 @@ impl SourceAnalyzer { if let Some(expanded_expr) = sm.macro_expansion_expr(macro_expr) { let mut is_unsafe = false; let mut walk_expr = |expr_id| { - unsafe_expressions(db, infer, *def, body, expr_id, &mut |inside_unsafe_block| { + unsafe_operations(db, infer, *def, body, expr_id, &mut |inside_unsafe_block| { is_unsafe |= inside_unsafe_block == InsideUnsafeBlock::No }) }; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs index 751e4a5a5719c..330587e0dbfbe 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs @@ -750,7 +750,10 @@ impl FunctionBody { ast::Stmt::Item(_) => (), ast::Stmt::LetStmt(stmt) => { if let Some(pat) = stmt.pat() { - walk_pat(&pat, cb); + walk_pat(&pat, &mut |pat| { + cb(pat); + std::ops::ControlFlow::<(), ()>::Continue(()) + }); } if let Some(expr) = stmt.initializer() { walk_patterns_in_expr(&expr, cb); diff --git a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs index 74c0b8e2baace..0b2e8aa6836f2 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs @@ -1,4 +1,6 @@ //! Various helper functions to work with SyntaxNodes. +use std::ops::ControlFlow; + use itertools::Itertools; use parser::T; use span::Edition; @@ -119,7 +121,10 @@ pub fn walk_patterns_in_expr(start: &ast::Expr, cb: &mut dyn FnMut(ast::Pat)) { match ast::Stmt::cast(node.clone()) { Some(ast::Stmt::LetStmt(l)) => { if let Some(pat) = l.pat() { - walk_pat(&pat, cb); + walk_pat(&pat, &mut |pat| { + cb(pat); + ControlFlow::<(), ()>::Continue(()) + }); } if let Some(expr) = l.initializer() { walk_patterns_in_expr(&expr, cb); @@ -154,7 +159,10 @@ pub fn walk_patterns_in_expr(start: &ast::Expr, cb: &mut dyn FnMut(ast::Pat)) { } } else if let Some(pat) = ast::Pat::cast(node) { preorder.skip_subtree(); - walk_pat(&pat, cb); + walk_pat(&pat, &mut |pat| { + cb(pat); + ControlFlow::<(), ()>::Continue(()) + }); } } } @@ -162,7 +170,10 @@ pub fn walk_patterns_in_expr(start: &ast::Expr, cb: &mut dyn FnMut(ast::Pat)) { } /// Preorder walk all the pattern's sub patterns. -pub fn walk_pat(pat: &ast::Pat, cb: &mut dyn FnMut(ast::Pat)) { +pub fn walk_pat( + pat: &ast::Pat, + cb: &mut dyn FnMut(ast::Pat) -> ControlFlow, +) -> ControlFlow { let mut preorder = pat.syntax().preorder(); while let Some(event) = preorder.next() { let node = match event { @@ -173,10 +184,10 @@ pub fn walk_pat(pat: &ast::Pat, cb: &mut dyn FnMut(ast::Pat)) { match ast::Pat::cast(node) { Some(pat @ ast::Pat::ConstBlockPat(_)) => { preorder.skip_subtree(); - cb(pat); + cb(pat)?; } Some(pat) => { - cb(pat); + cb(pat)?; } // skip const args None if ast::GenericArg::can_cast(kind) => { @@ -185,6 +196,7 @@ pub fn walk_pat(pat: &ast::Pat, cb: &mut dyn FnMut(ast::Pat)) { None => (), } } + ControlFlow::Continue(()) } /// Preorder walk all the type's sub types. diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs index 519133e3ad18c..62dc92feb1d62 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs @@ -14,8 +14,11 @@ mod tests; use std::ops::ControlFlow; -use hir::{HirFileIdExt, InFile, InRealFile, MacroFileIdExt, MacroKind, Name, Semantics}; -use ide_db::{FxHashMap, Ranker, RootDatabase, SymbolKind}; +use either::Either; +use hir::{ + DefWithBody, HirFileIdExt, InFile, InRealFile, MacroFileIdExt, MacroKind, Name, Semantics, +}; +use ide_db::{FxHashMap, FxHashSet, Ranker, RootDatabase, SymbolKind}; use span::EditionedFileId; use syntax::{ ast::{self, IsString}, @@ -232,7 +235,6 @@ fn traverse( range_to_highlight: TextRange, ) { let is_unlinked = sema.file_to_module_def(file_id).is_none(); - let mut bindings_shadow_count: FxHashMap = FxHashMap::default(); enum AttrOrDerive { Attr(ast::Item), @@ -247,13 +249,22 @@ fn traverse( } } + let empty = FxHashSet::default(); + + // FIXME: accommodate range highlighting let mut tt_level = 0; + // FIXME: accommodate range highlighting let mut attr_or_derive_item = None; // FIXME: these are not perfectly accurate, we determine them by the real file's syntax tree // an attribute nested in a macro call will not emit `inside_attribute` let mut inside_attribute = false; + // FIXME: accommodate range highlighting + let mut body_stack: Vec> = vec![]; + let mut per_body_cache: FxHashMap, FxHashMap)> = + FxHashMap::default(); + // Walk all nodes, keeping track of whether we are inside a macro or not. // If in macro, expand it first and highlight the expanded code. let mut preorder = root.preorder_with_tokens(); @@ -282,48 +293,68 @@ fn traverse( Leave(NodeOrToken::Node(node)) if ast::Attr::can_cast(node.kind()) => { inside_attribute = false } - Enter(NodeOrToken::Node(node)) => { - if let Some(item) = ast::Item::cast(node.clone()) { + if let Some(item) = >::cast(node.clone()) { match item { - ast::Item::Fn(_) | ast::Item::Const(_) | ast::Item::Static(_) => { - bindings_shadow_count.clear() - } - _ => (), - } - - if attr_or_derive_item.is_none() { - if sema.is_attr_macro_call(InFile::new(file_id.into(), &item)) { - attr_or_derive_item = Some(AttrOrDerive::Attr(item)); - } else { - let adt = match item { - ast::Item::Enum(it) => Some(ast::Adt::Enum(it)), - ast::Item::Struct(it) => Some(ast::Adt::Struct(it)), - ast::Item::Union(it) => Some(ast::Adt::Union(it)), - _ => None, - }; - match adt { - Some(adt) - if sema - .is_derive_annotated(InFile::new(file_id.into(), &adt)) => - { - attr_or_derive_item = - Some(AttrOrDerive::Derive(ast::Item::from(adt))); + Either::Left(item) => { + match &item { + ast::Item::Fn(it) => { + body_stack.push(sema.to_def(it).map(Into::into)) + } + ast::Item::Const(it) => { + body_stack.push(sema.to_def(it).map(Into::into)) + } + ast::Item::Static(it) => { + body_stack.push(sema.to_def(it).map(Into::into)) } _ => (), } + + if attr_or_derive_item.is_none() { + if sema.is_attr_macro_call(InFile::new(file_id.into(), &item)) { + attr_or_derive_item = Some(AttrOrDerive::Attr(item)); + } else { + let adt = match item { + ast::Item::Enum(it) => Some(ast::Adt::Enum(it)), + ast::Item::Struct(it) => Some(ast::Adt::Struct(it)), + ast::Item::Union(it) => Some(ast::Adt::Union(it)), + _ => None, + }; + match adt { + Some(adt) + if sema.is_derive_annotated(InFile::new( + file_id.into(), + &adt, + )) => + { + attr_or_derive_item = + Some(AttrOrDerive::Derive(ast::Item::from(adt))); + } + _ => (), + } + } + } } + Either::Right(it) => body_stack.push(sema.to_def(&it).map(Into::into)), } } } - Leave(NodeOrToken::Node(node)) if ast::Item::can_cast(node.kind()) => { + Leave(NodeOrToken::Node(node)) + if >::can_cast(node.kind()) => + { match ast::Item::cast(node.clone()) { - Some(item) - if attr_or_derive_item.as_ref().is_some_and(|it| *it.item() == item) => - { - attr_or_derive_item = None; + Some(item) => { + if attr_or_derive_item.as_ref().is_some_and(|it| *it.item() == item) { + attr_or_derive_item = None; + } + if matches!( + item, + ast::Item::Fn(_) | ast::Item::Const(_) | ast::Item::Static(_) + ) { + body_stack.pop(); + } } - _ => (), + None => _ = body_stack.pop(), } } _ => (), @@ -361,16 +392,22 @@ fn traverse( None => false, }; - let descended_element = if in_macro { + let (descended_element, current_body) = match element { // Attempt to descend tokens into macro-calls. - match element { - NodeOrToken::Token(token) => descend_token(sema, InRealFile::new(file_id, token)), - n => InFile::new(file_id.into(), n), + NodeOrToken::Token(token) if in_macro => { + let descended = descend_token(sema, InRealFile::new(file_id, token)); + let body = match &descended.value { + NodeOrToken::Node(n) => { + sema.body_for(InFile::new(descended.file_id, n.syntax())) + } + NodeOrToken::Token(t) => { + t.parent().and_then(|it| sema.body_for(InFile::new(descended.file_id, &it))) + } + }; + (descended, body) } - } else { - InFile::new(file_id.into(), element) + n => (InFile::new(file_id.into(), n), body_stack.last().copied().flatten()), }; - // string highlight injections if let (Some(original_token), Some(descended_token)) = (original_token, descended_element.value.as_token()) @@ -390,12 +427,24 @@ fn traverse( } let edition = descended_element.file_id.edition(sema.db); + let (unsafe_ops, bindings_shadow_count) = match current_body { + Some(current_body) => { + let (ops, bindings) = per_body_cache + .entry(current_body) + .or_insert_with(|| (sema.get_unsafe_ops(current_body), Default::default())); + (&*ops, Some(bindings)) + } + None => (&empty, None), + }; + let is_unsafe_node = + |node| unsafe_ops.contains(&InFile::new(descended_element.file_id, node)); let element = match descended_element.value { NodeOrToken::Node(name_like) => { let hl = highlight::name_like( sema, krate, - &mut bindings_shadow_count, + bindings_shadow_count, + &is_unsafe_node, config.syntactic_name_ref_highlighting, name_like, edition, @@ -408,7 +457,8 @@ fn traverse( hl } NodeOrToken::Token(token) => { - highlight::token(sema, token, edition, tt_level > 0).zip(Some(None)) + highlight::token(sema, token, edition, &is_unsafe_node, tt_level > 0) + .zip(Some(None)) } }; if let Some((mut highlight, binding_hash)) = element { diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/format.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/format.rs index c63043621c276..cc02aff2acf8a 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/format.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/format.rs @@ -41,7 +41,7 @@ pub(super) fn highlight_format_string( if let Some(res) = res { stack.add(HlRange { range, - highlight: highlight_def(sema, krate, Definition::from(res), edition), + highlight: highlight_def(sema, krate, Definition::from(res), edition, true), binding_hash: None, }) } diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs index 127861a04bd8d..282fbb4433b22 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs @@ -1,17 +1,20 @@ //! Computes color for a single element. +use std::ops::ControlFlow; + use either::Either; use hir::{AsAssocItem, HasVisibility, MacroFileIdExt, Semantics}; use ide_db::{ defs::{Definition, IdentClass, NameClass, NameRefClass}, + syntax_helpers::node_ext::walk_pat, FxHashMap, RootDatabase, SymbolKind, }; use span::Edition; use stdx::hash_once; use syntax::{ - ast, match_ast, AstNode, AstToken, NodeOrToken, + ast, match_ast, AstNode, AstPtr, AstToken, NodeOrToken, SyntaxKind::{self, *}, - SyntaxNode, SyntaxToken, T, + SyntaxNode, SyntaxNodePtr, SyntaxToken, T, }; use crate::{ @@ -23,6 +26,7 @@ pub(super) fn token( sema: &Semantics<'_, RootDatabase>, token: SyntaxToken, edition: Edition, + is_unsafe_node: &impl Fn(AstPtr>) -> bool, in_tt: bool, ) -> Option { if let Some(comment) = ast::Comment::cast(token.clone()) { @@ -33,11 +37,8 @@ pub(super) fn token( }); } - let highlight: Highlight = match token.kind() { + let h = match token.kind() { STRING | BYTE_STRING | C_STRING => HlTag::StringLiteral.into(), - INT_NUMBER if token.parent_ancestors().nth(1).map(|it| it.kind()) == Some(FIELD_EXPR) => { - SymbolKind::Field.into() - } INT_NUMBER | FLOAT_NUMBER => HlTag::NumericLiteral.into(), BYTE => HlTag::ByteLiteral.into(), CHAR => HlTag::CharLiteral.into(), @@ -46,24 +47,25 @@ pub(super) fn token( // that were not mapped down into macro invocations HlTag::None.into() } - p if p.is_punct() => punctuation(sema, token, p), + p if p.is_punct() => punctuation(sema, token, p, is_unsafe_node), k if k.is_keyword(edition) => { if in_tt && token.prev_token().is_some_and(|t| t.kind() == T![$]) { // we are likely within a macro definition where our keyword is a fragment name HlTag::None.into() } else { - keyword(sema, token, k)? + keyword(token, k) } } _ => return None, }; - Some(highlight) + Some(h) } pub(super) fn name_like( sema: &Semantics<'_, RootDatabase>, krate: hir::Crate, - bindings_shadow_count: &mut FxHashMap, + bindings_shadow_count: Option<&mut FxHashMap>, + is_unsafe_node: &impl Fn(AstPtr>) -> bool, syntactic_name_ref_highlighting: bool, name_like: ast::NameLike, edition: Edition, @@ -75,19 +77,26 @@ pub(super) fn name_like( krate, bindings_shadow_count, &mut binding_hash, + is_unsafe_node, syntactic_name_ref_highlighting, name_ref, edition, ), - ast::NameLike::Name(name) => { - highlight_name(sema, bindings_shadow_count, &mut binding_hash, krate, name, edition) - } + ast::NameLike::Name(name) => highlight_name( + sema, + bindings_shadow_count, + &mut binding_hash, + is_unsafe_node, + krate, + name, + edition, + ), ast::NameLike::Lifetime(lifetime) => match IdentClass::classify_lifetime(sema, &lifetime) { Some(IdentClass::NameClass(NameClass::Definition(def))) => { - highlight_def(sema, krate, def, edition) | HlMod::Definition + highlight_def(sema, krate, def, edition, false) | HlMod::Definition } Some(IdentClass::NameRefClass(NameRefClass::Definition(def, _))) => { - highlight_def(sema, krate, def, edition) + highlight_def(sema, krate, def, edition, true) } // FIXME: Fallback for '_, as we do not resolve these yet _ => SymbolKind::LifetimeParam.into(), @@ -100,44 +109,49 @@ fn punctuation( sema: &Semantics<'_, RootDatabase>, token: SyntaxToken, kind: SyntaxKind, + is_unsafe_node: &impl Fn(AstPtr>) -> bool, ) -> Highlight { - let parent = token.parent(); - let parent_kind = parent.as_ref().map_or(EOF, SyntaxNode::kind); - match (kind, parent_kind) { + let operator_parent = token.parent(); + let parent_kind = operator_parent.as_ref().map_or(EOF, SyntaxNode::kind); + let h = match (kind, parent_kind) { (T![?], TRY_EXPR) => HlTag::Operator(HlOperator::Other) | HlMod::ControlFlow, (T![&], BIN_EXPR) => HlOperator::Bitwise.into(), - (T![&], REF_EXPR) => { - let h = HlTag::Operator(HlOperator::Other).into(); - let is_unsafe = parent - .and_then(ast::RefExpr::cast) - .map(|ref_expr| sema.is_unsafe_ref_expr(&ref_expr)); - if let Some(true) = is_unsafe { - h | HlMod::Unsafe + (T![&], REF_EXPR | REF_PAT) => HlTag::Operator(HlOperator::Other).into(), + (T![..] | T![..=], _) => match token.parent().and_then(ast::Pat::cast) { + Some(pat) if is_unsafe_node(AstPtr::new(&pat).wrap_right()) => { + Highlight::from(HlOperator::Other) | HlMod::Unsafe + } + _ => HlOperator::Other.into(), + }, + (T![::] | T![->] | T![=>] | T![=] | T![@] | T![.], _) => HlOperator::Other.into(), + (T![!], MACRO_CALL) => { + if operator_parent + .and_then(ast::MacroCall::cast) + .is_some_and(|macro_call| sema.is_unsafe_macro_call(¯o_call)) + { + Highlight::from(HlPunct::MacroBang) | HlMod::Unsafe } else { - h + HlPunct::MacroBang.into() } } - (T![::] | T![->] | T![=>] | T![..] | T![..=] | T![=] | T![@] | T![.], _) => { - HlOperator::Other.into() - } - (T![!], MACRO_CALL | MACRO_RULES) => HlPunct::MacroBang.into(), + (T![!], MACRO_RULES) => HlPunct::MacroBang.into(), (T![!], NEVER_TYPE) => HlTag::BuiltinType.into(), (T![!], PREFIX_EXPR) => HlOperator::Logical.into(), (T![*], PTR_TYPE) => HlTag::Keyword.into(), (T![*], PREFIX_EXPR) => { - let is_raw_ptr = (|| { - let prefix_expr = parent.and_then(ast::PrefixExpr::cast)?; - let expr = prefix_expr.expr()?; - sema.type_of_expr(&expr)?.original.is_raw_ptr().then_some(()) - })(); - if let Some(()) = is_raw_ptr { - HlTag::Operator(HlOperator::Other) | HlMod::Unsafe + let h = HlTag::Operator(HlOperator::Other).into(); + let ptr = operator_parent + .as_ref() + .and_then(|it| AstPtr::try_from_raw(SyntaxNodePtr::new(it))); + if ptr.is_some_and(is_unsafe_node) { + h | HlMod::Unsafe } else { - HlOperator::Other.into() + h } } (T![-], PREFIX_EXPR) => { - let prefix_expr = parent.and_then(ast::PrefixExpr::cast).and_then(|e| e.expr()); + let prefix_expr = + operator_parent.and_then(ast::PrefixExpr::cast).and_then(|e| e.expr()); match prefix_expr { Some(ast::Expr::Literal(_)) => HlTag::NumericLiteral, _ => HlTag::Operator(HlOperator::Other), @@ -157,36 +171,90 @@ fn punctuation( HlOperator::Comparison.into() } (_, ATTR) => HlTag::AttributeBracket.into(), + (T![>], _) + if operator_parent + .as_ref() + .and_then(SyntaxNode::parent) + .is_some_and(|it| it.kind() == MACRO_RULES) => + { + HlOperator::Other.into() + } (kind, _) => match kind { - T!['['] | T![']'] => HlPunct::Bracket, - T!['{'] | T!['}'] => HlPunct::Brace, - T!['('] | T![')'] => HlPunct::Parenthesis, - T![>] - if parent + T!['['] | T![']'] => { + let is_unsafe_macro = operator_parent .as_ref() - .and_then(SyntaxNode::parent) - .is_some_and(|it| it.kind() == MACRO_RULES) => - { - return HlOperator::Other.into() + .and_then(|it| ast::TokenTree::cast(it.clone())?.syntax().parent()) + .and_then(ast::MacroCall::cast) + .is_some_and(|macro_call| sema.is_unsafe_macro_call(¯o_call)); + let is_unsafe = is_unsafe_macro + || operator_parent + .as_ref() + .and_then(|it| AstPtr::try_from_raw(SyntaxNodePtr::new(it))) + .is_some_and(is_unsafe_node); + if is_unsafe { + return Highlight::from(HlPunct::Bracket) | HlMod::Unsafe; + } else { + HlPunct::Bracket + } + } + T!['{'] | T!['}'] => { + let is_unsafe_macro = operator_parent + .as_ref() + .and_then(|it| ast::TokenTree::cast(it.clone())?.syntax().parent()) + .and_then(ast::MacroCall::cast) + .is_some_and(|macro_call| sema.is_unsafe_macro_call(¯o_call)); + let is_unsafe = is_unsafe_macro + || operator_parent + .as_ref() + .and_then(|it| AstPtr::try_from_raw(SyntaxNodePtr::new(it))) + .is_some_and(is_unsafe_node); + if is_unsafe { + return Highlight::from(HlPunct::Brace) | HlMod::Unsafe; + } else { + HlPunct::Brace + } + } + T!['('] | T![')'] => { + let is_unsafe_macro = operator_parent + .as_ref() + .and_then(|it| ast::TokenTree::cast(it.clone())?.syntax().parent()) + .and_then(ast::MacroCall::cast) + .is_some_and(|macro_call| sema.is_unsafe_macro_call(¯o_call)); + let is_unsafe = is_unsafe_macro + || operator_parent + .and_then(|it| { + if ast::ArgList::can_cast(it.kind()) { + it.parent() + } else { + Some(it) + } + }) + .and_then(|it| AstPtr::try_from_raw(SyntaxNodePtr::new(&it))) + .is_some_and(is_unsafe_node); + + if is_unsafe { + return Highlight::from(HlPunct::Parenthesis) | HlMod::Unsafe; + } else { + HlPunct::Parenthesis + } } T![<] | T![>] => HlPunct::Angle, - T![,] => HlPunct::Comma, + // Early return as otherwise we'd highlight these in + // asm expressions + T![,] => return HlPunct::Comma.into(), T![:] => HlPunct::Colon, T![;] => HlPunct::Semi, T![.] => HlPunct::Dot, _ => HlPunct::Other, } .into(), - } + }; + h } -fn keyword( - sema: &Semantics<'_, RootDatabase>, - token: SyntaxToken, - kind: SyntaxKind, -) -> Option { +fn keyword(token: SyntaxToken, kind: SyntaxKind) -> Highlight { let h = Highlight::new(HlTag::Keyword); - let h = match kind { + match kind { T![await] => h | HlMod::Async | HlMod::ControlFlow, T![async] => h | HlMod::Async, T![break] @@ -202,53 +270,33 @@ fn keyword( T![do] | T![yeet] if parent_matches::(&token) => h | HlMod::ControlFlow, T![for] if parent_matches::(&token) => h | HlMod::ControlFlow, T![unsafe] => h | HlMod::Unsafe, - T![const] - if token.parent().is_some_and(|it| { - matches!( - it.kind(), - SyntaxKind::CONST - | SyntaxKind::FN - | SyntaxKind::IMPL - | SyntaxKind::BLOCK_EXPR - | SyntaxKind::CLOSURE_EXPR - | SyntaxKind::FN_PTR_TYPE - | SyntaxKind::TYPE_BOUND - | SyntaxKind::CONST_BLOCK_PAT - ) - }) => - { - h | HlMod::Const - } + T![const] => h | HlMod::Const, T![true] | T![false] => HlTag::BoolLiteral.into(), // crate is handled just as a token if it's in an `extern crate` T![crate] if parent_matches::(&token) => h, - T![ref] => match token.parent().and_then(ast::IdentPat::cast) { - Some(ident) if sema.is_unsafe_ident_pat(&ident) => h | HlMod::Unsafe, - _ => h, - }, _ => h, - }; - Some(h) + } } fn highlight_name_ref( sema: &Semantics<'_, RootDatabase>, krate: hir::Crate, - bindings_shadow_count: &mut FxHashMap, + bindings_shadow_count: Option<&mut FxHashMap>, binding_hash: &mut Option, + is_unsafe_node: &impl Fn(AstPtr>) -> bool, syntactic_name_ref_highlighting: bool, name_ref: ast::NameRef, edition: Edition, ) -> Highlight { let db = sema.db; - if let Some(res) = highlight_method_call_by_name_ref(sema, krate, &name_ref, edition) { + if let Some(res) = highlight_method_call_by_name_ref(sema, krate, &name_ref, is_unsafe_node) { return res; } let name_class = match NameRefClass::classify(sema, &name_ref) { Some(name_kind) => name_kind, None if syntactic_name_ref_highlighting => { - return highlight_name_ref_by_syntax(name_ref, sema, krate, edition) + return highlight_name_ref_by_syntax(name_ref, sema, krate, is_unsafe_node) } // FIXME: This is required for helper attributes used by proc-macros, as those do not map down // to anything when used. @@ -267,17 +315,20 @@ fn highlight_name_ref( let mut h = match name_class { NameRefClass::Definition(def, _) => { if let Definition::Local(local) = &def { - let name = local.name(db); - let shadow_count = bindings_shadow_count.entry(name.clone()).or_default(); - *binding_hash = Some(calc_binding_hash(&name, *shadow_count)) + if let Some(bindings_shadow_count) = bindings_shadow_count { + let name = local.name(sema.db); + let shadow_count = bindings_shadow_count.entry(name.clone()).or_default(); + *binding_hash = Some(calc_binding_hash(&name, *shadow_count)) + } }; - let mut h = highlight_def(sema, krate, def, edition); + let mut h = highlight_def(sema, krate, def, edition, true); match def { Definition::Local(local) if is_consumed_lvalue(name_ref.syntax(), &local, db) => { h |= HlMod::Consuming; } + // highlight unsafe traits as unsafe only in their implementations Definition::Trait(trait_) if trait_.is_unsafe(db) => { if ast::Impl::for_trait_name_ref(&name_ref) .is_some_and(|impl_| impl_.unsafe_token().is_some()) @@ -285,23 +336,66 @@ fn highlight_name_ref( h |= HlMod::Unsafe; } } - Definition::Field(field) => { - if let Some(parent) = name_ref.syntax().parent() { - if matches!(parent.kind(), FIELD_EXPR | RECORD_PAT_FIELD) { - if let hir::VariantDef::Union(_) = field.parent_def(db) { - h |= HlMod::Unsafe; - } - } + Definition::Function(_) => { + let is_unsafe = name_ref + .syntax() + .parent() + .and_then(|it| ast::PathSegment::cast(it)?.parent_path().syntax().parent()) + .and_then(ast::PathExpr::cast) + .and_then(|it| it.syntax().parent()) + .and_then(ast::CallExpr::cast) + .is_some_and(|it| { + is_unsafe_node(AstPtr::new(&ast::Expr::CallExpr(it)).wrap_left()) + }); + if is_unsafe { + h |= HlMod::Unsafe; } } Definition::Macro(_) => { - if let Some(macro_call) = - ide_db::syntax_helpers::node_ext::full_path_of_name_ref(&name_ref) - .and_then(|it| it.syntax().parent().and_then(ast::MacroCall::cast)) - { - if sema.is_unsafe_macro_call(¯o_call) { - h |= HlMod::Unsafe; - } + let is_unsafe = name_ref + .syntax() + .parent() + .and_then(|it| ast::PathSegment::cast(it)?.parent_path().syntax().parent()) + .and_then(ast::MacroCall::cast) + .is_some_and(|macro_call| sema.is_unsafe_macro_call(¯o_call)); + if is_unsafe { + h |= HlMod::Unsafe; + } + } + Definition::Field(_) => { + let is_unsafe = name_ref + .syntax() + .parent() + .and_then(|it| { + match_ast! { match it { + ast::FieldExpr(expr) => Some(is_unsafe_node(AstPtr::new(&Either::Left(expr.into())))), + ast::RecordPatField(pat) => { + walk_pat(&pat.pat()?, &mut |pat| { + if is_unsafe_node(AstPtr::new(&Either::Right(pat))) { + ControlFlow::Break(true) + } + else {ControlFlow::Continue(())} + }).break_value() + }, + _ => None, + }} + }) + .unwrap_or(false); + if is_unsafe { + h |= HlMod::Unsafe; + } + } + Definition::Static(_) => { + let is_unsafe = name_ref + .syntax() + .parent() + .and_then(|it| ast::PathSegment::cast(it)?.parent_path().syntax().parent()) + .and_then(ast::PathExpr::cast) + .is_some_and(|it| { + is_unsafe_node(AstPtr::new(&ast::Expr::PathExpr(it)).wrap_left()) + }); + if is_unsafe { + h |= HlMod::Unsafe; } } _ => (), @@ -310,7 +404,7 @@ fn highlight_name_ref( h } NameRefClass::FieldShorthand { field_ref, .. } => { - highlight_def(sema, krate, field_ref.into(), edition) + highlight_def(sema, krate, field_ref.into(), edition, true) } NameRefClass::ExternCrateShorthand { decl, krate: resolved_krate } => { let mut h = HlTag::Symbol(SymbolKind::Module).into(); @@ -342,22 +436,25 @@ fn highlight_name_ref( fn highlight_name( sema: &Semantics<'_, RootDatabase>, - bindings_shadow_count: &mut FxHashMap, + bindings_shadow_count: Option<&mut FxHashMap>, binding_hash: &mut Option, + is_unsafe_node: &impl Fn(AstPtr>) -> bool, krate: hir::Crate, name: ast::Name, edition: Edition, ) -> Highlight { let name_kind = NameClass::classify(sema, &name); if let Some(NameClass::Definition(Definition::Local(local))) = &name_kind { - let name = local.name(sema.db); - let shadow_count = bindings_shadow_count.entry(name.clone()).or_default(); - *shadow_count += 1; - *binding_hash = Some(calc_binding_hash(&name, *shadow_count)) + if let Some(bindings_shadow_count) = bindings_shadow_count { + let name = local.name(sema.db); + let shadow_count = bindings_shadow_count.entry(name.clone()).or_default(); + *shadow_count += 1; + *binding_hash = Some(calc_binding_hash(&name, *shadow_count)) + } }; match name_kind { Some(NameClass::Definition(def)) => { - let mut h = highlight_def(sema, krate, def, edition) | HlMod::Definition; + let mut h = highlight_def(sema, krate, def, edition, false) | HlMod::Definition; if let Definition::Trait(trait_) = &def { if trait_.is_unsafe(sema.db) { h |= HlMod::Unsafe; @@ -365,10 +462,14 @@ fn highlight_name( } h } - Some(NameClass::ConstReference(def)) => highlight_def(sema, krate, def, edition), - Some(NameClass::PatFieldShorthand { field_ref, .. }) => { + Some(NameClass::ConstReference(def)) => highlight_def(sema, krate, def, edition, true), + Some(NameClass::PatFieldShorthand { .. }) => { let mut h = HlTag::Symbol(SymbolKind::Field).into(); - if let hir::VariantDef::Union(_) = field_ref.parent_def(sema.db) { + let is_unsafe = + name.syntax().parent().and_then(ast::IdentPat::cast).is_some_and(|it| { + is_unsafe_node(AstPtr::new(&ast::Pat::IdentPat(it)).wrap_right()) + }); + if is_unsafe { h |= HlMod::Unsafe; } h @@ -386,6 +487,7 @@ pub(super) fn highlight_def( krate: hir::Crate, def: Definition, edition: Edition, + is_ref: bool, ) -> Highlight { let db = sema.db; let mut h = match def { @@ -439,7 +541,7 @@ pub(super) fn highlight_def( // We probably should consider checking the current function, but I found no easy way to do // that (also I'm worried about perf). There's also an instance below. // FIXME: This should be the edition of the call. - if func.is_unsafe_to_call(db, None, edition) { + if !is_ref && func.is_unsafe_to_call(db, None, edition) { h |= HlMod::Unsafe; } if func.is_async(db) { @@ -509,7 +611,9 @@ pub(super) fn highlight_def( if s.is_mut(db) { h |= HlMod::Mutable; - h |= HlMod::Unsafe; + if !is_ref { + h |= HlMod::Unsafe; + } } h @@ -587,23 +691,24 @@ fn highlight_method_call_by_name_ref( sema: &Semantics<'_, RootDatabase>, krate: hir::Crate, name_ref: &ast::NameRef, - edition: Edition, + is_unsafe_node: &impl Fn(AstPtr>) -> bool, ) -> Option { let mc = name_ref.syntax().parent().and_then(ast::MethodCallExpr::cast)?; - highlight_method_call(sema, krate, &mc, edition) + highlight_method_call(sema, krate, &mc, is_unsafe_node) } fn highlight_method_call( sema: &Semantics<'_, RootDatabase>, krate: hir::Crate, method_call: &ast::MethodCallExpr, - edition: Edition, + is_unsafe_node: &impl Fn(AstPtr>) -> bool, ) -> Option { let func = sema.resolve_method_call(method_call)?; let mut h = SymbolKind::Method.into(); - if func.is_unsafe_to_call(sema.db, None, edition) || sema.is_unsafe_method_call(method_call) { + let is_unsafe = is_unsafe_node(AstPtr::new(method_call).upcast::().wrap_left()); + if is_unsafe { h |= HlMod::Unsafe; } if func.is_async(sema.db) { @@ -695,7 +800,7 @@ fn highlight_name_ref_by_syntax( name: ast::NameRef, sema: &Semantics<'_, RootDatabase>, krate: hir::Crate, - edition: Edition, + is_unsafe_node: &impl Fn(AstPtr>) -> bool, ) -> Highlight { let default = HlTag::UnresolvedReference; @@ -707,19 +812,13 @@ fn highlight_name_ref_by_syntax( match parent.kind() { EXTERN_CRATE => HlTag::Symbol(SymbolKind::Module) | HlMod::CrateRoot, METHOD_CALL_EXPR => ast::MethodCallExpr::cast(parent) - .and_then(|it| highlight_method_call(sema, krate, &it, edition)) + .and_then(|it| highlight_method_call(sema, krate, &it, is_unsafe_node)) .unwrap_or_else(|| SymbolKind::Method.into()), FIELD_EXPR => { let h = HlTag::Symbol(SymbolKind::Field); - let is_union = ast::FieldExpr::cast(parent) - .and_then(|field_expr| sema.resolve_field(&field_expr)) - .is_some_and(|field| match field { - Either::Left(field) => { - matches!(field.parent_def(sema.db), hir::VariantDef::Union(_)) - } - Either::Right(_) => false, - }); - if is_union { + let is_unsafe = ast::Expr::cast(parent) + .is_some_and(|it| is_unsafe_node(AstPtr::new(&it).wrap_left())); + if is_unsafe { h | HlMod::Unsafe } else { h.into() diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/html.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/html.rs index 47ad54759a872..07d40bafeba17 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/html.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/html.rs @@ -88,12 +88,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -115,6 +109,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_asm.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_asm.html index 2bc22f960bd5a..c8ffa9e85583e 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_asm.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_asm.html @@ -14,12 +14,6 @@ .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } @@ -49,26 +44,26 @@ unsafe { let foo = 1; let mut o = 0; - core::arch::asm!( + core::arch::asm!( "%input = OpLoad _ {0}", concat!("%result = ", "bar", " _ %input"), "OpStore {1} %result", in(reg) &foo, in(reg) &mut o, - ); + ); let thread_id: usize; - core::arch::asm!(" + core::arch::asm!(" mov {0}, gs:[0x30] mov {0}, [{0}+0x48] - ", out(reg) thread_id, options(pure, readonly, nostack)); + ", out(reg) thread_id, options(pure, readonly, nostack)); static UNMAP_BASE: usize; const MEM_RELEASE: usize; static VirtualFree: usize; const OffPtr: usize; const OffFn: usize; - core::arch::asm!(" + core::arch::asm!(" push {free_type} push {free_size} push {base} @@ -82,26 +77,26 @@ jmp {virtual_free} ", - off_ptr = const OffPtr, - off_fn = const OffFn, + off_ptr = const OffPtr, + off_fn = const OffFn, - free_size = const 0, - free_type = const MEM_RELEASE, + free_size = const 0, + free_type = const MEM_RELEASE, virtual_free = sym VirtualFree, base = sym UNMAP_BASE, options(noreturn), - ); + ); } } // taken from https://github.com/rust-embedded/cortex-m/blob/47921b51f8b960344fcfa1255a50a0d19efcde6d/cortex-m/src/asm.rs#L254-L274 #[inline] -pub unsafe fn bootstrap(msp: *const u32, rv: *const u32) -> ! { +pub unsafe fn bootstrap(msp: *const u32, rv: *const u32) -> ! { // Ensure thumb mode is set. let rv = (rv as u32) | 1; let msp = msp as u32; - core::arch::asm!( + core::arch::asm!( "mrs {tmp}, CONTROL", "bics {tmp}, {spsel}", "msr CONTROL, {tmp}", @@ -115,5 +110,5 @@ msp = in(reg) msp, rv = in(reg) rv, options(noreturn, nomem, nostack), - ); + ); } \ No newline at end of file diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html index 9c7f03fc1587e..faace6eaff86f 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html @@ -14,12 +14,6 @@ .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html index e1d51dc0b71e5..d59f4caa97f64 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html @@ -14,12 +14,6 @@ .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_block_mod_items.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_block_mod_items.html index af29af3f03cac..3beda396da80c 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_block_mod_items.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_block_mod_items.html @@ -14,12 +14,6 @@ .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } @@ -58,7 +53,7 @@ foo!(Bar); fn func(_: y::Bar) { mod inner { - struct Innerest<const C: usize> { field: [(); {C}] } + struct Innerest<const C: usize> { field: [(); {C}] } } } } diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_const.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_const.html index 6d8f6b3c6e328..9c7324eafa3ab 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_const.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_const.html @@ -14,12 +14,6 @@ .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } @@ -50,21 +45,21 @@ $($tt)* }; } -const CONST_ITEM: *const () = &raw const (); -const fn const_fn<const CONST_PARAM: ()>(const {}: const fn()) where (): const ConstTrait { +const CONST_ITEM: *const () = &raw const (); +const fn const_fn<const CONST_PARAM: ()>(const {}: const fn()) where (): const ConstTrait { CONST_ITEM; CONST_PARAM; const { - const || {} + const || {} } id!( CONST_ITEM; CONST_PARAM; const { - const || {} + const || {} }; - &raw const (); - const + &raw const (); + const ); ().assoc_const_method(); } @@ -80,6 +75,6 @@ macro_rules! unsafe_deref { () => { - *(&() as *const ()) + *(&() as *const ()) }; } \ No newline at end of file diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_crate_root.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_crate_root.html index 63e1560b92107..4613c65ee614e 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_crate_root.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_crate_root.html @@ -14,12 +14,6 @@ .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_default_library.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_default_library.html index dfad3a6605ce7..b1b2c659a22fc 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_default_library.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_default_library.html @@ -14,12 +14,6 @@ .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html index 263e4545fb5a6..c8c8c5dba4c40 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html @@ -14,12 +14,6 @@ .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } @@ -129,7 +124,7 @@ /// /// ``` /// // functions - /// fn foo<T, const X: usize>(arg: i32) { + /// fn foo<T, const X: usize>(arg: i32) { /// let x: T = X; /// } /// ``` diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html index fe5f5ab6a9a27..5399f83085ed2 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html @@ -14,12 +14,6 @@ .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html index eb532a5639d4b..00925bd81ed8e 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html @@ -14,12 +14,6 @@ .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } @@ -109,7 +104,7 @@ loop {} } -fn const_param<const FOO: usize>() -> usize { +fn const_param<const FOO: usize>() -> usize { const_param::<{ FOO }>(); FOO } diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html index 1f9422161de4b..3b468ab6dba65 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html @@ -14,12 +14,6 @@ .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_issue_18089.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_issue_18089.html index a846addba3f2e..5ef64465c9830 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_issue_18089.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_issue_18089.html @@ -14,12 +14,6 @@ .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2015.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2015.html index c3377614d7298..0407e6896e977 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2015.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2015.html @@ -14,12 +14,6 @@ .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2018.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2018.html index 9b22500396bd4..f39d033c76f79 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2018.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2018.html @@ -14,12 +14,6 @@ .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2021.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2021.html index 9b22500396bd4..f39d033c76f79 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2021.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2021.html @@ -14,12 +14,6 @@ .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2024.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2024.html index ac8353120e872..721185a1a8476 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2024.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2024.html @@ -14,12 +14,6 @@ .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_macros.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_macros.html index 694e54d2fa8c4..b2c82051eb166 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_macros.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_macros.html @@ -14,12 +14,6 @@ .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_lifetimes.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_lifetimes.html index 8428b81580036..618ea2171b52f 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_lifetimes.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_lifetimes.html @@ -14,12 +14,6 @@ .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html index f224435e96183..c3145941c3e35 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html @@ -14,12 +14,6 @@ .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_inline.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_inline.html index 947d1bf1e3570..9996a871580fb 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_inline.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_inline.html @@ -14,12 +14,6 @@ .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_outline.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_outline.html index 0fe2b6f274d03..dc9e1de4a4200 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_outline.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_outline.html @@ -14,12 +14,6 @@ .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_operators.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_operators.html index c60b6ab27bba5..9c42401ed0775 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_operators.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_operators.html @@ -14,12 +14,6 @@ .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_rainbow.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_rainbow.html index a4449b5d8d8e9..7f6b4c2c880e1 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_rainbow.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_rainbow.html @@ -14,12 +14,6 @@ .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html index 539c74f6b57e4..f7d798208037e 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html @@ -14,12 +14,6 @@ .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } @@ -169,12 +164,12 @@ toho!("{}fmt", 0); let i: u64 = 3; let o: u64; - core::arch::asm!( + core::arch::asm!( "mov {0}, {1}", "add {0}, 5", out(reg) o, in(reg) i, - ); + ); const CONSTANT: () = (): let mut m = (); diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html index 9a46d9f4025d9..44905831e36ac 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html @@ -14,12 +14,6 @@ .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } @@ -52,78 +47,82 @@ } macro_rules! unsafe_deref { () => { - *(&() as *const ()) + *(&() as *const ()) }; } -static mut MUT_GLOBAL: Struct = Struct { field: 0 }; -static GLOBAL: Struct = Struct { field: 0 }; -unsafe fn unsafe_fn() {} union Union { - a: u32, - b: f32, + field: u32, } struct Struct { field: i32 } + +static mut MUT_GLOBAL: Struct = Struct { field: 0 }; +unsafe fn unsafe_fn() {} + impl Struct { unsafe fn unsafe_method(&self) {} } -#[repr(packed)] -struct Packed { - a: u16, -} - unsafe trait UnsafeTrait {} -unsafe impl UnsafeTrait for Packed {} +unsafe impl UnsafeTrait for Union {} impl !UnsafeTrait for () {} fn unsafe_trait_bound<T: UnsafeTrait>(_: T) {} -trait DoTheAutoref { - fn calls_autoref(&self); -} - -impl DoTheAutoref for u16 { - fn calls_autoref(&self) {} +extern { + static EXTERN_STATIC: (); } fn main() { - let x = &5 as *const _ as *const usize; - let u = Union { b: 0 }; + let x: *const usize; + let u: Union; + // id should be safe here, but unsafe_deref should not id! { - unsafe { unsafe_deref!() } + unsafe { unsafe_deref!() } }; unsafe { - unsafe_deref!(); - id! { unsafe_deref!() }; + // unsafe macro calls + unsafe_deref!(); + id! { unsafe_deref!() }; // unsafe fn and method calls - unsafe_fn(); - let b = u.b; - match u { - Union { b: 0 } => (), - Union { a } => (), - } - Struct { field: 0 }.unsafe_method(); + unsafe_fn(); + self::unsafe_fn(); + (unsafe_fn as unsafe fn())(); + Struct { field: 0 }.unsafe_method(); + + u.field; + &u.field; + &raw const u.field; + // this should be safe! + let Union { field: _ }; + // but not these + let Union { field }; + let Union { field: true }; + let Union { field: field }; + let Union { field: ref field }; + let Union { field: (ref field | 0) }; // unsafe deref - *x; + *&raw const*&*x; // unsafe access to a static mut MUT_GLOBAL.field; - GLOBAL.field; - - // unsafe ref of packed fields - let packed = Packed { a: 0 }; - let a = &packed.a; - let ref a = packed.a; - let Packed { ref a } = packed; - let Packed { a: ref _a } = packed; - - // unsafe auto ref of packed field - packed.a.calls_autoref(); + &MUT_GLOBAL.field; + &raw const MUT_GLOBAL.field; + MUT_GLOBAL; + &MUT_GLOBAL; + &raw const MUT_GLOBAL; + EXTERN_STATIC; + &EXTERN_STATIC; + &raw const EXTERN_STATIC; + + core::arch::asm!( + "push {base}", + base = const 0 + ); } } \ No newline at end of file diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs index e48ca86c46b54..504a1c970efb4 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs @@ -589,7 +589,7 @@ fn main() { fn test_unsafe_highlighting() { check_highlighting( r#" -//- minicore: sized +//- minicore: sized, asm macro_rules! id { ($($tt:tt)*) => { $($tt)* @@ -600,76 +600,80 @@ macro_rules! unsafe_deref { *(&() as *const ()) }; } -static mut MUT_GLOBAL: Struct = Struct { field: 0 }; -static GLOBAL: Struct = Struct { field: 0 }; -unsafe fn unsafe_fn() {} union Union { - a: u32, - b: f32, + field: u32, } struct Struct { field: i32 } + +static mut MUT_GLOBAL: Struct = Struct { field: 0 }; +unsafe fn unsafe_fn() {} + impl Struct { unsafe fn unsafe_method(&self) {} } -#[repr(packed)] -struct Packed { - a: u16, -} - unsafe trait UnsafeTrait {} -unsafe impl UnsafeTrait for Packed {} +unsafe impl UnsafeTrait for Union {} impl !UnsafeTrait for () {} fn unsafe_trait_bound(_: T) {} -trait DoTheAutoref { - fn calls_autoref(&self); -} - -impl DoTheAutoref for u16 { - fn calls_autoref(&self) {} +extern { + static EXTERN_STATIC: (); } fn main() { - let x = &5 as *const _ as *const usize; - let u = Union { b: 0 }; + let x: *const usize; + let u: Union; + // id should be safe here, but unsafe_deref should not id! { unsafe { unsafe_deref!() } }; unsafe { + // unsafe macro calls unsafe_deref!(); id! { unsafe_deref!() }; // unsafe fn and method calls unsafe_fn(); - let b = u.b; - match u { - Union { b: 0 } => (), - Union { a } => (), - } + self::unsafe_fn(); + (unsafe_fn as unsafe fn())(); Struct { field: 0 }.unsafe_method(); + u.field; + &u.field; + &raw const u.field; + // this should be safe! + let Union { field: _ }; + // but not these + let Union { field }; + let Union { field: true }; + let Union { field: field }; + let Union { field: ref field }; + let Union { field: (ref field | 0) }; + // unsafe deref - *x; + *&raw const*&*x; // unsafe access to a static mut MUT_GLOBAL.field; - GLOBAL.field; + &MUT_GLOBAL.field; + &raw const MUT_GLOBAL.field; + MUT_GLOBAL; + &MUT_GLOBAL; + &raw const MUT_GLOBAL; + EXTERN_STATIC; + &EXTERN_STATIC; + &raw const EXTERN_STATIC; - // unsafe ref of packed fields - let packed = Packed { a: 0 }; - let a = &packed.a; - let ref a = packed.a; - let Packed { ref a } = packed; - let Packed { a: ref _a } = packed; - - // unsafe auto ref of packed field - packed.a.calls_autoref(); + core::arch::asm!( + "push {base}", + base$0 = const 0 + ); } } "#, diff --git a/src/tools/rust-analyzer/docs/book/src/assists_generated.md b/src/tools/rust-analyzer/docs/book/src/assists_generated.md index c2063df506893..1be0dda76cddb 100644 --- a/src/tools/rust-analyzer/docs/book/src/assists_generated.md +++ b/src/tools/rust-analyzer/docs/book/src/assists_generated.md @@ -443,7 +443,7 @@ fn main() { ### `convert_closure_to_fn` -**Source:** [convert_closure_to_fn.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_closure_to_fn.rs#L27) +**Source:** [convert_closure_to_fn.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_closure_to_fn.rs#L25) This converts a closure to a freestanding function, changing all captures to parameters. @@ -1348,7 +1348,7 @@ fn main() { ### `flip_or_pattern` **Source:** [flip_or_pattern.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/flip_or_pattern.rs#L9) -Flips two trait bounds. +Flips two patterns in an or-pattern. #### Before ```rust @@ -2278,7 +2278,7 @@ fn bar() { ### `inline_local_variable` -**Source:** [inline_local_variable.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/inline_local_variable.rs#L21) +**Source:** [inline_local_variable.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/inline_local_variable.rs#L17) Inlines a local variable. From 8641805dfeb035f66a8c04f57893864deeaaef03 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 5 Mar 2025 14:42:43 +0100 Subject: [PATCH 18/53] Fix syntax highlightingg punct filtering ignoring mods --- .../rust-analyzer/crates/ide/src/syntax_highlighting.rs | 2 +- .../src/syntax_highlighting/test_data/highlight_unsafe.html | 3 +-- .../crates/ide/src/syntax_highlighting/tests.rs | 5 ++--- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs index 62dc92feb1d62..83082496d5b64 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs @@ -593,7 +593,7 @@ fn filter_by_config(highlight: &mut Highlight, config: HighlightConfig) -> bool *tag = HlTag::Punctuation(HlPunct::Other); } } - HlTag::Punctuation(_) if !config.punctuation => return false, + HlTag::Punctuation(_) if !config.punctuation && highlight.mods.is_empty() => return false, tag @ HlTag::Punctuation(_) if !config.specialize_punctuation => { *tag = HlTag::Punctuation(HlPunct::Other); } diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html index 44905831e36ac..828b8f762c58a 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html @@ -101,10 +101,9 @@ let Union { field: _ }; // but not these let Union { field }; - let Union { field: true }; let Union { field: field }; let Union { field: ref field }; - let Union { field: (ref field | 0) }; + let Union { field: (_ | ref field) }; // unsafe deref *&raw const*&*x; diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs index 504a1c970efb4..8f69bb8230000 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs @@ -651,10 +651,9 @@ fn main() { let Union { field: _ }; // but not these let Union { field }; - let Union { field: true }; let Union { field: field }; let Union { field: ref field }; - let Union { field: (ref field | 0) }; + let Union { field: (_ | ref field) }; // unsafe deref *&raw const*&*x; @@ -672,7 +671,7 @@ fn main() { core::arch::asm!( "push {base}", - base$0 = const 0 + base = const 0 ); } } From bee6cdd962bc9517282e044617d6e42a657620a7 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Wed, 5 Mar 2025 23:38:29 +0100 Subject: [PATCH 19/53] fix: Make RustAnalyzer:Run available in manifest file --- .../rust-analyzer/editors/code/src/ctx.ts | 6 ++++++ .../rust-analyzer/editors/code/src/run.ts | 19 +++++++++++++------ .../rust-analyzer/editors/code/src/util.ts | 4 ++++ 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/tools/rust-analyzer/editors/code/src/ctx.ts b/src/tools/rust-analyzer/editors/code/src/ctx.ts index ac73f2ae6bf19..37a2ee236915c 100644 --- a/src/tools/rust-analyzer/editors/code/src/ctx.ts +++ b/src/tools/rust-analyzer/editors/code/src/ctx.ts @@ -5,6 +5,7 @@ import * as ra from "./lsp_ext"; import { Config, prepareVSCodeConfig } from "./config"; import { createClient } from "./client"; import { + isCargoTomlEditor, isDocumentInWorkspace, isRustDocument, isRustEditor, @@ -429,6 +430,11 @@ export class Ctx implements RustAnalyzerExtensionApi { return editor && isRustEditor(editor) ? editor : undefined; } + get activeCargoTomlEditor(): RustEditor | undefined { + const editor = vscode.window.activeTextEditor; + return editor && isCargoTomlEditor(editor) ? editor : undefined; + } + get extensionPath(): string { return this.extCtx.extensionPath; } diff --git a/src/tools/rust-analyzer/editors/code/src/run.ts b/src/tools/rust-analyzer/editors/code/src/run.ts index f71ab7ffbd816..40027cc7c8579 100644 --- a/src/tools/rust-analyzer/editors/code/src/run.ts +++ b/src/tools/rust-analyzer/editors/code/src/run.ts @@ -7,7 +7,7 @@ import type { CtxInit } from "./ctx"; import { makeDebugConfig } from "./debug"; import type { Config } from "./config"; import type { LanguageClient } from "vscode-languageclient/node"; -import { unwrapUndefinable, type RustEditor } from "./util"; +import { log, unwrapUndefinable, type RustEditor } from "./util"; const quickPickButtons = [ { iconPath: new vscode.ThemeIcon("save"), tooltip: "Save as a launch.json configuration." }, @@ -19,7 +19,7 @@ export async function selectRunnable( debuggeeOnly = false, showButtons: boolean = true, ): Promise { - const editor = ctx.activeRustEditor; + const editor = ctx.activeRustEditor ?? ctx.activeCargoTomlEditor; if (!editor) return; // show a placeholder while we get the runnables from the server @@ -175,10 +175,17 @@ async function getRunnables( uri: editor.document.uri.toString(), }; - const runnables = await client.sendRequest(ra.runnables, { - textDocument, - position: client.code2ProtocolConverter.asPosition(editor.selection.active), - }); + const runnables = await client + .sendRequest(ra.runnables, { + textDocument, + position: client.code2ProtocolConverter.asPosition(editor.selection.active), + }) + .catch((err) => { + // If this command is run for a virtual manifest at the workspace root, then this request + // will fail as we do not watch this file. + log.error(`${err}`); + return []; + }); const items: RunnableQuickPick[] = []; if (prevRunnable) { items.push(prevRunnable); diff --git a/src/tools/rust-analyzer/editors/code/src/util.ts b/src/tools/rust-analyzer/editors/code/src/util.ts index 2f7702baebb67..93c7bf8d73e7b 100644 --- a/src/tools/rust-analyzer/editors/code/src/util.ts +++ b/src/tools/rust-analyzer/editors/code/src/util.ts @@ -90,6 +90,10 @@ export function isRustEditor(editor: vscode.TextEditor): editor is RustEditor { return isRustDocument(editor.document); } +export function isCargoTomlEditor(editor: vscode.TextEditor): editor is RustEditor { + return isCargoTomlDocument(editor.document); +} + export function isDocumentInWorkspace(document: RustDocument): boolean { const workspaceFolders = vscode.workspace.workspaceFolders; if (!workspaceFolders) { From d95d2784da05988bf09bcbf83c460e34030b9362 Mon Sep 17 00:00:00 2001 From: Tongjun Gao Date: Thu, 6 Mar 2025 10:14:39 +0800 Subject: [PATCH 20/53] Adjust relevance scoring threshold to consistent with existing implementations --- src/tools/rust-analyzer/crates/ide-completion/src/item.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs index b3dd8a8d06eb8..ea52d69c7952e 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs @@ -350,7 +350,7 @@ impl CompletionRelevance { /// some threshold such that we think it is especially likely /// to be relevant. pub fn is_relevant(&self) -> bool { - self.score() > 0 + self.score() > (!0 / 2) } } From 66a1164eeb6095c80cdb440a6194e8b86e7c8630 Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Thu, 6 Mar 2025 13:36:20 +0100 Subject: [PATCH 21/53] Change `%e` to `?e` to include detailed error message --- .../rust-analyzer/crates/project-model/src/cargo_workspace.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs index 68a9fba09c722..014028a0b63e2 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs @@ -300,10 +300,9 @@ impl CargoWorkspace { if let Ok((_, Some(ref e))) = res { tracing::warn!( %cargo_toml, - %e, + ?e, "`cargo metadata` failed, but retry with `--no-deps` succeeded" ); - tracing::debug!("{e:?}"); } res } From 860637abc36c5ab3cdc1cf6a5b4130a2d8fecd03 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Thu, 27 Feb 2025 11:21:01 +0200 Subject: [PATCH 22/53] Normalize projections in evaluated const display and layout calculation --- .../crates/hir-ty/src/display.rs | 2 ++ .../rust-analyzer/crates/hir-ty/src/layout.rs | 3 ++ .../crates/ide/src/hover/tests.rs | 34 +++++++++++++++++++ 3 files changed, 39 insertions(+) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs index 6ee4780d206fe..b3613b372bfd0 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs @@ -45,6 +45,7 @@ use crate::{ db::{HirDatabase, InternedClosure}, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, generics::generics, + infer::normalize, layout::Layout, lt_from_placeholder_idx, mapping::from_chalk, @@ -657,6 +658,7 @@ fn render_const_scalar( // infrastructure and have it here as a field on `f`. let trait_env = TraitEnvironment::empty(*f.db.crate_graph().crates_in_topological_order().last().unwrap()); + let ty = normalize(f.db, trait_env.clone(), ty.clone()); match ty.kind(Interner) { TyKind::Scalar(s) => match s { Scalar::Bool => write!(f, "{}", b[0] != 0), diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs index a4e49e0aa10ab..6b5c712159a54 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs @@ -435,6 +435,9 @@ pub fn layout_of_ty_query( TyKind::Error => return Err(LayoutError::HasErrorType), TyKind::AssociatedType(id, subst) => { // Try again with `TyKind::Alias` to normalize the associated type. + // Usually we should not try to normalize `TyKind::AssociatedType`, but layout calculation is used + // in monomorphized MIR where this is okay. If outside monomorphization, this will lead to cycle, + // which we will recover from with an error. let ty = TyKind::Alias(chalk_ir::AliasTy::Projection(ProjectionTy { associated_ty_id: *id, substitution: subst.clone(), diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs index 7c720d97cb6d7..964b1d7eb7dcd 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs @@ -10947,3 +10947,37 @@ pub struct ManuallyDrop$0 { "#]], ); } + +#[test] +fn projection_const() { + check( + r#" +pub trait PublicFlags { + type Internal; +} + +pub struct NoteDialects(::Internal); + +impl NoteDialects { + pub const CLAP$0: Self = Self(InternalBitFlags); +} + +pub struct InternalBitFlags; + +impl PublicFlags for NoteDialects { + type Internal = InternalBitFlags; +} + "#, + expect![[r#" + *CLAP* + + ```rust + ra_test_fixture::NoteDialects + ``` + + ```rust + pub const CLAP: Self = NoteDialects(InternalBitFlags) + ``` + "#]], + ); +} From fcb34b17e22268636a7b227ce78237b158737d39 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Thu, 27 Feb 2025 14:19:54 +0200 Subject: [PATCH 23/53] Pass the target crate in `HirFormatter` This is required to format evaluated consts, because we need trait env, and it needs the crate (currently it uses the last crate in topological order, which is wrong, the next commit will fix that). --- .../crates/hir-ty/src/consteval.rs | 17 ++- .../crates/hir-ty/src/consteval/tests.rs | 18 ++- .../crates/hir-ty/src/diagnostics/expr.rs | 15 +-- .../crates/hir-ty/src/display.rs | 100 ++++++++------ .../rust-analyzer/crates/hir-ty/src/lib.rs | 10 +- .../rust-analyzer/crates/hir-ty/src/mir.rs | 4 +- .../crates/hir-ty/src/mir/borrowck.rs | 6 +- .../crates/hir-ty/src/mir/eval.rs | 27 ++-- .../crates/hir-ty/src/mir/eval/shim.rs | 4 +- .../crates/hir-ty/src/mir/eval/tests.rs | 5 +- .../crates/hir-ty/src/mir/lower.rs | 55 +++++--- .../hir-ty/src/mir/lower/pattern_matching.rs | 7 +- .../crates/hir-ty/src/mir/pretty.rs | 63 +++++---- .../rust-analyzer/crates/hir-ty/src/tests.rs | 47 ++++--- .../hir-ty/src/tests/closure_captures.rs | 8 +- src/tools/rust-analyzer/crates/hir/src/lib.rs | 71 +++++++--- .../rust-analyzer/crates/hir/src/semantics.rs | 8 ++ .../rust-analyzer/crates/hir/src/symbols.rs | 14 +- .../crates/hir/src/term_search/expr.rs | 50 ++++--- .../src/handlers/generate_function.rs | 11 +- .../src/handlers/generate_getter_or_setter.rs | 2 +- .../src/handlers/inline_const_as_literal.rs | 2 +- .../ide-assists/src/handlers/term_search.rs | 9 +- .../crates/ide-assists/src/utils.rs | 44 +++++-- .../crates/ide-completion/src/context.rs | 7 +- .../ide-completion/src/context/tests.rs | 2 +- .../crates/ide-completion/src/render.rs | 13 +- .../ide-completion/src/render/const_.rs | 2 +- .../ide-completion/src/render/function.rs | 32 ++--- .../ide-completion/src/render/literal.rs | 4 +- .../ide-completion/src/render/macro_.rs | 2 +- .../ide-completion/src/render/type_alias.rs | 2 +- .../src/render/union_literal.rs | 2 +- .../ide-completion/src/render/variant.rs | 22 ++-- .../rust-analyzer/crates/ide-db/src/defs.rs | 93 +++++++------ .../crates/ide-db/src/path_transform.rs | 4 +- .../src/handlers/expected_function.rs | 2 +- .../src/handlers/invalid_cast.rs | 2 +- .../src/handlers/moved_out_of_ref.rs | 2 +- .../trait_impl_redundant_assoc_item.rs | 4 +- .../src/handlers/type_mismatch.rs | 8 +- .../src/handlers/typed_hole.rs | 4 +- .../src/handlers/unresolved_field.rs | 2 +- .../src/handlers/unresolved_method.rs | 4 +- .../crates/ide-diagnostics/src/lib.rs | 19 ++- .../crates/ide-ssr/src/matching.rs | 20 +-- .../rust-analyzer/crates/ide/src/hover.rs | 54 ++++++-- .../crates/ide/src/hover/render.rs | 124 +++++++++++------- .../crates/ide/src/inlay_hints.rs | 28 ++-- .../crates/ide/src/inlay_hints/adjustment.rs | 10 +- .../crates/ide/src/inlay_hints/bind_pat.rs | 7 +- .../crates/ide/src/inlay_hints/chaining.rs | 6 +- .../ide/src/inlay_hints/closing_brace.rs | 7 +- .../crates/ide/src/inlay_hints/closure_ret.rs | 6 +- .../rust-analyzer/crates/ide/src/interpret.rs | 15 +-- .../rust-analyzer/crates/ide/src/moniker.rs | 14 +- .../crates/ide/src/navigation_target.rs | 61 ++++++--- .../rust-analyzer/crates/ide/src/runnables.rs | 14 +- .../crates/ide/src/signature_help.rs | 55 ++++---- .../crates/ide/src/static_index.rs | 12 +- .../crates/ide/src/view_memory_layout.rs | 20 ++- .../rust-analyzer/src/cli/analysis_stats.rs | 41 +++--- 62 files changed, 824 insertions(+), 499 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs index 7839589994b2f..fb604569f439d 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs @@ -15,9 +15,10 @@ use stdx::never; use triomphe::Arc; use crate::{ - db::HirDatabase, generics::Generics, infer::InferenceContext, lower::ParamLoweringMode, - mir::monomorphize_mir_body_bad, to_placeholder_idx, Const, ConstData, ConstScalar, ConstValue, - GenericArg, Interner, MemoryMap, Substitution, TraitEnvironment, Ty, TyBuilder, + db::HirDatabase, display::DisplayTarget, generics::Generics, infer::InferenceContext, + lower::ParamLoweringMode, mir::monomorphize_mir_body_bad, to_placeholder_idx, Const, ConstData, + ConstScalar, ConstValue, GenericArg, Interner, MemoryMap, Substitution, TraitEnvironment, Ty, + TyBuilder, }; use super::mir::{interpret_mir, lower_to_mir, pad16, MirEvalError, MirLowerError}; @@ -62,11 +63,15 @@ impl ConstEvalError { f: &mut String, db: &dyn HirDatabase, span_formatter: impl Fn(span::FileId, span::TextRange) -> String, - edition: span::Edition, + display_target: DisplayTarget, ) -> std::result::Result<(), std::fmt::Error> { match self { - ConstEvalError::MirLowerError(e) => e.pretty_print(f, db, span_formatter, edition), - ConstEvalError::MirEvalError(e) => e.pretty_print(f, db, span_formatter, edition), + ConstEvalError::MirLowerError(e) => { + e.pretty_print(f, db, span_formatter, display_target) + } + ConstEvalError::MirEvalError(e) => { + e.pretty_print(f, db, span_formatter, display_target) + } } } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs index 249170c4f3eec..26a3b7022976f 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs @@ -10,8 +10,8 @@ use test_fixture::WithFixture; use test_utils::skip_slow_tests; use crate::{ - consteval::try_const_usize, db::HirDatabase, mir::pad16, test_db::TestDB, Const, ConstScalar, - Interner, MemoryMap, + consteval::try_const_usize, db::HirDatabase, display::DisplayTarget, mir::pad16, + test_db::TestDB, Const, ConstScalar, Interner, MemoryMap, }; use super::{ @@ -101,11 +101,17 @@ fn check_answer( fn pretty_print_err(e: ConstEvalError, db: TestDB) -> String { let mut err = String::new(); let span_formatter = |file, range| format!("{file:?} {range:?}"); - let edition = - db.crate_graph()[*db.crate_graph().crates_in_topological_order().last().unwrap()].edition; + let display_target = DisplayTarget::from_crate( + &db, + *db.crate_graph().crates_in_topological_order().last().unwrap(), + ); match e { - ConstEvalError::MirLowerError(e) => e.pretty_print(&mut err, &db, span_formatter, edition), - ConstEvalError::MirEvalError(e) => e.pretty_print(&mut err, &db, span_formatter, edition), + ConstEvalError::MirLowerError(e) => { + e.pretty_print(&mut err, &db, span_formatter, display_target) + } + ConstEvalError::MirEvalError(e) => { + e.pretty_print(&mut err, &db, span_formatter, display_target) + } } .unwrap(); err diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs index 59aaf85164a0c..cc6f4d9e52eb8 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs @@ -16,7 +16,6 @@ use intern::sym; use itertools::Itertools; use rustc_hash::FxHashSet; use rustc_pattern_analysis::constructor::Constructor; -use span::Edition; use syntax::{ ast::{self, UnaryOp}, AstNode, @@ -31,7 +30,7 @@ use crate::{ self, pat_analysis::{self, DeconstructedPat, MatchCheckCtx, WitnessPat}, }, - display::HirDisplay, + display::{DisplayTarget, HirDisplay}, Adjust, InferenceResult, Interner, Ty, TyExt, TyKind, }; @@ -633,24 +632,24 @@ fn missing_match_arms<'p>( arms_is_empty: bool, krate: CrateId, ) -> String { - struct DisplayWitness<'a, 'p>(&'a WitnessPat<'p>, &'a MatchCheckCtx<'p>, Edition); + struct DisplayWitness<'a, 'p>(&'a WitnessPat<'p>, &'a MatchCheckCtx<'p>, DisplayTarget); impl fmt::Display for DisplayWitness<'_, '_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let DisplayWitness(witness, cx, edition) = *self; + let DisplayWitness(witness, cx, display_target) = *self; let pat = cx.hoist_witness_pat(witness); - write!(f, "{}", pat.display(cx.db, edition)) + write!(f, "{}", pat.display(cx.db, display_target)) } } - let edition = cx.db.crate_graph()[krate].edition; let non_empty_enum = match scrut_ty.as_adt() { Some((AdtId::EnumId(e), _)) => !cx.db.enum_data(e).variants.is_empty(), _ => false, }; + let display_target = DisplayTarget::from_crate(cx.db, krate); if arms_is_empty && !non_empty_enum { - format!("type `{}` is non-empty", scrut_ty.display(cx.db, edition)) + format!("type `{}` is non-empty", scrut_ty.display(cx.db, display_target)) } else { - let pat_display = |witness| DisplayWitness(witness, cx, edition); + let pat_display = |witness| DisplayWitness(witness, cx, display_target); const LIMIT: usize = 3; match &*witnesses { [witness] => format!("`{}` not covered", pat_display(witness)), diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs index b3613b372bfd0..41152d90220ec 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs @@ -88,6 +88,7 @@ pub struct HirFormatter<'a> { show_container_bounds: bool, omit_verbose_types: bool, closure_style: ClosureStyle, + display_kind: DisplayKind, display_target: DisplayTarget, bounds_formatting_ctx: BoundsFormattingCtx, } @@ -165,6 +166,7 @@ pub trait HirDisplay { limited_size: Option, omit_verbose_types: bool, display_target: DisplayTarget, + display_kind: DisplayKind, closure_style: ClosureStyle, show_container_bounds: bool, ) -> HirDisplayWrapper<'a, Self> @@ -172,7 +174,7 @@ pub trait HirDisplay { Self: Sized, { assert!( - !matches!(display_target, DisplayTarget::SourceCode { .. }), + !matches!(display_kind, DisplayKind::SourceCode { .. }), "HirDisplayWrapper cannot fail with DisplaySourceCodeError, use HirDisplay::hir_fmt directly instead" ); HirDisplayWrapper { @@ -182,6 +184,7 @@ pub trait HirDisplay { limited_size, omit_verbose_types, display_target, + display_kind, closure_style, show_container_bounds, } @@ -192,7 +195,7 @@ pub trait HirDisplay { fn display<'a>( &'a self, db: &'a dyn HirDatabase, - edition: Edition, + display_target: DisplayTarget, ) -> HirDisplayWrapper<'a, Self> where Self: Sized, @@ -204,7 +207,8 @@ pub trait HirDisplay { limited_size: None, omit_verbose_types: false, closure_style: ClosureStyle::ImplFn, - display_target: DisplayTarget::Diagnostics { edition }, + display_target, + display_kind: DisplayKind::Diagnostics, show_container_bounds: false, } } @@ -215,7 +219,7 @@ pub trait HirDisplay { &'a self, db: &'a dyn HirDatabase, max_size: Option, - edition: Edition, + display_target: DisplayTarget, ) -> HirDisplayWrapper<'a, Self> where Self: Sized, @@ -227,7 +231,8 @@ pub trait HirDisplay { limited_size: None, omit_verbose_types: true, closure_style: ClosureStyle::ImplFn, - display_target: DisplayTarget::Diagnostics { edition }, + display_target, + display_kind: DisplayKind::Diagnostics, show_container_bounds: false, } } @@ -238,7 +243,7 @@ pub trait HirDisplay { &'a self, db: &'a dyn HirDatabase, limited_size: Option, - edition: Edition, + display_target: DisplayTarget, ) -> HirDisplayWrapper<'a, Self> where Self: Sized, @@ -250,7 +255,8 @@ pub trait HirDisplay { limited_size, omit_verbose_types: true, closure_style: ClosureStyle::ImplFn, - display_target: DisplayTarget::Diagnostics { edition }, + display_target, + display_kind: DisplayKind::Diagnostics, show_container_bounds: false, } } @@ -273,7 +279,8 @@ pub trait HirDisplay { entity_limit: None, omit_verbose_types: false, closure_style: ClosureStyle::ImplFn, - display_target: DisplayTarget::SourceCode { module_id, allow_opaque }, + display_target: DisplayTarget::from_crate(db, module_id.krate()), + display_kind: DisplayKind::SourceCode { target_module_id: module_id, allow_opaque }, show_container_bounds: false, bounds_formatting_ctx: Default::default(), }) { @@ -285,7 +292,11 @@ pub trait HirDisplay { } /// Returns a String representation of `self` for test purposes - fn display_test<'a>(&'a self, db: &'a dyn HirDatabase) -> HirDisplayWrapper<'a, Self> + fn display_test<'a>( + &'a self, + db: &'a dyn HirDatabase, + display_target: DisplayTarget, + ) -> HirDisplayWrapper<'a, Self> where Self: Sized, { @@ -296,7 +307,8 @@ pub trait HirDisplay { limited_size: None, omit_verbose_types: false, closure_style: ClosureStyle::ImplFn, - display_target: DisplayTarget::Test, + display_target, + display_kind: DisplayKind::Test, show_container_bounds: false, } } @@ -307,7 +319,7 @@ pub trait HirDisplay { &'a self, db: &'a dyn HirDatabase, show_container_bounds: bool, - edition: Edition, + display_target: DisplayTarget, ) -> HirDisplayWrapper<'a, Self> where Self: Sized, @@ -319,21 +331,20 @@ pub trait HirDisplay { limited_size: None, omit_verbose_types: false, closure_style: ClosureStyle::ImplFn, - display_target: DisplayTarget::Diagnostics { edition }, + display_target, + display_kind: DisplayKind::Diagnostics, show_container_bounds, } } } impl HirFormatter<'_> { + pub fn krate(&self) -> CrateId { + self.display_target.krate + } + pub fn edition(&self) -> Edition { - match self.display_target { - DisplayTarget::Diagnostics { edition } => edition, - DisplayTarget::SourceCode { module_id, .. } => { - self.db.crate_graph()[module_id.krate()].edition - } - DisplayTarget::Test => Edition::CURRENT, - } + self.display_target.edition } pub fn write_joined( @@ -395,20 +406,33 @@ impl HirFormatter<'_> { } } +#[derive(Debug, Clone, Copy)] +pub struct DisplayTarget { + krate: CrateId, + pub edition: Edition, +} + +impl DisplayTarget { + pub fn from_crate(db: &dyn HirDatabase, krate: CrateId) -> Self { + let edition = db.crate_graph()[krate].edition; + Self { krate, edition } + } +} + #[derive(Clone, Copy)] -pub enum DisplayTarget { +pub enum DisplayKind { /// Display types for inlays, doc popups, autocompletion, etc... /// Showing `{unknown}` or not qualifying paths is fine here. /// There's no reason for this to fail. - Diagnostics { edition: Edition }, + Diagnostics, /// Display types for inserting them in source files. /// The generated code should compile, so paths need to be qualified. - SourceCode { module_id: ModuleId, allow_opaque: bool }, + SourceCode { target_module_id: ModuleId, allow_opaque: bool }, /// Only for test purpose to keep real types Test, } -impl DisplayTarget { +impl DisplayKind { fn is_source_code(self) -> bool { matches!(self, Self::SourceCode { .. }) } @@ -451,6 +475,7 @@ pub struct HirDisplayWrapper<'a, T> { limited_size: Option, omit_verbose_types: bool, closure_style: ClosureStyle, + display_kind: DisplayKind, display_target: DisplayTarget, show_container_bounds: bool, } @@ -480,6 +505,7 @@ impl HirDisplayWrapper<'_, T> { max_size: self.max_size, entity_limit: self.limited_size, omit_verbose_types: self.omit_verbose_types, + display_kind: self.display_kind, display_target: self.display_target, closure_style: self.closure_style, show_container_bounds: self.show_container_bounds, @@ -534,7 +560,7 @@ impl HirDisplay for ProjectionTy { // if we are projection on a type parameter, check if the projection target has bounds // itself, if so, we render them directly as `impl Bound` instead of the less useful // `::Assoc` - if !f.display_target.is_source_code() { + if !f.display_kind.is_source_code() { if let TyKind::Placeholder(idx) = self_ty.kind(Interner) { if !f.bounds_formatting_ctx.contains(self) { let db = f.db; @@ -1111,7 +1137,7 @@ impl HirDisplay for Ty { let def = from_chalk(db, *def); let sig = db.callable_item_signature(def).substitute(Interner, parameters); - if f.display_target.is_source_code() { + if f.display_kind.is_source_code() { // `FnDef` is anonymous and there's no surface syntax for it. Show it as a // function pointer type. return sig.hir_fmt(f); @@ -1200,8 +1226,8 @@ impl HirDisplay for Ty { } TyKind::Adt(AdtId(def_id), parameters) => { f.start_location_link((*def_id).into()); - match f.display_target { - DisplayTarget::Diagnostics { .. } | DisplayTarget::Test => { + match f.display_kind { + DisplayKind::Diagnostics { .. } | DisplayKind::Test { .. } => { let name = match *def_id { hir_def::AdtId::StructId(it) => db.struct_data(it).name.clone(), hir_def::AdtId::UnionId(it) => db.union_data(it).name.clone(), @@ -1209,7 +1235,7 @@ impl HirDisplay for Ty { }; write!(f, "{}", name.display(f.db.upcast(), f.edition()))?; } - DisplayTarget::SourceCode { module_id, allow_opaque: _ } => { + DisplayKind::SourceCode { target_module_id: module_id, allow_opaque: _ } => { if let Some(path) = find_path::find_path( db.upcast(), ItemInNs::Types((*def_id).into()), @@ -1248,7 +1274,7 @@ impl HirDisplay for Ty { let type_alias_data = db.type_alias_data(type_alias); // Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types) - if f.display_target.is_test() { + if f.display_kind.is_test() { f.start_location_link(trait_.into()); write!(f, "{}", trait_data.name.display(f.db.upcast(), f.edition()))?; f.end_location_link(); @@ -1277,7 +1303,7 @@ impl HirDisplay for Ty { f.end_location_link(); } TyKind::OpaqueType(opaque_ty_id, parameters) => { - if !f.display_target.allows_opaque() { + if !f.display_kind.allows_opaque() { return Err(HirDisplayError::DisplaySourceCodeError( DisplaySourceCodeError::OpaqueType, )); @@ -1346,8 +1372,8 @@ impl HirDisplay for Ty { } } TyKind::Closure(id, substs) => { - if f.display_target.is_source_code() { - if !f.display_target.allows_opaque() { + if f.display_kind.is_source_code() { + if !f.display_kind.allows_opaque() { return Err(HirDisplayError::DisplaySourceCodeError( DisplaySourceCodeError::OpaqueType, )); @@ -1467,7 +1493,7 @@ impl HirDisplay for Ty { } TyKind::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?, TyKind::Alias(AliasTy::Opaque(opaque_ty)) => { - if !f.display_target.allows_opaque() { + if !f.display_kind.allows_opaque() { return Err(HirDisplayError::DisplaySourceCodeError( DisplaySourceCodeError::OpaqueType, )); @@ -1510,7 +1536,7 @@ impl HirDisplay for Ty { }; } TyKind::Error => { - if f.display_target.is_source_code() { + if f.display_kind.is_source_code() { f.write_char('_')?; } else { write!(f, "{{unknown}}")?; @@ -1518,7 +1544,7 @@ impl HirDisplay for Ty { } TyKind::InferenceVar(..) => write!(f, "_")?, TyKind::Coroutine(_, subst) => { - if f.display_target.is_source_code() { + if f.display_kind.is_source_code() { return Err(HirDisplayError::DisplaySourceCodeError( DisplaySourceCodeError::Coroutine, )); @@ -1575,7 +1601,7 @@ fn generic_args_sans_defaults<'ga>( generic_def: Option, parameters: &'ga [GenericArg], ) -> &'ga [GenericArg] { - if f.display_target.is_source_code() || f.omit_verbose_types() { + if f.display_kind.is_source_code() || f.omit_verbose_types() { match generic_def .map(|generic_def_id| f.db.generic_defaults(generic_def_id)) .filter(|it| !it.is_empty()) @@ -1960,7 +1986,7 @@ impl HirDisplay for LifetimeData { write!(f, "{}", param_data.name.display(f.db.upcast(), f.edition()))?; Ok(()) } - _ if f.display_target.is_source_code() => write!(f, "'_"), + _ if f.display_kind.is_source_code() => write!(f, "'_"), LifetimeData::BoundVar(idx) => idx.hir_fmt(f), LifetimeData::InferenceVar(_) => write!(f, "_"), LifetimeData::Static => write!(f, "'static"), diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs index 707c43777267e..2f9245a332615 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs @@ -76,13 +76,15 @@ use intern::{sym, Symbol}; use la_arena::{Arena, Idx}; use mir::{MirEvalError, VTableMap}; use rustc_hash::{FxBuildHasher, FxHashMap, FxHashSet}; -use span::Edition; use syntax::ast::{make, ConstArg}; use traits::FnTrait; use triomphe::Arc; use crate::{ - consteval::unknown_const, db::HirDatabase, display::HirDisplay, generics::Generics, + consteval::unknown_const, + db::HirDatabase, + display::{DisplayTarget, HirDisplay}, + generics::Generics, infer::unify::InferenceTable, }; @@ -1044,7 +1046,7 @@ where pub fn known_const_to_ast( konst: &Const, db: &dyn HirDatabase, - edition: Edition, + display_target: DisplayTarget, ) -> Option { if let ConstValue::Concrete(c) = &konst.interned().value { match c.interned { @@ -1055,7 +1057,7 @@ pub fn known_const_to_ast( _ => (), } } - Some(make::expr_const_value(konst.display(db, edition).to_string().as_str())) + Some(make::expr_const_value(konst.display(db, display_target).to_string().as_str())) } #[derive(Debug, Copy, Clone)] diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs index 41304bbd8a919..56c431ef8dab6 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs @@ -5,7 +5,7 @@ use std::{collections::hash_map::Entry, fmt::Display, iter}; use crate::{ consteval::usize_const, db::HirDatabase, - display::HirDisplay, + display::{DisplayTarget, HirDisplay}, infer::{normalize, PointerCast}, lang_items::is_box, mapping::ToChalk, @@ -168,7 +168,7 @@ impl ProjectionElem { _ => { never!( "Overloaded deref on type {} is not a projection", - base.display(db, db.crate_graph()[krate].edition) + base.display(db, DisplayTarget::from_crate(db, krate)) ); TyKind::Error.intern(Interner) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs index 9c86d3b59f6d9..fbcca388e781d 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs @@ -13,6 +13,7 @@ use triomphe::Arc; use crate::{ db::{HirDatabase, InternedClosure}, + display::DisplayTarget, mir::Operand, utils::ClosureSubst, ClosureId, Interner, Substitution, Ty, TyExt, TypeFlags, @@ -422,7 +423,10 @@ fn ever_initialized_map( let Some(terminator) = &block.terminator else { never!( "Terminator should be none only in construction.\nThe body:\n{}", - body.pretty_print(db) + body.pretty_print( + db, + DisplayTarget::from_crate(db, body.owner.krate(db.upcast())) + ) ); return; }; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs index d0f9f4519caa7..74a34e2981710 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs @@ -24,7 +24,7 @@ use rustc_apfloat::{ Float, }; use rustc_hash::{FxHashMap, FxHashSet}; -use span::{Edition, FileId}; +use span::FileId; use stdx::never; use syntax::{SyntaxNodePtr, TextRange}; use triomphe::Arc; @@ -32,7 +32,7 @@ use triomphe::Arc; use crate::{ consteval::{intern_const_scalar, try_const_usize, ConstEvalError}, db::{HirDatabase, InternedClosure}, - display::{ClosureStyle, HirDisplay}, + display::{ClosureStyle, DisplayTarget, HirDisplay}, infer::PointerCast, layout::{Layout, LayoutError, RustcEnumVariantIdx}, mapping::from_chalk, @@ -359,7 +359,7 @@ impl MirEvalError { f: &mut String, db: &dyn HirDatabase, span_formatter: impl Fn(FileId, TextRange) -> String, - edition: Edition, + display_target: DisplayTarget, ) -> std::result::Result<(), std::fmt::Error> { writeln!(f, "Mir eval error:")?; let mut err = self; @@ -372,7 +372,7 @@ impl MirEvalError { writeln!( f, "In function {} ({:?})", - function_name.name.display(db.upcast(), edition), + function_name.name.display(db.upcast(), display_target.edition), func )?; } @@ -417,7 +417,7 @@ impl MirEvalError { write!( f, "Layout for type `{}` is not available due {err:?}", - ty.display(db, edition).with_closure_style(ClosureStyle::ClosureWithId) + ty.display(db, display_target).with_closure_style(ClosureStyle::ClosureWithId) )?; } MirEvalError::MirLowerError(func, err) => { @@ -428,12 +428,15 @@ impl MirEvalError { let substs = generics.placeholder_subst(db); db.impl_self_ty(impl_id) .substitute(Interner, &substs) - .display(db, edition) + .display(db, display_target) .to_string() }), - ItemContainerId::TraitId(it) => { - Some(db.trait_data(it).name.display(db.upcast(), edition).to_string()) - } + ItemContainerId::TraitId(it) => Some( + db.trait_data(it) + .name + .display(db.upcast(), display_target.edition) + .to_string(), + ), _ => None, }; writeln!( @@ -441,17 +444,17 @@ impl MirEvalError { "MIR lowering for function `{}{}{}` ({:?}) failed due:", self_.as_deref().unwrap_or_default(), if self_.is_some() { "::" } else { "" }, - function_name.name.display(db.upcast(), edition), + function_name.name.display(db.upcast(), display_target.edition), func )?; - err.pretty_print(f, db, span_formatter, edition)?; + err.pretty_print(f, db, span_formatter, display_target)?; } MirEvalError::ConstEvalError(name, err) => { MirLowerError::ConstEvalError((**name).into(), err.clone()).pretty_print( f, db, span_formatter, - edition, + display_target, )?; } MirEvalError::UndefinedBehavior(_) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs index 7d3376f56be18..f61ecabb7e41d 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs @@ -14,6 +14,7 @@ use intern::{sym, Symbol}; use stdx::never; use crate::{ + display::DisplayTarget, error_lifetime, mir::eval::{ pad16, Address, AdtId, Arc, BuiltinType, Evaluator, FunctionId, HasModule, HirDisplay, @@ -835,8 +836,7 @@ impl Evaluator<'_> { // render full paths. Err(_) => { let krate = locals.body.owner.krate(self.db.upcast()); - let edition = self.db.crate_graph()[krate].edition; - ty.display(self.db, edition).to_string() + ty.display(self.db, DisplayTarget::from_crate(self.db, krate)).to_string() } }; let len = ty_name.len(); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs index 2b5486fc5fa05..084c391d26cbb 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs @@ -3,6 +3,7 @@ use span::{Edition, EditionedFileId}; use syntax::{TextRange, TextSize}; use test_fixture::WithFixture; +use crate::display::DisplayTarget; use crate::{db::HirDatabase, mir::MirLowerError, test_db::TestDB, Interner, Substitution}; use super::{interpret_mir, MirEvalError}; @@ -67,7 +68,9 @@ fn check_pass_and_stdio( let span_formatter = |file, range: TextRange| { format!("{:?} {:?}..{:?}", file, line_index(range.start()), line_index(range.end())) }; - e.pretty_print(&mut err, &db, span_formatter, Edition::CURRENT).unwrap(); + let krate = db.module_for_file(file_id).krate(); + e.pretty_print(&mut err, &db, span_formatter, DisplayTarget::from_crate(&db, krate)) + .unwrap(); panic!("Error in interpreting: {err}"); } Ok((stdout, stderr)) => { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs index 2fe4ce8319e27..520717e799521 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs @@ -2,7 +2,7 @@ use std::{fmt::Write, iter, mem}; -use base_db::ra_salsa::Cycle; +use base_db::{ra_salsa::Cycle, CrateId}; use chalk_ir::{BoundVar, ConstData, DebruijnIndex, TyKind}; use hir_def::{ data::adt::{StructKind, VariantData}, @@ -29,7 +29,7 @@ use triomphe::Arc; use crate::{ consteval::ConstEvalError, db::{HirDatabase, InternedClosure}, - display::{hir_display_with_types_map, HirDisplay}, + display::{hir_display_with_types_map, DisplayTarget, HirDisplay}, error_lifetime, generics::generics, infer::{cast::CastTy, unify::InferenceTable, CaptureKind, CapturedItem, TypeMismatch}, @@ -160,17 +160,17 @@ impl MirLowerError { f: &mut String, db: &dyn HirDatabase, span_formatter: impl Fn(FileId, TextRange) -> String, - edition: Edition, + display_target: DisplayTarget, ) -> std::result::Result<(), std::fmt::Error> { match self { MirLowerError::ConstEvalError(name, e) => { writeln!(f, "In evaluating constant {name}")?; match &**e { ConstEvalError::MirLowerError(e) => { - e.pretty_print(f, db, span_formatter, edition)? + e.pretty_print(f, db, span_formatter, display_target)? } ConstEvalError::MirEvalError(e) => { - e.pretty_print(f, db, span_formatter, edition)? + e.pretty_print(f, db, span_formatter, display_target)? } } } @@ -179,15 +179,15 @@ impl MirLowerError { writeln!( f, "Missing function definition for {}", - body.pretty_print_expr(db.upcast(), *owner, *it, edition) + body.pretty_print_expr(db.upcast(), *owner, *it, display_target.edition) )?; } MirLowerError::HasErrors => writeln!(f, "Type inference result contains errors")?, MirLowerError::TypeMismatch(e) => writeln!( f, "Type mismatch: Expected {}, found {}", - e.expected.display(db, edition), - e.actual.display(db, edition), + e.expected.display(db, display_target), + e.actual.display(db, display_target), )?, MirLowerError::GenericArgNotProvided(id, subst) => { let parent = id.parent; @@ -195,11 +195,14 @@ impl MirLowerError { writeln!( f, "Generic arg not provided for {}", - param.name().unwrap_or(&Name::missing()).display(db.upcast(), edition) + param + .name() + .unwrap_or(&Name::missing()) + .display(db.upcast(), display_target.edition) )?; writeln!(f, "Provided args: [")?; for g in subst.iter(Interner) { - write!(f, " {},", g.display(db, edition))?; + write!(f, " {},", g.display(db, display_target))?; } writeln!(f, "]")?; } @@ -251,11 +254,11 @@ impl MirLowerError { fn unresolved_path( db: &dyn HirDatabase, p: &Path, - edition: Edition, + display_target: DisplayTarget, types_map: &TypesMap, ) -> Self { Self::UnresolvedName( - hir_display_with_types_map(p, types_map).display(db, edition).to_string(), + hir_display_with_types_map(p, types_map).display(db, display_target).to_string(), ) } } @@ -462,7 +465,7 @@ impl<'ctx> MirLowerCtx<'ctx> { MirLowerError::unresolved_path( self.db, p, - self.edition(), + DisplayTarget::from_crate(self.db, self.krate()), &self.body.types, ) })?; @@ -838,7 +841,7 @@ impl<'ctx> MirLowerCtx<'ctx> { self.infer.variant_resolution_for_expr(expr_id).ok_or_else(|| match path { Some(p) => MirLowerError::UnresolvedName( hir_display_with_types_map(&**p, &self.body.types) - .display(self.db, self.edition()) + .display(self.db, self.display_target()) .to_string(), ), None => MirLowerError::RecordLiteralWithoutPath, @@ -1362,9 +1365,16 @@ impl<'ctx> MirLowerCtx<'ctx> { match &self.body.exprs[*loc] { Expr::Literal(l) => self.lower_literal_to_operand(ty, l), Expr::Path(c) => { - let edition = self.edition(); - let unresolved_name = - || MirLowerError::unresolved_path(self.db, c, edition, &self.body.types); + let owner = self.owner; + let db = self.db; + let unresolved_name = || { + MirLowerError::unresolved_path( + self.db, + c, + DisplayTarget::from_crate(db, owner.krate(db.upcast())), + &self.body.types, + ) + }; let pr = self .resolver .resolve_path_in_value_ns(self.db.upcast(), c, HygieneId::ROOT) @@ -1910,8 +1920,15 @@ impl<'ctx> MirLowerCtx<'ctx> { } fn edition(&self) -> Edition { - let krate = self.owner.krate(self.db.upcast()); - self.db.crate_graph()[krate].edition + self.db.crate_graph()[self.krate()].edition + } + + fn krate(&self) -> CrateId { + self.owner.krate(self.db.upcast()) + } + + fn display_target(&self) -> DisplayTarget { + DisplayTarget::from_crate(self.db, self.krate()) } fn drop_until_scope( diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs index 289175feefb18..783f92b2043f6 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs @@ -350,7 +350,12 @@ impl MirLowerCtx<'_> { )?, None => { let unresolved_name = || { - MirLowerError::unresolved_path(self.db, p, self.edition(), &self.body.types) + MirLowerError::unresolved_path( + self.db, + p, + self.display_target(), + &self.body.types, + ) }; let hygiene = self.body.pat_path_hygiene(pattern); let pr = self diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs index 2a26101ac439f..7d7d4106cb955 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs @@ -9,11 +9,10 @@ use either::Either; use hir_def::{expr_store::Body, hir::BindingId}; use hir_expand::{name::Name, Lookup}; use la_arena::ArenaMap; -use span::Edition; use crate::{ db::HirDatabase, - display::{ClosureStyle, HirDisplay}, + display::{ClosureStyle, DisplayTarget, HirDisplay}, mir::{PlaceElem, ProjectionElem, StatementKind, TerminatorKind}, ClosureId, }; @@ -39,17 +38,21 @@ macro_rules! wln { } impl MirBody { - pub fn pretty_print(&self, db: &dyn HirDatabase) -> String { + pub fn pretty_print(&self, db: &dyn HirDatabase, display_target: DisplayTarget) -> String { let hir_body = db.body(self.owner); - let mut ctx = MirPrettyCtx::new(self, &hir_body, db); + let mut ctx = MirPrettyCtx::new(self, &hir_body, db, display_target); ctx.for_body(|this| match ctx.body.owner { hir_def::DefWithBodyId::FunctionId(id) => { let data = db.function_data(id); - w!(this, "fn {}() ", data.name.display(db.upcast(), Edition::LATEST)); + w!(this, "fn {}() ", data.name.display(db.upcast(), this.display_target.edition)); } hir_def::DefWithBodyId::StaticId(id) => { let data = db.static_data(id); - w!(this, "static {}: _ = ", data.name.display(db.upcast(), Edition::LATEST)); + w!( + this, + "static {}: _ = ", + data.name.display(db.upcast(), this.display_target.edition) + ); } hir_def::DefWithBodyId::ConstId(id) => { let data = db.const_data(id); @@ -59,7 +62,7 @@ impl MirBody { data.name .as_ref() .unwrap_or(&Name::missing()) - .display(db.upcast(), Edition::LATEST) + .display(db.upcast(), this.display_target.edition) ); } hir_def::DefWithBodyId::VariantId(id) => { @@ -70,10 +73,10 @@ impl MirBody { "enum {}::{} = ", enum_loc.id.item_tree(db.upcast())[enum_loc.id.value] .name - .display(db.upcast(), Edition::LATEST), + .display(db.upcast(), this.display_target.edition), loc.id.item_tree(db.upcast())[loc.id.value] .name - .display(db.upcast(), Edition::LATEST), + .display(db.upcast(), this.display_target.edition), ) } hir_def::DefWithBodyId::InTypeConstId(id) => { @@ -85,14 +88,14 @@ impl MirBody { // String with lines is rendered poorly in `dbg` macros, which I use very much, so this // function exists to solve that. - pub fn dbg(&self, db: &dyn HirDatabase) -> impl Debug { + pub fn dbg(&self, db: &dyn HirDatabase, display_target: DisplayTarget) -> impl Debug { struct StringDbg(String); impl Debug for StringDbg { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_str(&self.0) } } - StringDbg(self.pretty_print(db)) + StringDbg(self.pretty_print(db, display_target)) } } @@ -103,6 +106,7 @@ struct MirPrettyCtx<'a> { result: String, indent: String, local_to_binding: ArenaMap, + display_target: DisplayTarget, } impl Write for MirPrettyCtx<'_> { @@ -182,7 +186,12 @@ impl<'a> MirPrettyCtx<'a> { wln!(self, "}}"); } - fn new(body: &'a MirBody, hir_body: &'a Body, db: &'a dyn HirDatabase) -> Self { + fn new( + body: &'a MirBody, + hir_body: &'a Body, + db: &'a dyn HirDatabase, + display_target: DisplayTarget, + ) -> Self { let local_to_binding = body.local_to_binding_map(); MirPrettyCtx { body, @@ -191,6 +200,7 @@ impl<'a> MirPrettyCtx<'a> { indent: String::new(), local_to_binding, hir_body, + display_target, } } @@ -208,7 +218,7 @@ impl<'a> MirPrettyCtx<'a> { wln!( self, "let {}: {};", - self.local_name(id).display_test(self.db), + self.local_name(id).display_test(self.db, self.display_target), self.hir_display(&local.ty) ); } @@ -242,14 +252,14 @@ impl<'a> MirPrettyCtx<'a> { wln!( this, "StorageDead({})", - this.local_name(*p).display_test(self.db) + this.local_name(*p).display_test(this.db, this.display_target) ); } StatementKind::StorageLive(p) => { wln!( this, "StorageLive({})", - this.local_name(*p).display_test(self.db) + this.local_name(*p).display_test(this.db, this.display_target) ); } StatementKind::Deinit(p) => { @@ -313,7 +323,7 @@ impl<'a> MirPrettyCtx<'a> { fn f(this: &mut MirPrettyCtx<'_>, local: LocalId, projections: &[PlaceElem]) { let Some((last, head)) = projections.split_last() else { // no projection - w!(this, "{}", this.local_name(local).display_test(this.db)); + w!(this, "{}", this.local_name(local).display_test(this.db, this.display_target)); return; }; match last { @@ -333,13 +343,17 @@ impl<'a> MirPrettyCtx<'a> { w!( this, " as {}).{}", - variant_name.display(this.db.upcast(), Edition::LATEST), - name.display(this.db.upcast(), Edition::LATEST) + variant_name.display(this.db.upcast(), this.display_target.edition), + name.display(this.db.upcast(), this.display_target.edition) ); } hir_def::VariantId::StructId(_) | hir_def::VariantId::UnionId(_) => { f(this, local, head); - w!(this, ".{}", name.display(this.db.upcast(), Edition::LATEST)); + w!( + this, + ".{}", + name.display(this.db.upcast(), this.display_target.edition) + ); } } } @@ -353,7 +367,11 @@ impl<'a> MirPrettyCtx<'a> { } ProjectionElem::Index(l) => { f(this, local, head); - w!(this, "[{}]", this.local_name(*l).display_test(this.db)); + w!( + this, + "[{}]", + this.local_name(*l).display_test(this.db, this.display_target) + ); } it => { f(this, local, head); @@ -403,7 +421,7 @@ impl<'a> MirPrettyCtx<'a> { Rvalue::Repeat(op, len) => { w!(self, "["); self.operand(op); - w!(self, "; {}]", len.display_test(self.db)); + w!(self, "; {}]", len.display_test(self.db, self.display_target)); } Rvalue::Aggregate(AggregateKind::Adt(_, _), it) => { w!(self, "Adt("); @@ -478,6 +496,7 @@ impl<'a> MirPrettyCtx<'a> { } fn hir_display(&self, ty: &'a T) -> impl Display + 'a { - ty.display_test(self.db).with_closure_style(ClosureStyle::ClosureWithSubst) + ty.display_test(self.db, self.display_target) + .with_closure_style(ClosureStyle::ClosureWithSubst) } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs index f5a4d4ff35c36..81e38be2285ab 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs @@ -15,7 +15,7 @@ mod type_alias_impl_traits; use std::env; use std::sync::LazyLock; -use base_db::SourceDatabaseFileInputExt as _; +use base_db::{CrateId, SourceDatabaseFileInputExt as _}; use expect_test::Expect; use hir_def::{ db::DefDatabase, @@ -41,7 +41,7 @@ use triomphe::Arc; use crate::{ db::HirDatabase, - display::HirDisplay, + display::{DisplayTarget, HirDisplay}, infer::{Adjustment, TypeMismatch}, test_db::TestDB, InferenceResult, Ty, @@ -124,7 +124,7 @@ fn check_impl( } assert!(had_annotations || allow_none, "no `//^` annotations found"); - let mut defs: Vec = Vec::new(); + let mut defs: Vec<(DefWithBodyId, CrateId)> = Vec::new(); for file_id in files { let module = db.module_for_file_opt(file_id); let module = match module { @@ -133,16 +133,17 @@ fn check_impl( }; let def_map = module.def_map(&db); visit_module(&db, &def_map, module.local_id, &mut |it| { - defs.push(match it { + let def = match it { ModuleDefId::FunctionId(it) => it.into(), ModuleDefId::EnumVariantId(it) => it.into(), ModuleDefId::ConstId(it) => it.into(), ModuleDefId::StaticId(it) => it.into(), _ => return, - }) + }; + defs.push((def, module.krate())) }); } - defs.sort_by_key(|def| match def { + defs.sort_by_key(|(def, _)| match def { DefWithBodyId::FunctionId(it) => { let loc = it.lookup(&db); loc.source(&db).value.syntax().text_range().start() @@ -162,7 +163,8 @@ fn check_impl( DefWithBodyId::InTypeConstId(it) => it.source(&db).syntax().text_range().start(), }); let mut unexpected_type_mismatches = String::new(); - for def in defs { + for (def, krate) in defs { + let display_target = DisplayTarget::from_crate(&db, krate); let (body, body_source_map) = db.body_with_source_map(def); let inference_result = db.infer(def); @@ -179,7 +181,7 @@ fn check_impl( let actual = if display_source { ty.display_source_code(&db, def.module(&db), true).unwrap() } else { - ty.display_test(&db).to_string() + ty.display_test(&db, display_target).to_string() }; assert_eq!(actual, expected, "type annotation differs at {:#?}", range.range); } @@ -195,7 +197,7 @@ fn check_impl( let actual = if display_source { ty.display_source_code(&db, def.module(&db), true).unwrap() } else { - ty.display_test(&db).to_string() + ty.display_test(&db, display_target).to_string() }; assert_eq!(actual, expected, "type annotation differs at {:#?}", range.range); } @@ -224,8 +226,8 @@ fn check_impl( let range = node.as_ref().original_file_range_rooted(&db); let actual = format!( "expected {}, got {}", - mismatch.expected.display_test(&db), - mismatch.actual.display_test(&db) + mismatch.expected.display_test(&db, display_target), + mismatch.actual.display_test(&db, display_target) ); match mismatches.remove(&range) { Some(annotation) => assert_eq!(actual, annotation), @@ -299,7 +301,9 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { let mut infer_def = |inference_result: Arc, body: Arc, - body_source_map: Arc| { + body_source_map: Arc, + krate: CrateId| { + let display_target = DisplayTarget::from_crate(&db, krate); let mut types: Vec<(InFile, &Ty)> = Vec::new(); let mut mismatches: Vec<(InFile, &TypeMismatch)> = Vec::new(); @@ -361,7 +365,7 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { macro_prefix, range, ellipsize(text, 15), - ty.display_test(&db) + ty.display_test(&db, display_target) ); } if include_mismatches { @@ -377,8 +381,8 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { "{}{:?}: expected {}, got {}\n", macro_prefix, range, - mismatch.expected.display_test(&db), - mismatch.actual.display_test(&db), + mismatch.expected.display_test(&db, display_target), + mismatch.actual.display_test(&db, display_target), ); } } @@ -387,17 +391,18 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { let module = db.module_for_file(file_id); let def_map = module.def_map(&db); - let mut defs: Vec = Vec::new(); + let mut defs: Vec<(DefWithBodyId, CrateId)> = Vec::new(); visit_module(&db, &def_map, module.local_id, &mut |it| { - defs.push(match it { + let def = match it { ModuleDefId::FunctionId(it) => it.into(), ModuleDefId::EnumVariantId(it) => it.into(), ModuleDefId::ConstId(it) => it.into(), ModuleDefId::StaticId(it) => it.into(), _ => return, - }) + }; + defs.push((def, module.krate())) }); - defs.sort_by_key(|def| match def { + defs.sort_by_key(|(def, _)| match def { DefWithBodyId::FunctionId(it) => { let loc = it.lookup(&db); loc.source(&db).value.syntax().text_range().start() @@ -416,10 +421,10 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { } DefWithBodyId::InTypeConstId(it) => it.source(&db).syntax().text_range().start(), }); - for def in defs { + for (def, krate) in defs { let (body, source_map) = db.body_with_source_map(def); let infer = db.infer(def); - infer_def(infer, body, source_map); + infer_def(infer, body, source_map, krate); } buf.truncate(buf.trim_end().len()); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs index 34d299edd1bdc..6f7bfc4ea7a00 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs @@ -8,7 +8,7 @@ use syntax::{AstNode, AstPtr}; use test_fixture::WithFixture; use crate::db::{HirDatabase, InternedClosureId}; -use crate::display::HirDisplay; +use crate::display::{DisplayTarget, HirDisplay}; use crate::mir::MirSpan; use crate::test_db::TestDB; @@ -66,7 +66,11 @@ fn check_closure_captures(#[rust_analyzer::rust_fixture] ra_fixture: &str, expec .join(", "), }; let place = capture.display_place(closure.0, db); - let capture_ty = capture.ty.skip_binders().display_test(db).to_string(); + let capture_ty = capture + .ty + .skip_binders() + .display_test(db, DisplayTarget::from_crate(db, module.krate())) + .to_string(); let spans = capture .spans() .iter() diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 7549d54a544e8..a59f90b17501d 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -39,7 +39,7 @@ use std::{ }; use arrayvec::ArrayVec; -use base_db::{CrateDisplayName, CrateId, CrateOrigin}; +use base_db::{CrateDisplayName, CrateId, CrateOrigin, LangCrateOrigin}; use either::Either; use hir_def::{ data::{adt::VariantData, TraitFlags}, @@ -147,7 +147,7 @@ pub use { hir_ty::{ consteval::ConstEvalError, diagnostics::UnsafetyReason, - display::{ClosureStyle, HirDisplay, HirDisplayError, HirWrite}, + display::{ClosureStyle, DisplayTarget, HirDisplay, HirDisplayError, HirWrite}, dyn_compatibility::{DynCompatibilityViolation, MethodViolationCode}, layout::LayoutError, method_resolution::TyFingerprint, @@ -282,6 +282,21 @@ impl Crate { let data = &db.crate_graph()[self.id]; data.potential_cfg_options.clone().unwrap_or_else(|| data.cfg_options.clone()) } + + pub fn to_display_target(self, db: &dyn HirDatabase) -> DisplayTarget { + DisplayTarget::from_crate(db, self.id) + } + + fn core(db: &dyn HirDatabase) -> Option { + let crate_graph = db.crate_graph(); + let result = crate_graph + .iter() + .find(|&krate| { + matches!(crate_graph[krate].origin, CrateOrigin::Lang(LangCrateOrigin::Core)) + }) + .map(Crate::from); + result + } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -470,6 +485,17 @@ impl ModuleDef { } } +impl HasCrate for ModuleDef { + fn krate(&self, db: &dyn HirDatabase) -> Crate { + match self.module(db) { + Some(module) => module.krate(), + None => Crate::core(db).unwrap_or_else(|| { + (*db.crate_graph().crates_in_topological_order().last().unwrap()).into() + }), + } + } +} + impl HasVisibility for ModuleDef { fn visibility(&self, db: &dyn HirDatabase) -> Visibility { match *self { @@ -1865,7 +1891,7 @@ impl DefWithBody { pub fn debug_mir(self, db: &dyn HirDatabase) -> String { let body = db.mir_body(self.id()); match body { - Ok(body) => body.pretty_print(db), + Ok(body) => body.pretty_print(db, self.module(db).krate().to_display_target(db)), Err(e) => format!("error:\n{e:?}"), } } @@ -2451,8 +2477,6 @@ impl Function { db: &dyn HirDatabase, span_formatter: impl Fn(FileId, TextRange) -> String, ) -> Result { - let krate = HasModule::krate(&self.id, db.upcast()); - let edition = db.crate_graph()[krate].edition; let body = db.monomorphized_mir_body( self.id.into(), Substitution::empty(Interner), @@ -2463,7 +2487,12 @@ impl Function { Ok(_) => "pass".to_owned(), Err(e) => { let mut r = String::new(); - _ = e.pretty_print(&mut r, db, &span_formatter, edition); + _ = e.pretty_print( + &mut r, + db, + &span_formatter, + self.krate(db).to_display_target(db), + ); r } }; @@ -2727,8 +2756,8 @@ pub struct EvaluatedConst { } impl EvaluatedConst { - pub fn render(&self, db: &dyn HirDatabase, edition: Edition) -> String { - format!("{}", self.const_.display(db, edition)) + pub fn render(&self, db: &dyn HirDatabase, display_target: DisplayTarget) -> String { + format!("{}", self.const_.display(db, display_target)) } pub fn render_debug(&self, db: &dyn HirDatabase) -> Result { @@ -4197,9 +4226,13 @@ impl ConstParam { Type::new(db, self.id.parent(), db.const_param_ty(self.id)) } - pub fn default(self, db: &dyn HirDatabase, edition: Edition) -> Option { + pub fn default( + self, + db: &dyn HirDatabase, + display_target: DisplayTarget, + ) -> Option { let arg = generic_arg_from_param(db, self.id.into())?; - known_const_to_ast(arg.constant(Interner)?, db, edition) + known_const_to_ast(arg.constant(Interner)?, db, display_target) } } @@ -4507,18 +4540,18 @@ impl Closure { TyKind::Closure(self.id, self.subst).intern(Interner) } - pub fn display_with_id(&self, db: &dyn HirDatabase, edition: Edition) -> String { + pub fn display_with_id(&self, db: &dyn HirDatabase, display_target: DisplayTarget) -> String { self.clone() .as_ty() - .display(db, edition) + .display(db, display_target) .with_closure_style(ClosureStyle::ClosureWithId) .to_string() } - pub fn display_with_impl(&self, db: &dyn HirDatabase, edition: Edition) -> String { + pub fn display_with_impl(&self, db: &dyn HirDatabase, display_target: DisplayTarget) -> String { self.clone() .as_ty() - .display(db, edition) + .display(db, display_target) .with_closure_style(ClosureStyle::ImplFn) .to_string() } @@ -5323,7 +5356,7 @@ impl Type { pub fn type_and_const_arguments<'a>( &'a self, db: &'a dyn HirDatabase, - edition: Edition, + display_target: DisplayTarget, ) -> impl Iterator + 'a { self.ty .strip_references() @@ -5333,10 +5366,10 @@ impl Type { .filter_map(move |arg| { // arg can be either a `Ty` or `constant` if let Some(ty) = arg.ty(Interner) { - Some(format_smolstr!("{}", ty.display(db, edition))) + Some(format_smolstr!("{}", ty.display(db, display_target))) } else { arg.constant(Interner) - .map(|const_| format_smolstr!("{}", const_.display(db, edition))) + .map(|const_| format_smolstr!("{}", const_.display(db, display_target))) } }) } @@ -5345,7 +5378,7 @@ impl Type { pub fn generic_parameters<'a>( &'a self, db: &'a dyn HirDatabase, - edition: Edition, + display_target: DisplayTarget, ) -> impl Iterator + 'a { // iterate the lifetime self.as_adt() @@ -5355,7 +5388,7 @@ impl Type { }) .into_iter() // add the type and const parameters - .chain(self.type_and_const_arguments(db, edition)) + .chain(self.type_and_const_arguments(db, display_target)) } pub fn iterate_method_candidates_with_traits( diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index 1b8531209c1b4..034e727d31bc6 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -313,6 +313,14 @@ impl<'db> SemanticsImpl<'db> { tree } + /// If not crate is found for the file, returns the last crate in topological order. + pub fn first_crate_or_default(&self, file: FileId) -> Crate { + match self.file_to_module_defs(file).next() { + Some(module) => module.krate(), + None => (*self.db.crate_graph().crates_in_topological_order().last().unwrap()).into(), + } + } + pub fn attach_first_edition(&self, file: FileId) -> Option { Some(EditionedFileId::new( file, diff --git a/src/tools/rust-analyzer/crates/hir/src/symbols.rs b/src/tools/rust-analyzer/crates/hir/src/symbols.rs index 2ebd88edae2d7..81eb6a70ad73e 100644 --- a/src/tools/rust-analyzer/crates/hir/src/symbols.rs +++ b/src/tools/rust-analyzer/crates/hir/src/symbols.rs @@ -13,11 +13,10 @@ use hir_def::{ use hir_expand::{name::Name, HirFileId}; use hir_ty::{ db::HirDatabase, - display::{hir_display_with_types_map, HirDisplay}, + display::{hir_display_with_types_map, DisplayTarget, HirDisplay}, }; use intern::Symbol; use rustc_hash::FxHashMap; -use span::Edition; use syntax::{ast::HasName, AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, ToSmolStr}; use crate::{Module, ModuleDef, Semantics}; @@ -66,7 +65,7 @@ pub struct SymbolCollector<'a> { symbols: FxIndexSet, work: Vec, current_container_name: Option, - edition: Edition, + display_target: DisplayTarget, } /// Given a [`ModuleId`] and a [`HirDatabase`], use the DefMap for the module's crate to collect @@ -78,7 +77,10 @@ impl<'a> SymbolCollector<'a> { symbols: Default::default(), work: Default::default(), current_container_name: None, - edition: Edition::Edition2015, + display_target: DisplayTarget::from_crate( + db, + *db.crate_graph().crates_in_topological_order().last().unwrap(), + ), } } @@ -91,7 +93,7 @@ impl<'a> SymbolCollector<'a> { pub fn collect(&mut self, module: Module) { let _p = tracing::info_span!("SymbolCollector::collect", ?module).entered(); tracing::info!(?module, "SymbolCollector::collect",); - self.edition = module.krate().edition(self.db); + self.display_target = module.krate().to_display_target(self.db); // The initial work is the root module we're collecting, additional work will // be populated as we traverse the module's definitions. @@ -307,7 +309,7 @@ impl<'a> SymbolCollector<'a> { let impl_data = self.db.impl_data(impl_id); let impl_name = Some( hir_display_with_types_map(impl_data.self_ty, &impl_data.types_map) - .display(self.db, self.edition) + .display(self.db, self.display_target) .to_smolstr(), ); self.with_container_name(impl_name, |s| { diff --git a/src/tools/rust-analyzer/crates/hir/src/term_search/expr.rs b/src/tools/rust-analyzer/crates/hir/src/term_search/expr.rs index d2070f0e18b46..0d672dc332f39 100644 --- a/src/tools/rust-analyzer/crates/hir/src/term_search/expr.rs +++ b/src/tools/rust-analyzer/crates/hir/src/term_search/expr.rs @@ -4,7 +4,7 @@ use hir_def::ImportPathConfig; use hir_expand::mod_path::ModPath; use hir_ty::{ db::HirDatabase, - display::{DisplaySourceCodeError, HirDisplay}, + display::{DisplaySourceCodeError, DisplayTarget, HirDisplay}, }; use itertools::Itertools; use span::Edition; @@ -99,14 +99,16 @@ impl Expr { sema_scope: &SemanticsScope<'_>, many_formatter: &mut dyn FnMut(&Type) -> String, cfg: ImportPathConfig, - edition: Edition, + display_target: DisplayTarget, ) -> Result { let db = sema_scope.db; + let edition = display_target.edition; let mod_item_path_str = |s, def| mod_item_path_str(s, def, cfg, edition); match self { Expr::Const(it) => match it.as_assoc_item(db).map(|it| it.container(db)) { Some(container) => { - let container_name = container_name(container, sema_scope, cfg, edition)?; + let container_name = + container_name(container, sema_scope, cfg, edition, display_target)?; let const_name = it .name(db) .map(|c| c.display(db.upcast(), edition).to_string()) @@ -122,14 +124,15 @@ impl Expr { Expr::Function { func, params, .. } => { let args = params .iter() - .map(|f| f.gen_source_code(sema_scope, many_formatter, cfg, edition)) + .map(|f| f.gen_source_code(sema_scope, many_formatter, cfg, display_target)) .collect::, DisplaySourceCodeError>>()? .into_iter() .join(", "); match func.as_assoc_item(db).map(|it| it.container(db)) { Some(container) => { - let container_name = container_name(container, sema_scope, cfg, edition)?; + let container_name = + container_name(container, sema_scope, cfg, edition, display_target)?; let fn_name = func.name(db).display(db.upcast(), edition).to_string(); Ok(format!("{container_name}::{fn_name}({args})")) } @@ -147,10 +150,10 @@ impl Expr { let func_name = func.name(db).display(db.upcast(), edition).to_string(); let self_param = func.self_param(db).unwrap(); let target_str = - target.gen_source_code(sema_scope, many_formatter, cfg, edition)?; + target.gen_source_code(sema_scope, many_formatter, cfg, display_target)?; let args = params .iter() - .map(|f| f.gen_source_code(sema_scope, many_formatter, cfg, edition)) + .map(|f| f.gen_source_code(sema_scope, many_formatter, cfg, display_target)) .collect::, DisplaySourceCodeError>>()? .into_iter() .join(", "); @@ -180,7 +183,9 @@ impl Expr { StructKind::Tuple => { let args = params .iter() - .map(|f| f.gen_source_code(sema_scope, many_formatter, cfg, edition)) + .map(|f| { + f.gen_source_code(sema_scope, many_formatter, cfg, display_target) + }) .collect::, DisplaySourceCodeError>>()? .into_iter() .join(", "); @@ -195,7 +200,12 @@ impl Expr { let tmp = format!( "{}: {}", f.name(db).display(db.upcast(), edition), - a.gen_source_code(sema_scope, many_formatter, cfg, edition)? + a.gen_source_code( + sema_scope, + many_formatter, + cfg, + display_target + )? ); Ok(tmp) }) @@ -215,7 +225,9 @@ impl Expr { StructKind::Tuple => { let args = params .iter() - .map(|a| a.gen_source_code(sema_scope, many_formatter, cfg, edition)) + .map(|a| { + a.gen_source_code(sema_scope, many_formatter, cfg, display_target) + }) .collect::, DisplaySourceCodeError>>()? .into_iter() .join(", "); @@ -230,7 +242,12 @@ impl Expr { let tmp = format!( "{}: {}", f.name(db).display(db.upcast(), edition), - a.gen_source_code(sema_scope, many_formatter, cfg, edition)? + a.gen_source_code( + sema_scope, + many_formatter, + cfg, + display_target + )? ); Ok(tmp) }) @@ -248,7 +265,7 @@ impl Expr { Expr::Tuple { params, .. } => { let args = params .iter() - .map(|a| a.gen_source_code(sema_scope, many_formatter, cfg, edition)) + .map(|a| a.gen_source_code(sema_scope, many_formatter, cfg, display_target)) .collect::, DisplaySourceCodeError>>()? .into_iter() .join(", "); @@ -260,7 +277,8 @@ impl Expr { return Ok(many_formatter(&expr.ty(db))); } - let strukt = expr.gen_source_code(sema_scope, many_formatter, cfg, edition)?; + let strukt = + expr.gen_source_code(sema_scope, many_formatter, cfg, display_target)?; let field = field.name(db).display(db.upcast(), edition).to_string(); Ok(format!("{strukt}.{field}")) } @@ -269,7 +287,8 @@ impl Expr { return Ok(many_formatter(&expr.ty(db))); } - let inner = expr.gen_source_code(sema_scope, many_formatter, cfg, edition)?; + let inner = + expr.gen_source_code(sema_scope, many_formatter, cfg, display_target)?; Ok(format!("&{inner}")) } Expr::Many(ty) => Ok(many_formatter(ty)), @@ -358,6 +377,7 @@ fn container_name( sema_scope: &SemanticsScope<'_>, cfg: ImportPathConfig, edition: Edition, + display_target: DisplayTarget, ) -> Result { let container_name = match container { crate::AssocItemContainer::Trait(trait_) => { @@ -368,7 +388,7 @@ fn container_name( // Should it be guaranteed that `mod_item_path` always exists? match self_ty.as_adt().and_then(|adt| mod_item_path(sema_scope, &adt.into(), cfg)) { Some(path) => path.display(sema_scope.db.upcast(), edition).to_string(), - None => self_ty.display(sema_scope.db, edition).to_string(), + None => self_ty.display(sema_scope.db, display_target).to_string(), } } }; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs index 91e248a1de514..7af2a2e1e6a33 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs @@ -724,9 +724,9 @@ fn fn_generic_params( filter_unnecessary_bounds(&mut generic_params, &mut where_preds, necessary_params); filter_bounds_in_scope(&mut generic_params, &mut where_preds, ctx, target); - let generic_params: Vec<_> = + let generic_params: Vec = generic_params.into_iter().map(|it| it.node.clone_for_update()).collect(); - let where_preds: Vec<_> = + let where_preds: Vec = where_preds.into_iter().map(|it| it.node.clone_for_update()).collect(); // 4. Rewrite paths @@ -1116,9 +1116,12 @@ fn fn_arg_type( if ty.is_reference() || ty.is_mutable_reference() { let famous_defs = &FamousDefs(&ctx.sema, ctx.sema.scope(fn_arg.syntax())?.krate()); - let target_edition = target_module.krate().edition(ctx.db()); convert_reference_type(ty.strip_references(), ctx.db(), famous_defs) - .map(|conversion| conversion.convert_type(ctx.db(), target_edition).to_string()) + .map(|conversion| { + conversion + .convert_type(ctx.db(), target_module.krate().to_display_target(ctx.db())) + .to_string() + }) .or_else(|| ty.display_source_code(ctx.db(), target_module.into(), true).ok()) } else { ty.display_source_code(ctx.db(), target_module.into(), true).ok() diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_getter_or_setter.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_getter_or_setter.rs index ac58af6252520..1b16ba5fc8ff3 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_getter_or_setter.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_getter_or_setter.rs @@ -233,7 +233,7 @@ fn generate_getter_from_info( .map(|conversion| { cov_mark::hit!(convert_reference_type); ( - conversion.convert_type(ctx.db(), krate.edition(ctx.db())), + conversion.convert_type(ctx.db(), krate.to_display_target(ctx.db())), conversion.getter(record_field_info.field_name.to_string()), ) }) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_const_as_literal.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_const_as_literal.rs index 139078eee7c4b..ca5882d0313ac 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_const_as_literal.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_const_as_literal.rs @@ -42,7 +42,7 @@ pub(crate) fn inline_const_as_literal(acc: &mut Assists, ctx: &AssistContext<'_> let value = konst .eval(ctx.sema.db) .ok()? - .render(ctx.sema.db, konst.krate(ctx.sema.db).edition(ctx.sema.db)); + .render(ctx.sema.db, konst.krate(ctx.sema.db).to_display_target(ctx.sema.db)); let id = AssistId("inline_const_as_literal", AssistKind::RefactorInline); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs index 66671c934c4b7..e10897b3bef75 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs @@ -52,8 +52,13 @@ pub(crate) fn term_search(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option< let paths = paths .into_iter() .filter_map(|path| { - path.gen_source_code(&scope, &mut formatter, ctx.config.import_path_config(), edition) - .ok() + path.gen_source_code( + &scope, + &mut formatter, + ctx.config.import_path_config(), + scope.krate().to_display_target(ctx.db()), + ) + .ok() }) .unique(); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs index 39686f065a9c9..a6fa1706710d1 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs @@ -3,7 +3,8 @@ pub(crate) use gen_trait_fn_body::gen_trait_fn_body; use hir::{ db::{ExpandDatabase, HirDatabase}, - HasAttrs as HirHasAttrs, HirDisplay, InFile, ModuleDef, PathResolution, Semantics, + DisplayTarget, HasAttrs as HirHasAttrs, HirDisplay, InFile, ModuleDef, PathResolution, + Semantics, }; use ide_db::{ famous_defs::FamousDefs, @@ -21,7 +22,7 @@ use syntax::{ syntax_factory::SyntaxFactory, HasArgList, HasAttrs, HasGenericParams, HasName, HasTypeBounds, Whitespace, }, - ted, AstNode, AstToken, Direction, Edition, NodeOrToken, SourceFile, + ted, AstNode, AstToken, Direction, NodeOrToken, SourceFile, SyntaxKind::*, SyntaxNode, SyntaxToken, TextRange, TextSize, WalkEvent, T, }; @@ -793,31 +794,50 @@ enum ReferenceConversionType { } impl ReferenceConversion { - pub(crate) fn convert_type(&self, db: &dyn HirDatabase, edition: Edition) -> ast::Type { + pub(crate) fn convert_type( + &self, + db: &dyn HirDatabase, + display_target: DisplayTarget, + ) -> ast::Type { let ty = match self.conversion { - ReferenceConversionType::Copy => self.ty.display(db, edition).to_string(), + ReferenceConversionType::Copy => self.ty.display(db, display_target).to_string(), ReferenceConversionType::AsRefStr => "&str".to_owned(), ReferenceConversionType::AsRefSlice => { - let type_argument_name = - self.ty.type_arguments().next().unwrap().display(db, edition).to_string(); + let type_argument_name = self + .ty + .type_arguments() + .next() + .unwrap() + .display(db, display_target) + .to_string(); format!("&[{type_argument_name}]") } ReferenceConversionType::Dereferenced => { - let type_argument_name = - self.ty.type_arguments().next().unwrap().display(db, edition).to_string(); + let type_argument_name = self + .ty + .type_arguments() + .next() + .unwrap() + .display(db, display_target) + .to_string(); format!("&{type_argument_name}") } ReferenceConversionType::Option => { - let type_argument_name = - self.ty.type_arguments().next().unwrap().display(db, edition).to_string(); + let type_argument_name = self + .ty + .type_arguments() + .next() + .unwrap() + .display(db, display_target) + .to_string(); format!("Option<&{type_argument_name}>") } ReferenceConversionType::Result => { let mut type_arguments = self.ty.type_arguments(); let first_type_argument_name = - type_arguments.next().unwrap().display(db, edition).to_string(); + type_arguments.next().unwrap().display(db, display_target).to_string(); let second_type_argument_name = - type_arguments.next().unwrap().display(db, edition).to_string(); + type_arguments.next().unwrap().display(db, display_target).to_string(); format!("Result<&{first_type_argument_name}, &{second_type_argument_name}>") } }; diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs index 919b30f7f971a..e686a29309461 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs @@ -7,8 +7,8 @@ mod tests; use std::{iter, ops::ControlFlow}; use hir::{ - HasAttrs, Local, ModPath, ModuleDef, ModuleSource, Name, PathResolution, ScopeDef, Semantics, - SemanticsScope, Symbol, Type, TypeInfo, + DisplayTarget, HasAttrs, Local, ModPath, ModuleDef, ModuleSource, Name, PathResolution, + ScopeDef, Semantics, SemanticsScope, Symbol, Type, TypeInfo, }; use ide_db::{ base_db::SourceDatabase, famous_defs::FamousDefs, helpers::is_editable_crate, FilePosition, @@ -440,6 +440,7 @@ pub(crate) struct CompletionContext<'a> { pub(crate) token: SyntaxToken, /// The crate of the current file. pub(crate) krate: hir::Crate, + pub(crate) display_target: DisplayTarget, /// The module of the `scope`. pub(crate) module: hir::Module, /// The function where we're completing, if inside a function. @@ -867,6 +868,7 @@ impl<'a> CompletionContext<'a> { CompleteSemicolon::DoNotComplete }; + let display_target = krate.to_display_target(db); let ctx = CompletionContext { sema, scope, @@ -888,6 +890,7 @@ impl<'a> CompletionContext<'a> { exclude_flyimport, exclude_traits, complete_semicolon, + display_target, }; Some((ctx, analysis)) } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs index fc2bfc01e62a7..a03f632cdfdfa 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs @@ -13,7 +13,7 @@ fn check_expected_type_and_name(#[rust_analyzer::rust_fixture] ra_fixture: &str, let ty = completion_context .expected_type - .map(|t| t.display_test(&db).to_string()) + .map(|t| t.display_test(&db, completion_context.krate.to_display_target(&db)).to_string()) .unwrap_or("?".to_owned()); let name = diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs index 4f6c4cb663930..b32a589a1b265 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs @@ -144,7 +144,7 @@ pub(crate) fn render_field( is_skipping_completion: receiver.is_some(), ..CompletionRelevance::default() }); - item.detail(ty.display(db, ctx.completion.edition).to_string()) + item.detail(ty.display(db, ctx.completion.display_target).to_string()) .set_documentation(field.docs(db)) .set_deprecated(is_deprecated) .lookup_by(name); @@ -212,7 +212,7 @@ pub(crate) fn render_tuple_field( field_with_receiver(receiver.as_deref(), &field.to_string()), ctx.completion.edition, ); - item.detail(ty.display(ctx.db(), ctx.completion.edition).to_string()) + item.detail(ty.display(ctx.db(), ctx.completion.display_target).to_string()) .lookup_by(field.to_string()); item.set_relevance(CompletionRelevance { is_skipping_completion: receiver.is_some(), @@ -303,7 +303,8 @@ pub(crate) fn render_expr( let cfg = ctx.config.import_path_config(ctx.is_nightly); - let label = expr.gen_source_code(&ctx.scope, &mut label_formatter, cfg, ctx.edition).ok()?; + let label = + expr.gen_source_code(&ctx.scope, &mut label_formatter, cfg, ctx.display_target).ok()?; let source_range = match ctx.original_token.parent() { Some(node) => match node.ancestors().find_map(ast::Path::cast) { @@ -318,7 +319,7 @@ pub(crate) fn render_expr( let snippet = format!( "{}$0", - expr.gen_source_code(&ctx.scope, &mut snippet_formatter, cfg, ctx.edition).ok()? + expr.gen_source_code(&ctx.scope, &mut snippet_formatter, cfg, ctx.display_target).ok()? ); let edit = TextEdit::replace(source_range, snippet); item.snippet_edit(ctx.config.snippet_cap?, edit); @@ -398,6 +399,8 @@ fn render_resolution_path( let _p = tracing::info_span!("render_resolution_path").entered(); use hir::ModuleDef::*; + let krate = ctx.completion.display_target; + match resolution { ScopeDef::ModuleDef(Macro(mac)) => { let ctx = ctx.import_to_add(import_to_add); @@ -459,7 +462,7 @@ fn render_resolution_path( let mut set_item_relevance = |ty: Type| { if !ty.is_unknown() { - item.detail(ty.display(db, completion.edition).to_string()); + item.detail(ty.display(db, krate).to_string()); } item.set_relevance(CompletionRelevance { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/const_.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/const_.rs index e357ab24d22df..f11b3023679ac 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render/const_.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/const_.rs @@ -16,7 +16,7 @@ fn render(ctx: RenderContext<'_>, const_: hir::Const) -> Option let name = const_.name(db)?; let (name, escaped_name) = (name.as_str().to_smolstr(), name.display(db, ctx.completion.edition).to_smolstr()); - let detail = const_.display(db, ctx.completion.edition).to_string(); + let detail = const_.display(db, ctx.completion.display_target).to_string(); let mut item = CompletionItem::new(SymbolKind::Const, ctx.source_range(), name, ctx.completion.edition); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs index fd90613964af0..4693bdc047f97 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs @@ -4,7 +4,7 @@ use hir::{db::HirDatabase, AsAssocItem, HirDisplay}; use ide_db::{SnippetCap, SymbolKind}; use itertools::Itertools; use stdx::{format_to, to_lower_snake_case}; -use syntax::{format_smolstr, AstNode, Edition, SmolStr, ToSmolStr}; +use syntax::{format_smolstr, AstNode, SmolStr, ToSmolStr}; use crate::{ context::{ @@ -142,9 +142,9 @@ fn render( } let detail = if ctx.completion.config.full_function_signatures { - detail_full(db, func, ctx.completion.edition) + detail_full(ctx.completion, func) } else { - detail(ctx.completion, func, ctx.completion.edition) + detail(ctx.completion, func) }; item.set_documentation(ctx.docs(func)) .set_deprecated(ctx.is_deprecated(func) || ctx.is_deprecated_assoc_item(func)) @@ -251,7 +251,7 @@ pub(super) fn add_call_parens<'b>( format!( "{}(${{1:{}}}{}{})$0", escaped_name, - self_param.display(ctx.db, ctx.edition), + self_param.display(ctx.db, ctx.display_target), if params.is_empty() { "" } else { ", " }, function_params_snippet ) @@ -307,7 +307,7 @@ fn ref_of_param(ctx: &CompletionContext<'_>, arg: &str, ty: &hir::Type) -> &'sta "" } -fn detail(ctx: &CompletionContext<'_>, func: hir::Function, edition: Edition) -> String { +fn detail(ctx: &CompletionContext<'_>, func: hir::Function) -> String { let mut ret_ty = func.ret_type(ctx.db); let mut detail = String::new(); @@ -324,15 +324,15 @@ fn detail(ctx: &CompletionContext<'_>, func: hir::Function, edition: Edition) -> format_to!(detail, "unsafe "); } - format_to!(detail, "fn({})", params_display(ctx.db, func, edition)); + format_to!(detail, "fn({})", params_display(ctx, func)); if !ret_ty.is_unit() { - format_to!(detail, " -> {}", ret_ty.display(ctx.db, edition)); + format_to!(detail, " -> {}", ret_ty.display(ctx.db, ctx.display_target)); } detail } -fn detail_full(db: &dyn HirDatabase, func: hir::Function, edition: Edition) -> String { - let signature = format!("{}", func.display(db, edition)); +fn detail_full(ctx: &CompletionContext<'_>, func: hir::Function) -> String { + let signature = format!("{}", func.display(ctx.db, ctx.display_target)); let mut detail = String::with_capacity(signature.len()); for segment in signature.split_whitespace() { @@ -346,24 +346,24 @@ fn detail_full(db: &dyn HirDatabase, func: hir::Function, edition: Edition) -> S detail } -fn params_display(db: &dyn HirDatabase, func: hir::Function, edition: Edition) -> String { - if let Some(self_param) = func.self_param(db) { - let assoc_fn_params = func.assoc_fn_params(db); +fn params_display(ctx: &CompletionContext<'_>, func: hir::Function) -> String { + if let Some(self_param) = func.self_param(ctx.db) { + let assoc_fn_params = func.assoc_fn_params(ctx.db); let params = assoc_fn_params .iter() .skip(1) // skip the self param because we are manually handling that - .map(|p| p.ty().display(db, edition)); + .map(|p| p.ty().display(ctx.db, ctx.display_target)); format!( "{}{}", - self_param.display(db, edition), + self_param.display(ctx.db, ctx.display_target), params.format_with("", |display, f| { f(&", ")?; f(&display) }) ) } else { - let assoc_fn_params = func.assoc_fn_params(db); - assoc_fn_params.iter().map(|p| p.ty().display(db, edition)).join(", ") + let assoc_fn_params = func.assoc_fn_params(ctx.db); + assoc_fn_params.iter().map(|p| p.ty().display(ctx.db, ctx.display_target)).join(", ") } } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs index aab54ca5e0146..3429ae1f46d4a 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs @@ -82,10 +82,10 @@ fn render( let mut rendered = match kind { StructKind::Tuple if should_add_parens => { - render_tuple_lit(db, snippet_cap, &fields, &escaped_qualified_name, completion.edition) + render_tuple_lit(completion, snippet_cap, &fields, &escaped_qualified_name) } StructKind::Record if should_add_parens => { - render_record_lit(db, snippet_cap, &fields, &escaped_qualified_name, completion.edition) + render_record_lit(completion, snippet_cap, &fields, &escaped_qualified_name) } _ => RenderedLiteral { literal: escaped_qualified_name.clone(), diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/macro_.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/macro_.rs index e265e92f9794b..8b2476d153f1f 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render/macro_.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/macro_.rs @@ -62,7 +62,7 @@ fn render( completion.edition, ); item.set_deprecated(ctx.is_deprecated(macro_)) - .detail(macro_.display(completion.db, completion.edition).to_string()) + .detail(macro_.display(completion.db, completion.display_target).to_string()) .set_documentation(docs) .set_relevance(ctx.completion_relevance()); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/type_alias.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/type_alias.rs index 1b952f31360c2..d57feee4fa65e 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render/type_alias.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/type_alias.rs @@ -38,7 +38,7 @@ fn render( } else { (name.as_str().to_smolstr(), name.display_no_db(ctx.completion.edition).to_smolstr()) }; - let detail = type_alias.display(db, ctx.completion.edition).to_string(); + let detail = type_alias.display(db, ctx.completion.display_target).to_string(); let mut item = CompletionItem::new( SymbolKind::TypeAlias, diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/union_literal.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/union_literal.rs index 742036265211e..09154e81c0304 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render/union_literal.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/union_literal.rs @@ -88,7 +88,7 @@ pub(crate) fn render_union_literal( f(&format_args!( "{}: {}", field.name(ctx.db()).display(ctx.db(), ctx.completion.edition), - field.ty(ctx.db()).display(ctx.db(), ctx.completion.edition) + field.ty(ctx.db()).display(ctx.db(), ctx.completion.display_target) )) }), if fields_omitted { ", .." } else { "" } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/variant.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/variant.rs index d8516ea107869..83718e57229a5 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render/variant.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/variant.rs @@ -1,10 +1,10 @@ //! Code common to structs, unions, and enum variants. use crate::context::CompletionContext; -use hir::{db::HirDatabase, sym, HasAttrs, HasCrate, HasVisibility, HirDisplay, StructKind}; +use hir::{sym, HasAttrs, HasCrate, HasVisibility, HirDisplay, StructKind}; use ide_db::SnippetCap; use itertools::Itertools; -use syntax::{Edition, SmolStr}; +use syntax::SmolStr; /// A rendered struct, union, or enum variant, split into fields for actual /// auto-completion (`literal`, using `field: ()`) and display in the @@ -17,11 +17,10 @@ pub(crate) struct RenderedLiteral { /// Render a record type (or sub-type) to a `RenderedCompound`. Use `None` for /// the `name` argument for an anonymous type. pub(crate) fn render_record_lit( - db: &dyn HirDatabase, + ctx: &CompletionContext<'_>, snippet_cap: Option, fields: &[hir::Field], path: &str, - edition: Edition, ) -> RenderedLiteral { if snippet_cap.is_none() { return RenderedLiteral { literal: path.to_owned(), detail: path.to_owned() }; @@ -30,19 +29,19 @@ pub(crate) fn render_record_lit( if snippet_cap.is_some() { f(&format_args!( "{}: ${{{}:()}}", - field.name(db).display(db.upcast(), edition), + field.name(ctx.db).display(ctx.db, ctx.edition), idx + 1 )) } else { - f(&format_args!("{}: ()", field.name(db).display(db.upcast(), edition))) + f(&format_args!("{}: ()", field.name(ctx.db).display(ctx.db, ctx.edition))) } }); let types = fields.iter().format_with(", ", |field, f| { f(&format_args!( "{}: {}", - field.name(db).display(db.upcast(), edition), - field.ty(db).display(db, edition) + field.name(ctx.db).display(ctx.db, ctx.edition), + field.ty(ctx.db).display(ctx.db, ctx.display_target) )) }); @@ -55,11 +54,10 @@ pub(crate) fn render_record_lit( /// Render a tuple type (or sub-type) to a `RenderedCompound`. Use `None` for /// the `name` argument for an anonymous type. pub(crate) fn render_tuple_lit( - db: &dyn HirDatabase, + ctx: &CompletionContext<'_>, snippet_cap: Option, fields: &[hir::Field], path: &str, - edition: Edition, ) -> RenderedLiteral { if snippet_cap.is_none() { return RenderedLiteral { literal: path.to_owned(), detail: path.to_owned() }; @@ -72,7 +70,9 @@ pub(crate) fn render_tuple_lit( } }); - let types = fields.iter().format_with(", ", |field, f| f(&field.ty(db).display(db, edition))); + let types = fields + .iter() + .format_with(", ", |field, f| f(&field.ty(ctx.db).display(ctx.db, ctx.display_target))); RenderedLiteral { literal: format!("{path}({completions})"), diff --git a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs index 6f71c3d9bd7e3..502314ed1e0ec 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs @@ -12,11 +12,11 @@ use arrayvec::ArrayVec; use either::Either; use hir::{ Adt, AsAssocItem, AsExternAssocItem, AssocItem, AttributeTemplate, BuiltinAttr, BuiltinType, - Const, Crate, DefWithBody, DeriveHelper, DocLinkDef, ExternAssocItem, ExternCrateDecl, Field, - Function, GenericDef, GenericParam, GenericSubstitution, HasContainer, HasVisibility, - HirDisplay, Impl, InlineAsmOperand, ItemContainer, Label, Local, Macro, Module, ModuleDef, - Name, PathResolution, Semantics, Static, StaticLifetime, Struct, ToolModule, Trait, TraitAlias, - TupleField, TypeAlias, Variant, VariantDef, Visibility, + Const, Crate, DefWithBody, DeriveHelper, DisplayTarget, DocLinkDef, ExternAssocItem, + ExternCrateDecl, Field, Function, GenericDef, GenericParam, GenericSubstitution, HasContainer, + HasVisibility, HirDisplay, Impl, InlineAsmOperand, ItemContainer, Label, Local, Macro, Module, + ModuleDef, Name, PathResolution, Semantics, Static, StaticLifetime, Struct, ToolModule, Trait, + TraitAlias, TupleField, TypeAlias, Variant, VariantDef, Visibility, }; use span::Edition; use stdx::{format_to, impl_from}; @@ -207,7 +207,7 @@ impl Definition { &self, db: &RootDatabase, famous_defs: Option<&FamousDefs<'_, '_>>, - edition: Edition, + display_target: DisplayTarget, ) -> Option { let docs = match self { Definition::Macro(it) => it.docs(db), @@ -228,7 +228,7 @@ impl Definition { let docs = adt.docs(db)?; let docs = format!( "*This is the documentation for* `{}`\n\n{}", - adt.display(db, edition), + adt.display(db, display_target), docs.as_str() ); Some(Documentation::new(docs)) @@ -237,8 +237,9 @@ impl Definition { Definition::BuiltinType(it) => { famous_defs.and_then(|fd| { // std exposes prim_{} modules with docstrings on the root to document the builtins - let primitive_mod = format!("prim_{}", it.name().display(fd.0.db, edition)); - let doc_owner = find_std_module(fd, &primitive_mod, edition)?; + let primitive_mod = + format!("prim_{}", it.name().display(fd.0.db, display_target.edition)); + let doc_owner = find_std_module(fd, &primitive_mod, display_target.edition)?; doc_owner.docs(fd.0.db) }) } @@ -256,16 +257,21 @@ impl Definition { let AttributeTemplate { word, list, name_value_str } = it.template(db)?; let mut docs = "Valid forms are:".to_owned(); if word { - format_to!(docs, "\n - #\\[{}]", name.display(db, edition)); + format_to!(docs, "\n - #\\[{}]", name.display(db, display_target.edition)); } if let Some(list) = list { - format_to!(docs, "\n - #\\[{}({})]", name.display(db, edition), list); + format_to!( + docs, + "\n - #\\[{}({})]", + name.display(db, display_target.edition), + list + ); } if let Some(name_value_str) = name_value_str { format_to!( docs, "\n - #\\[{} = {}]", - name.display(db, edition), + name.display(db, display_target.edition), name_value_str ); } @@ -288,49 +294,60 @@ impl Definition { }) } - pub fn label(&self, db: &RootDatabase, edition: Edition) -> String { + pub fn label(&self, db: &RootDatabase, display_target: DisplayTarget) -> String { match *self { - Definition::Macro(it) => it.display(db, edition).to_string(), - Definition::Field(it) => it.display(db, edition).to_string(), - Definition::TupleField(it) => it.display(db, edition).to_string(), - Definition::Module(it) => it.display(db, edition).to_string(), - Definition::Crate(it) => it.display(db, edition).to_string(), - Definition::Function(it) => it.display(db, edition).to_string(), - Definition::Adt(it) => it.display(db, edition).to_string(), - Definition::Variant(it) => it.display(db, edition).to_string(), - Definition::Const(it) => it.display(db, edition).to_string(), - Definition::Static(it) => it.display(db, edition).to_string(), - Definition::Trait(it) => it.display(db, edition).to_string(), - Definition::TraitAlias(it) => it.display(db, edition).to_string(), - Definition::TypeAlias(it) => it.display(db, edition).to_string(), - Definition::BuiltinType(it) => it.name().display(db, edition).to_string(), - Definition::BuiltinLifetime(it) => it.name().display(db, edition).to_string(), + Definition::Macro(it) => it.display(db, display_target).to_string(), + Definition::Field(it) => it.display(db, display_target).to_string(), + Definition::TupleField(it) => it.display(db, display_target).to_string(), + Definition::Module(it) => it.display(db, display_target).to_string(), + Definition::Crate(it) => it.display(db, display_target).to_string(), + Definition::Function(it) => it.display(db, display_target).to_string(), + Definition::Adt(it) => it.display(db, display_target).to_string(), + Definition::Variant(it) => it.display(db, display_target).to_string(), + Definition::Const(it) => it.display(db, display_target).to_string(), + Definition::Static(it) => it.display(db, display_target).to_string(), + Definition::Trait(it) => it.display(db, display_target).to_string(), + Definition::TraitAlias(it) => it.display(db, display_target).to_string(), + Definition::TypeAlias(it) => it.display(db, display_target).to_string(), + Definition::BuiltinType(it) => { + it.name().display(db, display_target.edition).to_string() + } + Definition::BuiltinLifetime(it) => { + it.name().display(db, display_target.edition).to_string() + } Definition::Local(it) => { let ty = it.ty(db); - let ty_display = ty.display_truncated(db, None, edition); + let ty_display = ty.display_truncated(db, None, display_target); let is_mut = if it.is_mut(db) { "mut " } else { "" }; if it.is_self(db) { format!("{is_mut}self: {ty_display}") } else { let name = it.name(db); let let_kw = if it.is_param(db) { "" } else { "let " }; - format!("{let_kw}{is_mut}{}: {ty_display}", name.display(db, edition)) + format!( + "{let_kw}{is_mut}{}: {ty_display}", + name.display(db, display_target.edition) + ) } } Definition::SelfType(impl_def) => { let self_ty = &impl_def.self_ty(db); match self_ty.as_adt() { - Some(it) => it.display(db, edition).to_string(), - None => self_ty.display(db, edition).to_string(), + Some(it) => it.display(db, display_target).to_string(), + None => self_ty.display(db, display_target).to_string(), } } - Definition::GenericParam(it) => it.display(db, edition).to_string(), - Definition::Label(it) => it.name(db).display(db, edition).to_string(), - Definition::ExternCrateDecl(it) => it.display(db, edition).to_string(), - Definition::BuiltinAttr(it) => format!("#[{}]", it.name(db).display(db, edition)), - Definition::ToolModule(it) => it.name(db).display(db, edition).to_string(), + Definition::GenericParam(it) => it.display(db, display_target).to_string(), + Definition::Label(it) => it.name(db).display(db, display_target.edition).to_string(), + Definition::ExternCrateDecl(it) => it.display(db, display_target).to_string(), + Definition::BuiltinAttr(it) => { + format!("#[{}]", it.name(db).display(db, display_target.edition)) + } + Definition::ToolModule(it) => { + it.name(db).display(db, display_target.edition).to_string() + } Definition::DeriveHelper(it) => { - format!("derive_helper {}", it.name(db).display(db, edition)) + format!("derive_helper {}", it.name(db).display(db, display_target.edition)) } // FIXME Definition::InlineAsmRegOrRegClass(_) => "inline_asm_reg_or_reg_class".to_owned(), diff --git a/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs b/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs index 126b30470b7e1..a348a4ef7d3fb 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs @@ -192,7 +192,9 @@ impl<'a> PathTransform<'a> { } } (Either::Left(k), None) => { - if let Some(default) = k.default(db, target_edition) { + if let Some(default) = + k.default(db, target_module.krate().to_display_target(db)) + { if let Some(default) = default.expr() { const_substs.insert(k, default.syntax().clone_for_update()); defaulted_params.push(Either::Right(k)); diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/expected_function.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/expected_function.rs index e3a1e12e0296c..af25c2b2e3329 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/expected_function.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/expected_function.rs @@ -12,7 +12,7 @@ pub(crate) fn expected_function( Diagnostic::new_with_syntax_node_ptr( ctx, DiagnosticCode::RustcHardError("E0618"), - format!("expected function, found {}", d.found.display(ctx.sema.db, ctx.edition)), + format!("expected function, found {}", d.found.display(ctx.sema.db, ctx.display_target)), d.call.map(|it| it.into()), ) .experimental() diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs index 5730508436d2c..82cd1f2fde6db 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs @@ -8,7 +8,7 @@ macro_rules! format_ty { $fmt, $( $arg - .display($ctx.sema.db, $ctx.edition) + .display($ctx.sema.db, $ctx.display_target) .with_closure_style(ClosureStyle::ClosureWithId) ),* ) diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs index a9ff06fb0ab1e..7d0f10983d731 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs @@ -8,7 +8,7 @@ pub(crate) fn moved_out_of_ref(ctx: &DiagnosticsContext<'_>, d: &hir::MovedOutOf Diagnostic::new_with_syntax_node_ptr( ctx, DiagnosticCode::RustcHardError("E0507"), - format!("cannot move `{}` out of reference", d.ty.display(ctx.sema.db, ctx.edition)), + format!("cannot move `{}` out of reference", d.ty.display(ctx.sema.db, ctx.display_target)), d.span, ) .experimental() // spans are broken, and I'm not sure how precise we can detect copy types diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs index 1363a8ff0ddb5..3db2e013a3978 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs @@ -30,7 +30,7 @@ pub(crate) fn trait_impl_redundant_assoc_item( ( format!("`fn {redundant_assoc_item_name}`"), function.source(db).map(|it| it.syntax().text_range()).unwrap_or(default_range), - format!("\n {};", function.display(db, ctx.edition)), + format!("\n {};", function.display(db, ctx.display_target)), ) } hir::AssocItem::Const(id) => { @@ -38,7 +38,7 @@ pub(crate) fn trait_impl_redundant_assoc_item( ( format!("`const {redundant_assoc_item_name}`"), constant.source(db).map(|it| it.syntax().text_range()).unwrap_or(default_range), - format!("\n {};", constant.display(db, ctx.edition)), + format!("\n {};", constant.display(db, ctx.display_target)), ) } hir::AssocItem::TypeAlias(id) => { diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs index 7cf8282d05292..c726a3bcd3cad 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs @@ -45,10 +45,10 @@ pub(crate) fn type_mismatch(ctx: &DiagnosticsContext<'_>, d: &hir::TypeMismatch) format!( "expected {}, found {}", d.expected - .display(ctx.sema.db, ctx.edition) + .display(ctx.sema.db, ctx.display_target) .with_closure_style(ClosureStyle::ClosureWithId), d.actual - .display(ctx.sema.db, ctx.edition) + .display(ctx.sema.db, ctx.display_target) .with_closure_style(ClosureStyle::ClosureWithId), ), display_range, @@ -306,8 +306,8 @@ fn str_ref_to_owned( expr_ptr: &InFile>, acc: &mut Vec, ) -> Option<()> { - let expected = d.expected.display(ctx.sema.db, ctx.edition); - let actual = d.actual.display(ctx.sema.db, ctx.edition); + let expected = d.expected.display(ctx.sema.db, ctx.display_target); + let actual = d.actual.display(ctx.sema.db, ctx.display_target); // FIXME do this properly if expected.to_string() != "String" || actual.to_string() != "&str" { diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs index b023a95fb3559..c25318eda4855 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs @@ -27,7 +27,7 @@ pub(crate) fn typed_hole(ctx: &DiagnosticsContext<'_>, d: &hir::TypedHole) -> Di format!( "invalid `_` expression, expected type `{}`", d.expected - .display(ctx.sema.db, ctx.edition) + .display(ctx.sema.db, ctx.display_target) .with_closure_style(ClosureStyle::ClosureWithId), ), fixes(ctx, d), @@ -72,7 +72,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::TypedHole) -> Option prefer_absolute: ctx.config.prefer_absolute, allow_unstable: ctx.is_nightly, }, - ctx.edition, + ctx.display_target, ) .ok() }) diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs index dfb03eee732ab..6ab713a5896c9 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs @@ -38,7 +38,7 @@ pub(crate) fn unresolved_field( format!( "no field `{}` on type `{}`{method_suffix}", d.name.display(ctx.sema.db, ctx.edition), - d.receiver.display(ctx.sema.db, ctx.edition) + d.receiver.display(ctx.sema.db, ctx.display_target) ), adjusted_display_range(ctx, d.expr, &|expr| { Some( diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs index e4de107249bd5..35e7521af7061 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs @@ -31,7 +31,7 @@ pub(crate) fn unresolved_method( format!( "no method `{}` on type `{}`{suffix}", d.name.display(ctx.sema.db, ctx.edition), - d.receiver.display(ctx.sema.db, ctx.edition) + d.receiver.display(ctx.sema.db, ctx.display_target) ), adjusted_display_range(ctx, d.expr, &|expr| { Some( @@ -152,7 +152,7 @@ fn assoc_func_fix(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedMethodCall) - receiver_type.as_adt()?.name(db).display_no_db(ctx.edition).to_smolstr(); let generic_parameters: Vec = - receiver_type.generic_parameters(db, ctx.edition).collect(); + receiver_type.generic_parameters(db, ctx.display_target).collect(); // if receiver should be pass as first arg in the assoc func, // we could omit generic parameters cause compiler can deduce it automatically if !need_to_take_receiver_as_first_arg && !generic_parameters.is_empty() { diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs index 0a55b6e9bee8e..e15d349578914 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs @@ -81,7 +81,10 @@ mod tests; use std::{collections::hash_map, iter, sync::LazyLock}; use either::Either; -use hir::{db::ExpandDatabase, diagnostics::AnyDiagnostic, Crate, HirFileId, InFile, Semantics}; +use hir::{ + db::ExpandDatabase, diagnostics::AnyDiagnostic, Crate, DisplayTarget, HirFileId, InFile, + Semantics, +}; use ide_db::{ assists::{Assist, AssistId, AssistKind, AssistResolveStrategy}, base_db::{ReleaseChannel, SourceDatabase}, @@ -277,6 +280,7 @@ struct DiagnosticsContext<'a> { sema: Semantics<'a, RootDatabase>, resolve: &'a AssistResolveStrategy, edition: Edition, + display_target: DisplayTarget, is_nightly: bool, } @@ -374,7 +378,18 @@ pub fn semantic_diagnostics( module.and_then(|m| db.toolchain_channel(m.krate().into())), Some(ReleaseChannel::Nightly) | None ); - let ctx = DiagnosticsContext { config, sema, resolve, edition: file_id.edition(), is_nightly }; + let krate = module.map(|module| module.krate()).unwrap_or_else(|| { + (*db.crate_graph().crates_in_topological_order().last().unwrap()).into() + }); + let display_target = krate.to_display_target(db); + let ctx = DiagnosticsContext { + config, + sema, + resolve, + edition: file_id.edition(), + is_nightly, + display_target, + }; let mut diags = Vec::new(); match module { diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs index 4bead14e31d4d..e219ba4bf6398 100644 --- a/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs +++ b/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs @@ -7,8 +7,7 @@ use crate::{ SsrMatches, }; use hir::{FileRange, ImportPathConfig, Semantics}; -use ide_db::FxHashMap; -use parser::Edition; +use ide_db::{base_db::SourceDatabase, FxHashMap}; use std::{cell::Cell, iter::Peekable}; use syntax::{ ast::{self, AstNode, AstToken, HasGenericArgs}, @@ -627,22 +626,23 @@ impl<'db, 'sema> Matcher<'db, 'sema> { match_error!("Failed to get receiver type for `{}`", expr.syntax().text()) })? .original; - let edition = self - .sema - .scope(expr.syntax()) - .map(|it| it.krate().edition(self.sema.db)) - .unwrap_or(Edition::CURRENT); - // Temporary needed to make the borrow checker happy. + let krate = self.sema.scope(expr.syntax()).map(|it| it.krate()).unwrap_or_else(|| { + hir::Crate::from( + *self.sema.db.crate_graph().crates_in_topological_order().last().unwrap(), + ) + }); let res = code_type .autoderef(self.sema.db) .enumerate() .find(|(_, deref_code_type)| pattern_type == deref_code_type) .map(|(count, _)| count) .ok_or_else(|| { + let display_target = krate.to_display_target(self.sema.db); + // Temporary needed to make the borrow checker happy. match_error!( "Pattern type `{}` didn't match code type `{}`", - pattern_type.display(self.sema.db, edition), - code_type.display(self.sema.db, edition) + pattern_type.display(self.sema.db, display_target), + code_type.display(self.sema.db, display_target) ) }); res diff --git a/src/tools/rust-analyzer/crates/ide/src/hover.rs b/src/tools/rust-analyzer/crates/ide/src/hover.rs index 9a3e77f3a9328..b00de6ba40833 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover.rs @@ -7,7 +7,8 @@ use std::{iter, ops::Not}; use either::Either; use hir::{ - db::DefDatabase, GenericDef, GenericSubstitution, HasCrate, HasSource, LangItem, Semantics, + db::DefDatabase, DisplayTarget, GenericDef, GenericSubstitution, HasCrate, HasSource, LangItem, + Semantics, }; use ide_db::{ defs::{Definition, IdentClass, NameRefClass, OperatorClass}, @@ -129,10 +130,18 @@ pub(crate) fn hover( let file = sema.parse_guess_edition(file_id).syntax().clone(); let edition = sema.attach_first_edition(file_id).map(|it| it.edition()).unwrap_or(Edition::CURRENT); + let display_target = sema.first_crate_or_default(file_id).to_display_target(db); let mut res = if range.is_empty() { - hover_offset(sema, FilePosition { file_id, offset: range.start() }, file, config, edition) + hover_offset( + sema, + FilePosition { file_id, offset: range.start() }, + file, + config, + edition, + display_target, + ) } else { - hover_ranged(sema, frange, file, config, edition) + hover_ranged(sema, frange, file, config, edition, display_target) }?; if let HoverDocFormat::PlainText = config.format { @@ -148,6 +157,7 @@ fn hover_offset( file: SyntaxNode, config: &HoverConfig, edition: Edition, + display_target: DisplayTarget, ) -> Option> { let original_token = pick_best_token(file.token_at_offset(offset), |kind| match kind { IDENT @@ -169,8 +179,18 @@ fn hover_offset( if let Some(doc_comment) = token_as_doc_comment(&original_token) { cov_mark::hit!(no_highlight_on_comment_hover); return doc_comment.get_definition_with_descend_at(sema, offset, |def, node, range| { - let res = - hover_for_definition(sema, file_id, def, None, &node, None, false, config, edition); + let res = hover_for_definition( + sema, + file_id, + def, + None, + &node, + None, + false, + config, + edition, + display_target, + ); Some(RangeInfo::new(range, res)) }); } @@ -188,6 +208,7 @@ fn hover_offset( false, config, edition, + display_target, ); return Some(RangeInfo::new(range, res)); } @@ -277,6 +298,7 @@ fn hover_offset( hovered_definition, config, edition, + display_target, ) }) .collect::>(), @@ -286,12 +308,12 @@ fn hover_offset( res.extend(definitions); continue; } - let keywords = || render::keyword(sema, config, &token, edition); + let keywords = || render::keyword(sema, config, &token, edition, display_target); let underscore = || { if !is_same_kind { return None; } - render::underscore(sema, config, &token, edition) + render::underscore(sema, config, &token, edition, display_target) }; let rest_pat = || { if !is_same_kind || token.kind() != DOT2 { @@ -305,7 +327,7 @@ fn hover_offset( let record_pat = record_pat_field_list.syntax().parent().and_then(ast::RecordPat::cast)?; - Some(render::struct_rest_pat(sema, config, &record_pat, edition)) + Some(render::struct_rest_pat(sema, config, &record_pat, edition, display_target)) }; let call = || { if !is_same_kind || token.kind() != T!['('] && token.kind() != T![')'] { @@ -319,17 +341,17 @@ fn hover_offset( _ => return None, } }; - render::type_info_of(sema, config, &Either::Left(call_expr), edition) + render::type_info_of(sema, config, &Either::Left(call_expr), edition, display_target) }; let closure = || { if !is_same_kind || token.kind() != T![|] { return None; } let c = token.parent().and_then(|x| x.parent()).and_then(ast::ClosureExpr::cast)?; - render::closure_expr(sema, config, c, edition) + render::closure_expr(sema, config, c, edition, display_target) }; let literal = || { - render::literal(sema, original_token.clone(), edition) + render::literal(sema, original_token.clone(), display_target) .map(|markup| HoverResult { markup, actions: vec![] }) }; if let Some(result) = keywords() @@ -362,6 +384,7 @@ fn hover_ranged( file: SyntaxNode, config: &HoverConfig, edition: Edition, + display_target: DisplayTarget, ) -> Option> { // FIXME: make this work in attributes let expr_or_pat = file @@ -371,16 +394,17 @@ fn hover_ranged( .find_map(Either::::cast)?; let res = match &expr_or_pat { Either::Left(ast::Expr::TryExpr(try_expr)) => { - render::try_expr(sema, config, try_expr, edition) + render::try_expr(sema, config, try_expr, edition, display_target) } Either::Left(ast::Expr::PrefixExpr(prefix_expr)) if prefix_expr.op_kind() == Some(ast::UnaryOp::Deref) => { - render::deref_expr(sema, config, prefix_expr, edition) + render::deref_expr(sema, config, prefix_expr, edition, display_target) } _ => None, }; - let res = res.or_else(|| render::type_info_of(sema, config, &expr_or_pat, edition)); + let res = + res.or_else(|| render::type_info_of(sema, config, &expr_or_pat, edition, display_target)); res.map(|it| { let range = match expr_or_pat { Either::Left(it) => it.syntax().text_range(), @@ -401,6 +425,7 @@ pub(crate) fn hover_for_definition( hovered_definition: bool, config: &HoverConfig, edition: Edition, + display_target: DisplayTarget, ) -> HoverResult { let famous_defs = match &def { Definition::BuiltinType(_) => sema.scope(scope_node).map(|it| FamousDefs(sema, it.krate())), @@ -435,6 +460,7 @@ pub(crate) fn hover_for_definition( subst_types.as_ref(), config, edition, + display_target, ); HoverResult { markup: render::process_markup(sema.db, def, &markup, config), diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs index c5a83e58cea13..31ef89a07cde1 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs @@ -3,7 +3,7 @@ use std::{env, mem, ops::Not}; use either::Either; use hir::{ - db::ExpandDatabase, Adt, AsAssocItem, AsExternAssocItem, CaptureKind, DropGlue, + db::ExpandDatabase, Adt, AsAssocItem, AsExternAssocItem, CaptureKind, DisplayTarget, DropGlue, DynCompatibilityViolation, HasCrate, HasSource, HirDisplay, Layout, LayoutError, MethodViolationCode, Name, Semantics, Symbol, Trait, Type, TypeInfo, VariantDef, }; @@ -38,12 +38,13 @@ pub(super) fn type_info_of( _config: &HoverConfig, expr_or_pat: &Either, edition: Edition, + display_target: DisplayTarget, ) -> Option { let ty_info = match expr_or_pat { Either::Left(expr) => sema.type_of_expr(expr)?, Either::Right(pat) => sema.type_of_pat(pat)?, }; - type_info(sema, _config, ty_info, edition) + type_info(sema, _config, ty_info, edition, display_target) } pub(super) fn closure_expr( @@ -51,9 +52,10 @@ pub(super) fn closure_expr( config: &HoverConfig, c: ast::ClosureExpr, edition: Edition, + display_target: DisplayTarget, ) -> Option { let TypeInfo { original, .. } = sema.type_of_expr(&c.into())?; - closure_ty(sema, config, &TypeInfo { original, adjusted: None }, edition) + closure_ty(sema, config, &TypeInfo { original, adjusted: None }, edition, display_target) } pub(super) fn try_expr( @@ -61,6 +63,7 @@ pub(super) fn try_expr( _config: &HoverConfig, try_expr: &ast::TryExpr, edition: Edition, + display_target: DisplayTarget, ) -> Option { let inner_ty = sema.type_of_expr(&try_expr.expr()?)?.original; let mut ancestors = try_expr.syntax().ancestors(); @@ -127,8 +130,8 @@ pub(super) fn try_expr( res.actions.push(actions); } - let inner_ty = inner_ty.display(sema.db, edition).to_string(); - let body_ty = body_ty.display(sema.db, edition).to_string(); + let inner_ty = inner_ty.display(sema.db, display_target).to_string(); + let body_ty = body_ty.display(sema.db, display_target).to_string(); let ty_len_max = inner_ty.len().max(body_ty.len()); let l = "Propagated as: ".len() - " Type: ".len(); @@ -153,6 +156,7 @@ pub(super) fn deref_expr( _config: &HoverConfig, deref_expr: &ast::PrefixExpr, edition: Edition, + display_target: DisplayTarget, ) -> Option { let inner_ty = sema.type_of_expr(&deref_expr.expr()?)?.original; let TypeInfo { original, adjusted } = @@ -170,9 +174,9 @@ pub(super) fn deref_expr( res.markup = if let Some(adjusted_ty) = adjusted { walk_and_push_ty(sema.db, &adjusted_ty, &mut push_new_def); - let original = original.display(sema.db, edition).to_string(); - let adjusted = adjusted_ty.display(sema.db, edition).to_string(); - let inner = inner_ty.display(sema.db, edition).to_string(); + let original = original.display(sema.db, display_target).to_string(); + let adjusted = adjusted_ty.display(sema.db, display_target).to_string(); + let inner = inner_ty.display(sema.db, display_target).to_string(); let type_len = "To type: ".len(); let coerced_len = "Coerced to: ".len(); let deref_len = "Dereferenced from: ".len(); @@ -190,8 +194,8 @@ pub(super) fn deref_expr( ) .into() } else { - let original = original.display(sema.db, edition).to_string(); - let inner = inner_ty.display(sema.db, edition).to_string(); + let original = original.display(sema.db, display_target).to_string(); + let inner = inner_ty.display(sema.db, display_target).to_string(); let type_len = "To type: ".len(); let deref_len = "Dereferenced from: ".len(); let max_len = (original.len() + type_len).max(inner.len() + deref_len); @@ -216,6 +220,7 @@ pub(super) fn underscore( config: &HoverConfig, token: &SyntaxToken, edition: Edition, + display_target: DisplayTarget, ) -> Option { if token.kind() != T![_] { return None; @@ -224,8 +229,8 @@ pub(super) fn underscore( let _it = match_ast! { match parent { ast::InferType(it) => it, - ast::UnderscoreExpr(it) => return type_info_of(sema, config, &Either::Left(ast::Expr::UnderscoreExpr(it)),edition), - ast::WildcardPat(it) => return type_info_of(sema, config, &Either::Right(ast::Pat::WildcardPat(it)),edition), + ast::UnderscoreExpr(it) => return type_info_of(sema, config, &Either::Left(ast::Expr::UnderscoreExpr(it)),edition, display_target), + ast::WildcardPat(it) => return type_info_of(sema, config, &Either::Right(ast::Pat::WildcardPat(it)),edition, display_target), _ => return None, } }; @@ -259,6 +264,7 @@ pub(super) fn keyword( config: &HoverConfig, token: &SyntaxToken, edition: Edition, + display_target: DisplayTarget, ) -> Option { if !token.kind().is_keyword(edition) || !config.documentation || !config.keywords { return None; @@ -267,7 +273,7 @@ pub(super) fn keyword( let famous_defs = FamousDefs(sema, sema.scope(&parent)?.krate()); let KeywordHint { description, keyword_mod, actions } = - keyword_hints(sema, token, parent, edition); + keyword_hints(sema, token, parent, edition, display_target); let doc_owner = find_std_module(&famous_defs, &keyword_mod, edition)?; let docs = doc_owner.docs(sema.db)?; @@ -288,6 +294,7 @@ pub(super) fn struct_rest_pat( _config: &HoverConfig, pattern: &ast::RecordPat, edition: Edition, + display_target: DisplayTarget, ) -> HoverResult { let missing_fields = sema.record_pattern_missing_fields(pattern); @@ -309,7 +316,7 @@ pub(super) fn struct_rest_pat( res.markup = { let mut s = String::from(".., "); for (f, _) in &missing_fields { - s += f.display(sema.db, edition).to_string().as_ref(); + s += f.display(sema.db, display_target).to_string().as_ref(); s += ", "; } // get rid of trailing comma @@ -479,41 +486,44 @@ pub(super) fn definition( subst_types: Option<&Vec<(Symbol, Type)>>, config: &HoverConfig, edition: Edition, + display_target: DisplayTarget, ) -> Markup { let mod_path = definition_path(db, &def, edition); let label = match def { - Definition::Trait(trait_) => { - trait_.display_limited(db, config.max_trait_assoc_items_count, edition).to_string() - } + Definition::Trait(trait_) => trait_ + .display_limited(db, config.max_trait_assoc_items_count, display_target) + .to_string(), Definition::Adt(adt @ (Adt::Struct(_) | Adt::Union(_))) => { - adt.display_limited(db, config.max_fields_count, edition).to_string() + adt.display_limited(db, config.max_fields_count, display_target).to_string() } Definition::Variant(variant) => { - variant.display_limited(db, config.max_fields_count, edition).to_string() + variant.display_limited(db, config.max_fields_count, display_target).to_string() } Definition::Adt(adt @ Adt::Enum(_)) => { - adt.display_limited(db, config.max_enum_variants_count, edition).to_string() + adt.display_limited(db, config.max_enum_variants_count, display_target).to_string() } Definition::SelfType(impl_def) => { let self_ty = &impl_def.self_ty(db); match self_ty.as_adt() { - Some(adt) => adt.display_limited(db, config.max_fields_count, edition).to_string(), - None => self_ty.display(db, edition).to_string(), + Some(adt) => { + adt.display_limited(db, config.max_fields_count, display_target).to_string() + } + None => self_ty.display(db, display_target).to_string(), } } Definition::Macro(it) => { - let mut label = it.display(db, edition).to_string(); + let mut label = it.display(db, display_target).to_string(); if let Some(macro_arm) = macro_arm { format_to!(label, " // matched arm #{}", macro_arm); } label } Definition::Function(fn_) => { - fn_.display_with_container_bounds(db, true, edition).to_string() + fn_.display_with_container_bounds(db, true, display_target).to_string() } - _ => def.label(db, edition), + _ => def.label(db, display_target), }; - let docs = def.docs(db, famous_defs, edition); + let docs = def.docs(db, famous_defs, display_target); let value = || match def { Definition::Variant(it) => { if !it.parent_enum(db).is_data_carrying(db) { @@ -525,7 +535,10 @@ pub(super) fn definition( let res = it.value(db).map(|it| format!("{it:?}")); if env::var_os("RA_DEV").is_some() { let res = res.as_deref().unwrap_or(""); - Some(format!("{res} ({})", render_const_eval_error(db, err, edition))) + Some(format!( + "{res} ({})", + render_const_eval_error(db, err, display_target) + )) } else { res } @@ -541,9 +554,12 @@ pub(super) fn definition( Ok(it) => match it.render_debug(db) { Ok(it) => it, Err(err) => { - let it = it.render(db, edition); + let it = it.render(db, display_target); if env::var_os("RA_DEV").is_some() { - format!("{it}\n{}", render_const_eval_error(db, err.into(), edition)) + format!( + "{it}\n{}", + render_const_eval_error(db, err.into(), display_target) + ) } else { it } @@ -557,7 +573,7 @@ pub(super) fn definition( body = prettify_macro_expansion(db, body, &span_map, it.krate(db).into()); } if env::var_os("RA_DEV").is_some() { - format!("{body}\n{}", render_const_eval_error(db, err, edition)) + format!("{body}\n{}", render_const_eval_error(db, err, display_target)) } else { body.to_string() } @@ -570,9 +586,12 @@ pub(super) fn definition( Ok(it) => match it.render_debug(db) { Ok(it) => it, Err(err) => { - let it = it.render(db, edition); + let it = it.render(db, display_target); if env::var_os("RA_DEV").is_some() { - format!("{it}\n{}", render_const_eval_error(db, err.into(), edition)) + format!( + "{it}\n{}", + render_const_eval_error(db, err.into(), display_target) + ) } else { it } @@ -586,7 +605,7 @@ pub(super) fn definition( body = prettify_macro_expansion(db, body, &span_map, it.krate(db).into()); } if env::var_os("RA_DEV").is_some() { - format!("{body}\n{}", render_const_eval_error(db, err, edition)) + format!("{body}\n{}", render_const_eval_error(db, err, display_target)) } else { body.to_string() } @@ -728,7 +747,9 @@ pub(super) fn definition( let mut extra = String::new(); if hovered_definition { - if let Some(notable_traits) = render_notable_trait(db, notable_traits, edition) { + if let Some(notable_traits) = + render_notable_trait(db, notable_traits, edition, display_target) + { extra.push_str("\n___\n"); extra.push_str(¬able_traits); } @@ -772,7 +793,7 @@ pub(super) fn definition( .format_with(", ", |(name, ty), fmt| { fmt(&format_args!( "`{name}` = `{}`", - ty.display_truncated(db, limit, edition) + ty.display_truncated(db, limit, display_target) )) }) .to_string() @@ -799,7 +820,7 @@ struct DropInfo { pub(super) fn literal( sema: &Semantics<'_, RootDatabase>, token: SyntaxToken, - edition: Edition, + display_target: DisplayTarget, ) -> Option { let lit = token.parent().and_then(ast::Literal::cast)?; let ty = if let Some(p) = lit.syntax().parent().and_then(ast::Pat::cast) { @@ -847,7 +868,7 @@ pub(super) fn literal( _ => return None } }; - let ty = ty.display(sema.db, edition); + let ty = ty.display(sema.db, display_target); let mut s = format!("```rust\n{ty}\n```\n___\n\n"); match value { @@ -879,6 +900,7 @@ fn render_notable_trait( db: &RootDatabase, notable_traits: &[(Trait, Vec<(Option, Name)>)], edition: Edition, + display_target: DisplayTarget, ) -> Option { let mut desc = String::new(); let mut needs_impl_header = true; @@ -898,7 +920,7 @@ fn render_notable_trait( f(&name.display(db, edition))?; f(&" = ")?; match ty { - Some(ty) => f(&ty.display(db, edition)), + Some(ty) => f(&ty.display(db, display_target)), None => f(&"?"), } }) @@ -914,8 +936,9 @@ fn type_info( config: &HoverConfig, ty: TypeInfo, edition: Edition, + display_target: DisplayTarget, ) -> Option { - if let Some(res) = closure_ty(sema, config, &ty, edition) { + if let Some(res) = closure_ty(sema, config, &ty, edition, display_target) { return Some(res); }; let db = sema.db; @@ -951,7 +974,7 @@ fn type_info( f(&name.display(db, edition))?; f(&" = ")?; match ty { - Some(ty) => f(&ty.display(db, edition)), + Some(ty) => f(&ty.display(db, display_target)), None => f(&"?"), } }) @@ -965,8 +988,8 @@ fn type_info( desc }; - let original = original.display(db, edition).to_string(); - let adjusted = adjusted_ty.display(db, edition).to_string(); + let original = original.display(db, display_target).to_string(); + let adjusted = adjusted_ty.display(db, display_target).to_string(); let static_text_diff_len = "Coerced to: ".len() - "Type: ".len(); format!( "```text\nType: {:>apad$}\nCoerced to: {:>opad$}\n{notable}```\n", @@ -977,8 +1000,10 @@ fn type_info( ) .into() } else { - let mut desc = format!("```rust\n{}\n```", original.display(db, edition)); - if let Some(extra) = render_notable_trait(db, ¬able_traits(db, &original), edition) { + let mut desc = format!("```rust\n{}\n```", original.display(db, display_target)); + if let Some(extra) = + render_notable_trait(db, ¬able_traits(db, &original), edition, display_target) + { desc.push_str("\n___\n"); desc.push_str(&extra); }; @@ -995,6 +1020,7 @@ fn closure_ty( config: &HoverConfig, TypeInfo { original, adjusted }: &TypeInfo, edition: Edition, + display_target: DisplayTarget, ) -> Option { let c = original.as_closure()?; let mut captures_rendered = c.captured_items(sema.db) @@ -1027,12 +1053,14 @@ fn closure_ty( walk_and_push_ty(sema.db, adjusted_ty, &mut push_new_def); format!( "\nCoerced to: {}", - adjusted_ty.display(sema.db, edition).with_closure_style(hir::ClosureStyle::ImplFn) + adjusted_ty + .display(sema.db, display_target) + .with_closure_style(hir::ClosureStyle::ImplFn) ) } else { String::new() }; - let mut markup = format!("```rust\n{}\n```", c.display_with_impl(sema.db, edition)); + let mut markup = format!("```rust\n{}\n```", c.display_with_impl(sema.db, display_target)); if let Some(trait_) = c.fn_trait(sema.db).get_id(sema.db, original.krate(sema.db).into()) { push_new_def(hir::Trait::from(trait_).into()) @@ -1213,6 +1241,7 @@ fn keyword_hints( token: &SyntaxToken, parent: syntax::SyntaxNode, edition: Edition, + display_target: DisplayTarget, ) -> KeywordHint { match token.kind() { T![await] | T![loop] | T![match] | T![unsafe] | T![as] | T![try] | T![if] | T![else] => { @@ -1230,7 +1259,8 @@ fn keyword_hints( walk_and_push_ty(sema.db, &ty.original, &mut push_new_def); let ty = ty.adjusted(); - let description = format!("{}: {}", token.text(), ty.display(sema.db, edition)); + let description = + format!("{}: {}", token.text(), ty.display(sema.db, display_target)); KeywordHint { description, diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs index 63039b1cd34e0..6babdff52a2be 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs @@ -5,14 +5,14 @@ use std::{ use either::Either; use hir::{ - sym, ClosureStyle, HasVisibility, HirDisplay, HirDisplayError, HirWrite, ModuleDef, - ModuleDefId, Semantics, + sym, ClosureStyle, DisplayTarget, HasVisibility, HirDisplay, HirDisplayError, HirWrite, + ModuleDef, ModuleDefId, Semantics, }; use ide_db::{famous_defs::FamousDefs, FileRange, RootDatabase}; use ide_db::{text_edit::TextEdit, FxHashSet}; use itertools::Itertools; use smallvec::{smallvec, SmallVec}; -use span::{Edition, EditionedFileId}; +use span::EditionedFileId; use stdx::never; use syntax::{ ast::{self, AstNode, HasGenericParams}, @@ -207,7 +207,8 @@ fn hints( file_id: EditionedFileId, node: SyntaxNode, ) { - closing_brace::hints(hints, sema, config, file_id, node.clone()); + let display_target = sema.first_crate_or_default(file_id.file_id()).to_display_target(sema.db); + closing_brace::hints(hints, sema, config, file_id, display_target, node.clone()); if let Some(any_has_generic_args) = ast::AnyHasGenericArgs::cast(node.clone()) { generic_param::hints(hints, famous_defs, config, any_has_generic_args); } @@ -215,8 +216,8 @@ fn hints( match_ast! { match node { ast::Expr(expr) => { - chaining::hints(hints, famous_defs, config, file_id, &expr); - adjustment::hints(hints, famous_defs, config, file_id, &expr); + chaining::hints(hints, famous_defs, config, display_target, &expr); + adjustment::hints(hints, famous_defs, config, display_target, &expr); match expr { ast::Expr::CallExpr(it) => param_name::hints(hints, famous_defs, config, file_id, ast::Expr::from(it)), ast::Expr::MethodCallExpr(it) => { @@ -224,7 +225,7 @@ fn hints( } ast::Expr::ClosureExpr(it) => { closure_captures::hints(hints, famous_defs, config, file_id, it.clone()); - closure_ret::hints(hints, famous_defs, config, file_id, it) + closure_ret::hints(hints, famous_defs, config, display_target, it) }, ast::Expr::RangeExpr(it) => range_exclusive::hints(hints, famous_defs, config, file_id, it), _ => Some(()), @@ -234,7 +235,7 @@ fn hints( binding_mode::hints(hints, famous_defs, config, file_id, &it); match it { ast::Pat::IdentPat(it) => { - bind_pat::hints(hints, famous_defs, config, file_id, &it); + bind_pat::hints(hints, famous_defs, config, display_target, &it); } ast::Pat::RangePat(it) => { range_exclusive::hints(hints, famous_defs, config, file_id, it); @@ -704,7 +705,7 @@ fn label_of_ty( famous_defs @ FamousDefs(sema, _): &FamousDefs<'_, '_>, config: &InlayHintsConfig, ty: &hir::Type, - edition: Edition, + display_target: DisplayTarget, ) -> Option { fn rec( sema: &Semantics<'_, RootDatabase>, @@ -713,7 +714,7 @@ fn label_of_ty( ty: &hir::Type, label_builder: &mut InlayHintLabelBuilder<'_>, config: &InlayHintsConfig, - edition: Edition, + display_target: DisplayTarget, ) -> Result<(), HirDisplayError> { let iter_item_type = hint_iterator(sema, famous_defs, ty); match iter_item_type { @@ -744,12 +745,12 @@ fn label_of_ty( label_builder.write_str(LABEL_ITEM)?; label_builder.end_location_link(); label_builder.write_str(LABEL_MIDDLE2)?; - rec(sema, famous_defs, max_length, &ty, label_builder, config, edition)?; + rec(sema, famous_defs, max_length, &ty, label_builder, config, display_target)?; label_builder.write_str(LABEL_END)?; Ok(()) } None => ty - .display_truncated(sema.db, max_length, edition) + .display_truncated(sema.db, max_length, display_target) .with_closure_style(config.closure_style) .write_to(label_builder), } @@ -762,7 +763,8 @@ fn label_of_ty( result: InlayHintLabel::default(), resolve: config.fields_to_resolve.resolve_label_location, }; - let _ = rec(sema, famous_defs, config.max_length, ty, &mut label_builder, config, edition); + let _ = + rec(sema, famous_defs, config.max_length, ty, &mut label_builder, config, display_target); let r = label_builder.finish(); Some(r) } diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs index 8522ef0a6d5f4..91b8187295236 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs @@ -7,12 +7,12 @@ use std::ops::Not; use either::Either; use hir::{ - Adjust, Adjustment, AutoBorrow, HirDisplay, Mutability, OverloadedDeref, PointerCast, Safety, + Adjust, Adjustment, AutoBorrow, DisplayTarget, HirDisplay, Mutability, OverloadedDeref, + PointerCast, Safety, }; use ide_db::famous_defs::FamousDefs; use ide_db::text_edit::TextEditBuilder; -use span::EditionedFileId; use syntax::ast::{self, prec::ExprPrecedence, AstNode}; use crate::{ @@ -24,7 +24,7 @@ pub(super) fn hints( acc: &mut Vec, FamousDefs(sema, _): &FamousDefs<'_, '_>, config: &InlayHintsConfig, - file_id: EditionedFileId, + display_target: DisplayTarget, expr: &ast::Expr, ) -> Option<()> { if config.adjustment_hints_hide_outside_unsafe && !sema.is_inside_unsafe(expr) { @@ -163,8 +163,8 @@ pub(super) fn hints( tooltip: Some(config.lazy_tooltip(|| { InlayTooltip::Markdown(format!( "`{}` → `{}` ({coercion} coercion)", - source.display(sema.db, file_id.edition()), - target.display(sema.db, file_id.edition()), + source.display(sema.db, display_target), + target.display(sema.db, display_target), )) })), }; diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs index c2986a9aa6626..4379153acaa17 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs @@ -3,11 +3,10 @@ //! fn f(a: i32, b: i32) -> i32 { a + b } //! let _x /* i32 */= f(4, 4); //! ``` -use hir::Semantics; +use hir::{DisplayTarget, Semantics}; use ide_db::{famous_defs::FamousDefs, RootDatabase}; use itertools::Itertools; -use span::EditionedFileId; use syntax::{ ast::{self, AstNode, HasGenericArgs, HasName}, match_ast, @@ -22,7 +21,7 @@ pub(super) fn hints( acc: &mut Vec, famous_defs @ FamousDefs(sema, _): &FamousDefs<'_, '_>, config: &InlayHintsConfig, - file_id: EditionedFileId, + display_target: DisplayTarget, pat: &ast::IdentPat, ) -> Option<()> { if !config.type_hints { @@ -70,7 +69,7 @@ pub(super) fn hints( return None; } - let mut label = label_of_ty(famous_defs, config, &ty, file_id.edition())?; + let mut label = label_of_ty(famous_defs, config, &ty, display_target)?; if config.hide_named_constructor_hints && is_named_constructor(sema, pat, &label.to_string()).is_some() diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs index 8471547727fed..604719bc366f5 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs @@ -1,6 +1,6 @@ //! Implementation of "chaining" inlay hints. +use hir::DisplayTarget; use ide_db::famous_defs::FamousDefs; -use span::EditionedFileId; use syntax::{ ast::{self, AstNode}, Direction, NodeOrToken, SyntaxKind, T, @@ -14,7 +14,7 @@ pub(super) fn hints( acc: &mut Vec, famous_defs @ FamousDefs(sema, _): &FamousDefs<'_, '_>, config: &InlayHintsConfig, - file_id: EditionedFileId, + display_target: DisplayTarget, expr: &ast::Expr, ) -> Option<()> { if !config.chaining_hints { @@ -58,7 +58,7 @@ pub(super) fn hints( } } } - let label = label_of_ty(famous_defs, config, &ty, file_id.edition())?; + let label = label_of_ty(famous_defs, config, &ty, display_target)?; acc.push(InlayHint { range: expr.syntax().text_range(), kind: InlayKind::Chaining, diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs index 3767d34e2c7a9..bec6d38ee9cac 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs @@ -3,7 +3,7 @@ //! fn g() { //! } /* fn g */ //! ``` -use hir::{HirDisplay, Semantics}; +use hir::{DisplayTarget, HirDisplay, Semantics}; use ide_db::{FileRange, RootDatabase}; use span::EditionedFileId; use syntax::{ @@ -21,6 +21,7 @@ pub(super) fn hints( sema: &Semantics<'_, RootDatabase>, config: &InlayHintsConfig, file_id: EditionedFileId, + display_target: DisplayTarget, original_node: SyntaxNode, ) -> Option<()> { let min_lines = config.closing_brace_hints_min_lines?; @@ -43,9 +44,9 @@ pub(super) fn hints( Some(tr) => format!( "impl {} for {}", tr.name(sema.db).display(sema.db, file_id.edition()), - ty.display_truncated(sema.db, config.max_length, file_id.edition(), + ty.display_truncated(sema.db, config.max_length, display_target, )), - None => format!("impl {}", ty.display_truncated(sema.db, config.max_length, file_id.edition())), + None => format!("impl {}", ty.display_truncated(sema.db, config.max_length, display_target)), }; (hint_text, None) }, diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs index 7858b1d90a384..61c9c25fe7396 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs @@ -1,8 +1,8 @@ //! Implementation of "closure return type" inlay hints. //! //! Tests live in [`bind_pat`][super::bind_pat] module. +use hir::DisplayTarget; use ide_db::famous_defs::FamousDefs; -use span::EditionedFileId; use syntax::ast::{self, AstNode}; use crate::{ @@ -14,7 +14,7 @@ pub(super) fn hints( acc: &mut Vec, famous_defs @ FamousDefs(sema, _): &FamousDefs<'_, '_>, config: &InlayHintsConfig, - file_id: EditionedFileId, + display_target: DisplayTarget, closure: ast::ClosureExpr, ) -> Option<()> { if config.closure_return_type_hints == ClosureReturnTypeHints::Never { @@ -43,7 +43,7 @@ pub(super) fn hints( return None; } - let mut label = label_of_ty(famous_defs, config, &ty, file_id.edition())?; + let mut label = label_of_ty(famous_defs, config, &ty, display_target)?; if arrow.is_none() { label.prepend_str(" -> "); diff --git a/src/tools/rust-analyzer/crates/ide/src/interpret.rs b/src/tools/rust-analyzer/crates/ide/src/interpret.rs index ae11072e34b74..74dad488b4d30 100644 --- a/src/tools/rust-analyzer/crates/ide/src/interpret.rs +++ b/src/tools/rust-analyzer/crates/ide/src/interpret.rs @@ -1,6 +1,5 @@ -use hir::{ConstEvalError, DefWithBody, Semantics}; +use hir::{ConstEvalError, DefWithBody, DisplayTarget, Semantics}; use ide_db::{base_db::SourceRootDatabase, FilePosition, LineIndexDatabase, RootDatabase}; -use span::Edition; use std::time::{Duration, Instant}; use stdx::format_to; use syntax::{algo::ancestors_at_offset, ast, AstNode, TextRange}; @@ -46,15 +45,15 @@ fn find_and_interpret(db: &RootDatabase, position: FilePosition) -> Option<(Dura None => format!("file://{path} range {text_range:?}"), } }; - let edition = def.module(db).krate().edition(db); + let display_target = def.module(db).krate().to_display_target(db); let start_time = Instant::now(); let res = match def { DefWithBody::Function(it) => it.eval(db, span_formatter), - DefWithBody::Static(it) => it.eval(db).map(|it| it.render(db, edition)), - DefWithBody::Const(it) => it.eval(db).map(|it| it.render(db, edition)), + DefWithBody::Static(it) => it.eval(db).map(|it| it.render(db, display_target)), + DefWithBody::Const(it) => it.eval(db).map(|it| it.render(db, display_target)), _ => unreachable!(), }; - let res = res.unwrap_or_else(|e| render_const_eval_error(db, e, edition)); + let res = res.unwrap_or_else(|e| render_const_eval_error(db, e, display_target)); let duration = Instant::now() - start_time; Some((duration, res)) } @@ -62,7 +61,7 @@ fn find_and_interpret(db: &RootDatabase, position: FilePosition) -> Option<(Dura pub(crate) fn render_const_eval_error( db: &RootDatabase, e: ConstEvalError, - edition: Edition, + display_target: DisplayTarget, ) -> String { let span_formatter = |file_id, text_range: TextRange| { let path = &db @@ -76,6 +75,6 @@ pub(crate) fn render_const_eval_error( } }; let mut r = String::new(); - _ = e.pretty_print(&mut r, db, span_formatter, edition); + _ = e.pretty_print(&mut r, db, span_formatter, display_target); r } diff --git a/src/tools/rust-analyzer/crates/ide/src/moniker.rs b/src/tools/rust-analyzer/crates/ide/src/moniker.rs index 25d12a4c0b4f4..5754b4fa82f43 100644 --- a/src/tools/rust-analyzer/crates/ide/src/moniker.rs +++ b/src/tools/rust-analyzer/crates/ide/src/moniker.rs @@ -11,7 +11,6 @@ use ide_db::{ FilePosition, RootDatabase, }; use itertools::Itertools; -use span::Edition; use syntax::{AstNode, SyntaxKind::*, T}; use crate::{doc_links::token_as_doc_comment, parent_module::crates_for, RangeInfo}; @@ -305,13 +304,13 @@ fn def_to_non_local_moniker( if let Some(trait_ref) = impl_.trait_ref(db) { // Trait impls use the trait type for the 2nd parameter. reverse_description.push(MonikerDescriptor { - name: display(db, edition, module, trait_ref), + name: display(db, module, trait_ref), desc: MonikerDescriptorKind::TypeParameter, }); } // Both inherent and trait impls use the self type for the first parameter. reverse_description.push(MonikerDescriptor { - name: display(db, edition, module, impl_.self_ty(db)), + name: display(db, module, impl_.self_ty(db)), desc: MonikerDescriptorKind::TypeParameter, }); reverse_description.push(MonikerDescriptor { @@ -390,17 +389,12 @@ fn def_to_non_local_moniker( }) } -fn display( - db: &RootDatabase, - edition: Edition, - module: hir::Module, - it: T, -) -> String { +fn display(db: &RootDatabase, module: hir::Module, it: T) -> String { match it.display_source_code(db, module.into(), true) { Ok(result) => result, // Fallback on display variant that always succeeds Err(_) => { - let fallback_result = it.display(db, edition).to_string(); + let fallback_result = it.display(db, module.krate().to_display_target(db)).to_string(); tracing::error!( display = %fallback_result, "`display_source_code` failed; falling back to using display" ); diff --git a/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs b/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs index d9f80cb53dd6b..d67aaac06fb95 100644 --- a/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs +++ b/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs @@ -6,7 +6,7 @@ use arrayvec::ArrayVec; use either::Either; use hir::{ db::ExpandDatabase, symbols::FileSymbol, AssocItem, FieldSource, HasContainer, HasCrate, - HasSource, HirDisplay, HirFileId, HirFileIdExt, InFile, LocalSource, ModuleSource, + HasSource, HirDisplay, HirFileId, InFile, LocalSource, ModuleSource, }; use ide_db::{ defs::Definition, @@ -116,7 +116,9 @@ impl NavigationTarget { SymbolKind::Module, ); res.docs = module.docs(db); - res.description = Some(module.display(db, edition).to_string()); + res.description = Some( + module.display(db, module.krate().to_display_target(db)).to_string(), + ); res }, ) @@ -183,6 +185,7 @@ impl TryToNav for FileSymbol { fn try_to_nav(&self, db: &RootDatabase) -> Option> { let edition = self.def.module(db).map(|it| it.krate().edition(db)).unwrap_or(Edition::CURRENT); + let display_target = self.def.krate(db).to_display_target(db); Some( orig_range_with_focus_r( db, @@ -203,16 +206,34 @@ impl TryToNav for FileSymbol { focus_range, container_name: self.container_name.clone(), description: match self.def { - hir::ModuleDef::Module(it) => Some(it.display(db, edition).to_string()), - hir::ModuleDef::Function(it) => Some(it.display(db, edition).to_string()), - hir::ModuleDef::Adt(it) => Some(it.display(db, edition).to_string()), - hir::ModuleDef::Variant(it) => Some(it.display(db, edition).to_string()), - hir::ModuleDef::Const(it) => Some(it.display(db, edition).to_string()), - hir::ModuleDef::Static(it) => Some(it.display(db, edition).to_string()), - hir::ModuleDef::Trait(it) => Some(it.display(db, edition).to_string()), - hir::ModuleDef::TraitAlias(it) => Some(it.display(db, edition).to_string()), - hir::ModuleDef::TypeAlias(it) => Some(it.display(db, edition).to_string()), - hir::ModuleDef::Macro(it) => Some(it.display(db, edition).to_string()), + hir::ModuleDef::Module(it) => { + Some(it.display(db, display_target).to_string()) + } + hir::ModuleDef::Function(it) => { + Some(it.display(db, display_target).to_string()) + } + hir::ModuleDef::Adt(it) => Some(it.display(db, display_target).to_string()), + hir::ModuleDef::Variant(it) => { + Some(it.display(db, display_target).to_string()) + } + hir::ModuleDef::Const(it) => { + Some(it.display(db, display_target).to_string()) + } + hir::ModuleDef::Static(it) => { + Some(it.display(db, display_target).to_string()) + } + hir::ModuleDef::Trait(it) => { + Some(it.display(db, display_target).to_string()) + } + hir::ModuleDef::TraitAlias(it) => { + Some(it.display(db, display_target).to_string()) + } + hir::ModuleDef::TypeAlias(it) => { + Some(it.display(db, display_target).to_string()) + } + hir::ModuleDef::Macro(it) => { + Some(it.display(db, display_target).to_string()) + } hir::ModuleDef::BuiltinType(_) => None, }, docs: None, @@ -353,12 +374,11 @@ impl ToNavFromAst for hir::TraitAlias { impl TryToNav for D where - D: HasSource + ToNavFromAst + Copy + HasDocs + HirDisplay, + D: HasSource + ToNavFromAst + Copy + HasDocs + HirDisplay + HasCrate, D::Ast: ast::HasName, { fn try_to_nav(&self, db: &RootDatabase) -> Option> { let src = self.source(db)?; - let edition = src.file_id.original_file(db).edition(); Some( NavigationTarget::from_named( db, @@ -367,7 +387,8 @@ where ) .map(|mut res| { res.docs = self.docs(db); - res.description = Some(self.display(db, edition).to_string()); + res.description = + Some(self.display(db, self.krate(db).to_display_target(db)).to_string()); res.container_name = self.container_name(db); res }), @@ -439,7 +460,8 @@ impl TryToNav for hir::ExternCrateDecl { let focus = value .rename() .map_or_else(|| value.name_ref().map(Either::Left), |it| it.name().map(Either::Right)); - let edition = self.module(db).krate().edition(db); + let krate = self.module(db).krate(); + let edition = krate.edition(db); Some(orig_range_with_focus(db, file_id, value.syntax(), focus).map( |(FileRange { file_id, range: full_range }, focus_range)| { @@ -455,7 +477,7 @@ impl TryToNav for hir::ExternCrateDecl { ); res.docs = self.docs(db); - res.description = Some(self.display(db, edition).to_string()); + res.description = Some(self.display(db, krate.to_display_target(db)).to_string()); res.container_name = container_name(db, *self, edition); res }, @@ -466,14 +488,15 @@ impl TryToNav for hir::ExternCrateDecl { impl TryToNav for hir::Field { fn try_to_nav(&self, db: &RootDatabase) -> Option> { let src = self.source(db)?; - let edition = self.parent_def(db).module(db).krate().edition(db); + let krate = self.parent_def(db).module(db).krate(); let field_source = match &src.value { FieldSource::Named(it) => { NavigationTarget::from_named(db, src.with_value(it), SymbolKind::Field).map( |mut res| { res.docs = self.docs(db); - res.description = Some(self.display(db, edition).to_string()); + res.description = + Some(self.display(db, krate.to_display_target(db)).to_string()); res }, ) diff --git a/src/tools/rust-analyzer/crates/ide/src/runnables.rs b/src/tools/rust-analyzer/crates/ide/src/runnables.rs index 509ae3204c36d..b8deed01fb7f2 100644 --- a/src/tools/rust-analyzer/crates/ide/src/runnables.rs +++ b/src/tools/rust-analyzer/crates/ide/src/runnables.rs @@ -9,6 +9,7 @@ use hir::{ }; use ide_assists::utils::{has_test_related_attribute, test_related_attribute_syn}; use ide_db::{ + base_db::SourceDatabase, defs::Definition, documentation::docs_from_attrs, helpers::visit_file_defs, @@ -399,7 +400,8 @@ pub(crate) fn runnable_impl( sema: &Semantics<'_, RootDatabase>, def: &hir::Impl, ) -> Option { - let edition = def.module(sema.db).krate().edition(sema.db); + let display_target = def.module(sema.db).krate().to_display_target(sema.db); + let edition = display_target.edition; let attrs = def.attrs(sema.db); if !has_runnable_doc_test(&attrs) { return None; @@ -408,7 +410,7 @@ pub(crate) fn runnable_impl( let nav = def.try_to_nav(sema.db)?.call_site(); let ty = def.self_ty(sema.db); let adt_name = ty.as_adt()?.name(sema.db); - let mut ty_args = ty.generic_parameters(sema.db, edition).peekable(); + let mut ty_args = ty.generic_parameters(sema.db, display_target).peekable(); let params = if ty_args.peek().is_some() { format!("<{}>", ty_args.format_with(",", |ty, cb| cb(&ty))) } else { @@ -494,7 +496,11 @@ fn module_def_doctest(db: &RootDatabase, def: Definition) -> Option { Definition::SelfType(it) => it.attrs(db), _ => return None, }; - let edition = def.krate(db).map(|it| it.edition(db)).unwrap_or(Edition::CURRENT); + let krate = def.krate(db); + let edition = krate.map(|it| it.edition(db)).unwrap_or(Edition::CURRENT); + let display_target = krate + .unwrap_or_else(|| (*db.crate_graph().crates_in_topological_order().last().unwrap()).into()) + .to_display_target(db); if !has_runnable_doc_test(&attrs) { return None; } @@ -509,7 +515,7 @@ fn module_def_doctest(db: &RootDatabase, def: Definition) -> Option { if let Some(ty) = assoc_item.implementing_ty(db) { if let Some(adt) = ty.as_adt() { let name = adt.name(db); - let mut ty_args = ty.generic_parameters(db, edition).peekable(); + let mut ty_args = ty.generic_parameters(db, display_target).peekable(); format_to!(path, "{}", name.display(db, edition)); if ty_args.peek().is_some() { format_to!(path, "<{}>", ty_args.format_with(",", |ty, cb| cb(&ty))); diff --git a/src/tools/rust-analyzer/crates/ide/src/signature_help.rs b/src/tools/rust-analyzer/crates/ide/src/signature_help.rs index f99721160041c..b5468a5aee9ff 100644 --- a/src/tools/rust-analyzer/crates/ide/src/signature_help.rs +++ b/src/tools/rust-analyzer/crates/ide/src/signature_help.rs @@ -4,7 +4,9 @@ use std::collections::BTreeSet; use either::Either; -use hir::{AssocItem, GenericParam, HirDisplay, ModuleDef, PathResolution, Semantics, Trait}; +use hir::{ + AssocItem, DisplayTarget, GenericParam, HirDisplay, ModuleDef, PathResolution, Semantics, Trait, +}; use ide_db::{ active_parameter::{callable_for_node, generic_def_for_node}, documentation::{Documentation, HasDocs}, @@ -82,6 +84,7 @@ pub(crate) fn signature_help( let token = sema.descend_into_macros_single_exact(token); let edition = sema.attach_first_edition(file_id).map(|it| it.edition()).unwrap_or(Edition::CURRENT); + let display_target = sema.first_crate_or_default(file_id).to_display_target(db); for node in token.parent_ancestors() { match_ast! { @@ -91,49 +94,49 @@ pub(crate) fn signature_help( if cursor_outside { continue; } - return signature_help_for_call(&sema, arg_list, token, edition); + return signature_help_for_call(&sema, arg_list, token, edition, display_target); }, ast::GenericArgList(garg_list) => { let cursor_outside = garg_list.r_angle_token().as_ref() == Some(&token); if cursor_outside { continue; } - return signature_help_for_generics(&sema, garg_list, token, edition); + return signature_help_for_generics(&sema, garg_list, token, edition, display_target); }, ast::RecordExpr(record) => { let cursor_outside = record.record_expr_field_list().and_then(|list| list.r_curly_token()).as_ref() == Some(&token); if cursor_outside { continue; } - return signature_help_for_record_lit(&sema, record, token, edition); + return signature_help_for_record_lit(&sema, record, token, edition, display_target); }, ast::RecordPat(record) => { let cursor_outside = record.record_pat_field_list().and_then(|list| list.r_curly_token()).as_ref() == Some(&token); if cursor_outside { continue; } - return signature_help_for_record_pat(&sema, record, token, edition); + return signature_help_for_record_pat(&sema, record, token, edition, display_target); }, ast::TupleStructPat(tuple_pat) => { let cursor_outside = tuple_pat.r_paren_token().as_ref() == Some(&token); if cursor_outside { continue; } - return signature_help_for_tuple_struct_pat(&sema, tuple_pat, token, edition); + return signature_help_for_tuple_struct_pat(&sema, tuple_pat, token, edition, display_target); }, ast::TuplePat(tuple_pat) => { let cursor_outside = tuple_pat.r_paren_token().as_ref() == Some(&token); if cursor_outside { continue; } - return signature_help_for_tuple_pat(&sema, tuple_pat, token, edition); + return signature_help_for_tuple_pat(&sema, tuple_pat, token, display_target); }, ast::TupleExpr(tuple_expr) => { let cursor_outside = tuple_expr.r_paren_token().as_ref() == Some(&token); if cursor_outside { continue; } - return signature_help_for_tuple_expr(&sema, tuple_expr, token, edition); + return signature_help_for_tuple_expr(&sema, tuple_expr, token, display_target); }, _ => (), } @@ -158,6 +161,7 @@ fn signature_help_for_call( arg_list: ast::ArgList, token: SyntaxToken, edition: Edition, + display_target: DisplayTarget, ) -> Option { // Find the calling expression and its NameRef let mut nodes = arg_list.syntax().ancestors().skip(1); @@ -221,7 +225,7 @@ fn signature_help_for_call( res.signature.push('('); { if let Some((self_param, _)) = callable.receiver_param(db) { - format_to!(res.signature, "{}", self_param.display(db, edition)) + format_to!(res.signature, "{}", self_param.display(db, display_target)) } let mut buf = String::new(); for (idx, p) in callable.params().into_iter().enumerate() { @@ -242,9 +246,9 @@ fn signature_help_for_call( // (see FIXME in tests::impl_trait) and falling back on any unknowns. match (p.ty().contains_unknown(), fn_params.as_deref()) { (true, Some(fn_params)) => { - format_to!(buf, "{}", fn_params[idx].ty().display(db, edition)) + format_to!(buf, "{}", fn_params[idx].ty().display(db, display_target)) } - _ => format_to!(buf, "{}", p.ty().display(db, edition)), + _ => format_to!(buf, "{}", p.ty().display(db, display_target)), } res.push_call_param(&buf); } @@ -253,7 +257,7 @@ fn signature_help_for_call( let mut render = |ret_type: hir::Type| { if !ret_type.is_unit() { - format_to!(res.signature, " -> {}", ret_type.display(db, edition)); + format_to!(res.signature, " -> {}", ret_type.display(db, display_target)); } }; match callable.kind() { @@ -274,6 +278,7 @@ fn signature_help_for_generics( arg_list: ast::GenericArgList, token: SyntaxToken, edition: Edition, + display_target: DisplayTarget, ) -> Option { let (generics_def, mut active_parameter, first_arg_is_non_lifetime, variant) = generic_def_for_node(sema, &arg_list, &token)?; @@ -345,7 +350,7 @@ fn signature_help_for_generics( } buf.clear(); - format_to!(buf, "{}", param.display(db, edition)); + format_to!(buf, "{}", param.display(db, display_target)); res.push_generic_param(&buf); } if let hir::GenericDef::Trait(tr) = generics_def { @@ -400,6 +405,7 @@ fn signature_help_for_record_lit( record: ast::RecordExpr, token: SyntaxToken, edition: Edition, + display_target: DisplayTarget, ) -> Option { signature_help_for_record_( sema, @@ -412,6 +418,7 @@ fn signature_help_for_record_lit( .map(|(field, _, ty)| (field, ty)), token, edition, + display_target, ) } @@ -420,6 +427,7 @@ fn signature_help_for_record_pat( record: ast::RecordPat, token: SyntaxToken, edition: Edition, + display_target: DisplayTarget, ) -> Option { signature_help_for_record_( sema, @@ -431,6 +439,7 @@ fn signature_help_for_record_pat( .filter_map(|field| sema.resolve_record_pat_field(&field)), token, edition, + display_target, ) } @@ -439,6 +448,7 @@ fn signature_help_for_tuple_struct_pat( pat: ast::TupleStructPat, token: SyntaxToken, edition: Edition, + display_target: DisplayTarget, ) -> Option { let path = pat.path()?; let path_res = sema.resolve_path(&path)?; @@ -484,7 +494,7 @@ fn signature_help_for_tuple_struct_pat( token, pat.fields(), fields.into_iter().map(|it| it.ty(db)), - edition, + display_target, )) } @@ -492,7 +502,7 @@ fn signature_help_for_tuple_pat( sema: &Semantics<'_, RootDatabase>, pat: ast::TuplePat, token: SyntaxToken, - edition: Edition, + display_target: DisplayTarget, ) -> Option { let db = sema.db; let field_pats = pat.fields(); @@ -512,7 +522,7 @@ fn signature_help_for_tuple_pat( token, field_pats, fields.into_iter(), - edition, + display_target, )) } @@ -520,7 +530,7 @@ fn signature_help_for_tuple_expr( sema: &Semantics<'_, RootDatabase>, expr: ast::TupleExpr, token: SyntaxToken, - edition: Edition, + display_target: DisplayTarget, ) -> Option { let active_parameter = Some( expr.syntax() @@ -542,7 +552,7 @@ fn signature_help_for_tuple_expr( let fields = expr.original.tuple_fields(db); let mut buf = String::new(); for ty in fields { - format_to!(buf, "{}", ty.display_truncated(db, Some(20), edition)); + format_to!(buf, "{}", ty.display_truncated(db, Some(20), display_target)); res.push_call_param(&buf); buf.clear(); } @@ -557,6 +567,7 @@ fn signature_help_for_record_( fields2: impl Iterator, token: SyntaxToken, edition: Edition, + display_target: DisplayTarget, ) -> Option { let active_parameter = field_list_children .filter_map(NodeOrToken::into_token) @@ -617,7 +628,7 @@ fn signature_help_for_record_( buf, "{}: {}", name.display(db, edition), - ty.display_truncated(db, Some(20), edition) + ty.display_truncated(db, Some(20), display_target) ); res.push_record_field(&buf); buf.clear(); @@ -632,7 +643,7 @@ fn signature_help_for_record_( buf, "{}: {}", name.display(db, edition), - field.ty(db).display_truncated(db, Some(20), edition) + field.ty(db).display_truncated(db, Some(20), display_target) ); res.push_record_field(&buf); buf.clear(); @@ -648,7 +659,7 @@ fn signature_help_for_tuple_pat_ish( token: SyntaxToken, mut field_pats: AstChildren, fields: impl ExactSizeIterator, - edition: Edition, + display_target: DisplayTarget, ) -> SignatureHelp { let rest_pat = field_pats.find(|it| matches!(it, ast::Pat::RestPat(_))); let is_left_of_rest_pat = @@ -675,7 +686,7 @@ fn signature_help_for_tuple_pat_ish( let mut buf = String::new(); for ty in fields { - format_to!(buf, "{}", ty.display_truncated(db, Some(20), edition)); + format_to!(buf, "{}", ty.display_truncated(db, Some(20), display_target)); res.push_call_param(&buf); buf.clear(); } diff --git a/src/tools/rust-analyzer/crates/ide/src/static_index.rs b/src/tools/rust-analyzer/crates/ide/src/static_index.rs index 41957bad7e071..332aecf1e3cc5 100644 --- a/src/tools/rust-analyzer/crates/ide/src/static_index.rs +++ b/src/tools/rust-analyzer/crates/ide/src/static_index.rs @@ -3,7 +3,7 @@ use hir::{db::HirDatabase, Crate, HirFileIdExt, Module, Semantics}; use ide_db::{ - base_db::{SourceRootDatabase, VfsPath}, + base_db::{SourceDatabase, SourceRootDatabase, VfsPath}, defs::Definition, documentation::Documentation, famous_defs::FamousDefs, @@ -118,7 +118,11 @@ fn documentation_for_definition( def.docs( sema.db, famous_defs.as_ref(), - def.krate(sema.db).map(|it| it.edition(sema.db)).unwrap_or(Edition::CURRENT), + def.krate(sema.db) + .unwrap_or_else(|| { + (*sema.db.crate_graph().crates_in_topological_order().last().unwrap()).into() + }) + .to_display_target(sema.db), ) } @@ -173,6 +177,7 @@ impl StaticIndex<'_> { let root = sema.parse_guess_edition(file_id).syntax().clone(); let edition = sema.attach_first_edition(file_id).map(|it| it.edition()).unwrap_or(Edition::CURRENT); + let display_target = sema.first_crate_or_default(file_id).to_display_target(self.db); let tokens = root.descendants_with_tokens().filter_map(|it| match it { syntax::NodeOrToken::Node(_) => None, syntax::NodeOrToken::Token(it) => Some(it), @@ -213,6 +218,7 @@ impl StaticIndex<'_> { false, &hover_config, edition, + display_target, )), definition: def.try_to_nav(self.db).map(UpmappingResult::call_site).map(|it| { FileRange { file_id: it.file_id, range: it.focus_or_full_range() } @@ -222,7 +228,7 @@ impl StaticIndex<'_> { display_name: def .name(self.db) .map(|name| name.display(self.db, edition).to_string()), - signature: Some(def.label(self.db, edition)), + signature: Some(def.label(self.db, display_target)), kind: def_to_kind(self.db, def), }); self.def_map.insert(def, it); diff --git a/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs b/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs index edb83bc4eac4c..34bca7bce12cf 100644 --- a/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs +++ b/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs @@ -1,12 +1,11 @@ use std::fmt; -use hir::{Field, HirDisplay, Layout, Semantics, Type}; +use hir::{DisplayTarget, Field, HirDisplay, Layout, Semantics, Type}; use ide_db::{ defs::Definition, helpers::{get_definition, pick_best_token}, RootDatabase, }; -use span::Edition; use syntax::{AstNode, SyntaxKind}; use crate::FilePosition; @@ -84,10 +83,7 @@ pub(crate) fn view_memory_layout( ) -> Option { let sema = Semantics::new(db); let file = sema.parse_guess_edition(position.file_id); - let edition = sema - .attach_first_edition(position.file_id) - .map(|it| it.edition()) - .unwrap_or(Edition::CURRENT); + let display_target = sema.first_crate_or_default(position.file_id).to_display_target(db); let token = pick_best_token(file.syntax().token_at_offset(position.offset), |kind| match kind { SyntaxKind::IDENT => 3, @@ -114,7 +110,7 @@ pub(crate) fn view_memory_layout( ty: &Type, layout: &Layout, parent_idx: usize, - edition: Edition, + display_target: DisplayTarget, ) { let mut fields = ty .fields(db) @@ -145,7 +141,7 @@ pub(crate) fn view_memory_layout( if let Ok(child_layout) = child_ty.layout(db) { nodes.push(MemoryLayoutNode { item_name: field.name(db), - typename: child_ty.display(db, edition).to_string(), + typename: child_ty.display(db, display_target).to_string(), size: child_layout.size(), alignment: child_layout.align(), offset: match *field { @@ -161,7 +157,7 @@ pub(crate) fn view_memory_layout( item_name: field.name(db) + format!("(no layout data: {:?})", child_ty.layout(db).unwrap_err()) .as_ref(), - typename: child_ty.display(db, edition).to_string(), + typename: child_ty.display(db, display_target).to_string(), size: 0, offset: 0, alignment: 0, @@ -174,7 +170,7 @@ pub(crate) fn view_memory_layout( for (i, (_, child_ty)) in fields.iter().enumerate() { if let Ok(child_layout) = child_ty.layout(db) { - read_layout(nodes, db, child_ty, &child_layout, children_start + i, edition); + read_layout(nodes, db, child_ty, &child_layout, children_start + i, display_target); } } } @@ -192,7 +188,7 @@ pub(crate) fn view_memory_layout( def => def.name(db).map(|n| n.as_str().to_owned()).unwrap_or("[ROOT]".to_owned()), }; - let typename = ty.display(db, edition).to_string(); + let typename = ty.display(db, display_target).to_string(); let mut nodes = vec![MemoryLayoutNode { item_name, @@ -204,7 +200,7 @@ pub(crate) fn view_memory_layout( children_start: -1, children_len: 0, }]; - read_layout(&mut nodes, db, &ty, &layout, 0, edition); + read_layout(&mut nodes, db, &ty, &layout, 0, display_target); RecursiveMemoryLayout { nodes } }) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs index b9e4457fc98d8..dee76ee15c3df 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -390,6 +390,8 @@ impl flags::AnalysisStats { for &file_id in &file_ids { let sema = hir::Semantics::new(db); + let display_target = + sema.first_crate_or_default(file_id.file_id()).to_display_target(db); let parse = sema.parse_guess_edition(file_id.into()); let file_txt = db.file_text(file_id.into()); @@ -467,7 +469,7 @@ impl flags::AnalysisStats { prefer_absolute: false, allow_unstable: true, }, - Edition::LATEST, + display_target, ) .unwrap(); syntax_hit_found |= trim(&original_text) == trim(&generated); @@ -641,6 +643,7 @@ impl flags::AnalysisStats { for &body_id in bodies { let name = body_id.name(db).unwrap_or_else(Name::missing); let module = body_id.module(db); + let display_target = module.krate().to_display_target(db); let full_name = move || { module .krate() @@ -739,12 +742,12 @@ impl flags::AnalysisStats { start.col, end.line + 1, end.col, - ty.display(db, Edition::LATEST) + ty.display(db, display_target) )); } else { bar.println(format!( "unknown location: {}", - ty.display(db, Edition::LATEST) + ty.display(db, display_target) )); } } @@ -752,7 +755,7 @@ impl flags::AnalysisStats { println!( r#"{},type,"{}""#, location_csv_expr(db, vfs, &sm(), expr_id), - ty.display(db, Edition::LATEST) + ty.display(db, display_target) ); } if let Some(mismatch) = inference_result.type_mismatch_for_expr(expr_id) { @@ -767,15 +770,15 @@ impl flags::AnalysisStats { start.col, end.line + 1, end.col, - mismatch.expected.display(db, Edition::LATEST), - mismatch.actual.display(db, Edition::LATEST) + mismatch.expected.display(db, display_target), + mismatch.actual.display(db, display_target) )); } else { bar.println(format!( "{}: Expected {}, got {}", name.display(db, Edition::LATEST), - mismatch.expected.display(db, Edition::LATEST), - mismatch.actual.display(db, Edition::LATEST) + mismatch.expected.display(db, display_target), + mismatch.actual.display(db, display_target) )); } } @@ -783,8 +786,8 @@ impl flags::AnalysisStats { println!( r#"{},mismatch,"{}","{}""#, location_csv_expr(db, vfs, &sm(), expr_id), - mismatch.expected.display(db, Edition::LATEST), - mismatch.actual.display(db, Edition::LATEST) + mismatch.expected.display(db, display_target), + mismatch.actual.display(db, display_target) ); } } @@ -843,12 +846,12 @@ impl flags::AnalysisStats { start.col, end.line + 1, end.col, - ty.display(db, Edition::LATEST) + ty.display(db, display_target) )); } else { bar.println(format!( "unknown location: {}", - ty.display(db, Edition::LATEST) + ty.display(db, display_target) )); } } @@ -856,7 +859,7 @@ impl flags::AnalysisStats { println!( r#"{},type,"{}""#, location_csv_pat(db, vfs, &sm(), pat_id), - ty.display(db, Edition::LATEST) + ty.display(db, display_target) ); } if let Some(mismatch) = inference_result.type_mismatch_for_pat(pat_id) { @@ -870,15 +873,15 @@ impl flags::AnalysisStats { start.col, end.line + 1, end.col, - mismatch.expected.display(db, Edition::LATEST), - mismatch.actual.display(db, Edition::LATEST) + mismatch.expected.display(db, display_target), + mismatch.actual.display(db, display_target) )); } else { bar.println(format!( "{}: Expected {}, got {}", name.display(db, Edition::LATEST), - mismatch.expected.display(db, Edition::LATEST), - mismatch.actual.display(db, Edition::LATEST) + mismatch.expected.display(db, display_target), + mismatch.actual.display(db, display_target) )); } } @@ -886,8 +889,8 @@ impl flags::AnalysisStats { println!( r#"{},mismatch,"{}","{}""#, location_csv_pat(db, vfs, &sm(), pat_id), - mismatch.expected.display(db, Edition::LATEST), - mismatch.actual.display(db, Edition::LATEST) + mismatch.expected.display(db, display_target), + mismatch.actual.display(db, display_target) ); } } From 92de0ffd5cf7a9cf35618a0f66c20b55918c69d6 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Thu, 27 Feb 2025 14:30:10 +0200 Subject: [PATCH 24/53] Use correct crate for trait env in `render_const_scalar()` --- src/tools/rust-analyzer/crates/hir-ty/src/display.rs | 5 +---- src/tools/rust-analyzer/crates/ide/src/hover/tests.rs | 7 ++++++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs index 41152d90220ec..95ce36390d33d 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs @@ -680,10 +680,7 @@ fn render_const_scalar( memory_map: &MemoryMap, ty: &Ty, ) -> Result<(), HirDisplayError> { - // FIXME: We need to get krate from the final callers of the hir display - // infrastructure and have it here as a field on `f`. - let trait_env = - TraitEnvironment::empty(*f.db.crate_graph().crates_in_topological_order().last().unwrap()); + let trait_env = TraitEnvironment::empty(f.krate()); let ty = normalize(f.db, trait_env.clone(), ty.clone()); match ty.kind(Interner) { TyKind::Scalar(s) => match s { diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs index 964b1d7eb7dcd..6b470d921f7a7 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs @@ -10950,8 +10950,12 @@ pub struct ManuallyDrop$0 { #[test] fn projection_const() { + // This uses two crates, which have *no* relation between them, to test another thing: + // `render_const_scalar()` used to just use the last crate for the trait env, which will + // fail in this scenario. check( r#" +//- /foo.rs crate:foo pub trait PublicFlags { type Internal; } @@ -10967,12 +10971,13 @@ pub struct InternalBitFlags; impl PublicFlags for NoteDialects { type Internal = InternalBitFlags; } +//- /bar.rs crate:bar "#, expect![[r#" *CLAP* ```rust - ra_test_fixture::NoteDialects + foo::NoteDialects ``` ```rust From 0bd3229ef2714487b2b697334499f3e85ea9b611 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Sun, 2 Feb 2025 01:49:04 +0200 Subject: [PATCH 25/53] Warn the user when a rename will change the meaning of the program Specifically, when a rename of a local will change some code that refers it to refer another local, or some code that refer another local to refer to it. We do it by introducing a dummy edit with an annotation. I'm not a fond of this approach, but I don't think LSP has a better way. --- .../rust-analyzer/crates/hir-def/src/path.rs | 16 +- .../crates/hir-def/src/resolver.rs | 166 +++++++++++++++--- .../rust-analyzer/crates/hir/src/semantics.rs | 95 +++++++++- .../crates/ide-assists/src/tests.rs | 30 ++++ .../crates/ide-completion/src/render.rs | 2 + .../rust-analyzer/crates/ide-db/src/rename.rs | 36 +++- .../crates/ide-db/src/source_change.rs | 45 +++-- .../crates/ide-db/src/text_edit.rs | 15 +- .../rust-analyzer/crates/ide/src/rename.rs | 81 +++++++++ src/tools/rust-analyzer/crates/ide/src/ssr.rs | 7 + .../rust-analyzer/src/handlers/request.rs | 21 ++- .../crates/rust-analyzer/src/lsp/to_proto.rs | 54 +++++- 12 files changed, 509 insertions(+), 59 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/path.rs b/src/tools/rust-analyzer/crates/hir-def/src/path.rs index e6c2504d07a5a..713e7389736a0 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/path.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/path.rs @@ -57,7 +57,7 @@ pub enum Path { /// or type anchor, it is `Path::Normal` with the generics filled with `None` even if there are none (practically /// this is not a problem since many more paths have generics than a type anchor). BarePath(Interned), - /// `Path::Normal` may have empty generics and type anchor (but generic args will be filled with `None`). + /// `Path::Normal` will always have either generics or type anchor. Normal(NormalPath), /// A link to a lang item. It is used in desugaring of things like `it?`. We can show these /// links via a normal path since they might be private and not accessible in the usage place. @@ -208,11 +208,15 @@ impl Path { mod_path.segments()[..mod_path.segments().len() - 1].iter().cloned(), )); let qualifier_generic_args = &generic_args[..generic_args.len() - 1]; - Some(Path::Normal(NormalPath::new( - type_anchor, - qualifier_mod_path, - qualifier_generic_args.iter().cloned(), - ))) + if type_anchor.is_none() && qualifier_generic_args.iter().all(|it| it.is_none()) { + Some(Path::BarePath(qualifier_mod_path)) + } else { + Some(Path::Normal(NormalPath::new( + type_anchor, + qualifier_mod_path, + qualifier_generic_args.iter().cloned(), + ))) + } } Path::LangItem(..) => None, } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs index e5774b48044fe..a2e6e4cc04368 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs @@ -3,10 +3,11 @@ use std::{fmt, iter, mem}; use base_db::CrateId; use hir_expand::{name::Name, MacroDefId}; -use intern::sym; +use intern::{sym, Symbol}; use itertools::Itertools as _; use rustc_hash::FxHashSet; use smallvec::{smallvec, SmallVec}; +use span::SyntaxContextId; use triomphe::Arc; use crate::{ @@ -343,15 +344,7 @@ impl Resolver { } if n_segments <= 1 { - let mut hygiene_info = if !hygiene_id.is_root() { - let ctx = hygiene_id.lookup(db); - ctx.outer_expn.map(|expansion| { - let expansion = db.lookup_intern_macro_call(expansion); - (ctx.parent, expansion.def) - }) - } else { - None - }; + let mut hygiene_info = hygiene_info(db, hygiene_id); for scope in self.scopes() { match scope { Scope::ExprScope(scope) => { @@ -371,19 +364,7 @@ impl Resolver { } } Scope::MacroDefScope(macro_id) => { - if let Some((parent_ctx, label_macro_id)) = hygiene_info { - if label_macro_id == **macro_id { - // A macro is allowed to refer to variables from before its declaration. - // Therefore, if we got to the rib of its declaration, give up its hygiene - // and use its parent expansion. - let parent_ctx = db.lookup_intern_syntax_context(parent_ctx); - hygiene_id = HygieneId::new(parent_ctx.opaque_and_semitransparent); - hygiene_info = parent_ctx.outer_expn.map(|expansion| { - let expansion = db.lookup_intern_macro_call(expansion); - (parent_ctx.parent, expansion.def) - }); - } - } + handle_macro_def_scope(db, &mut hygiene_id, &mut hygiene_info, macro_id) } Scope::GenericParams { params, def } => { if let Some(id) = params.find_const_by_name(first_name, *def) { @@ -730,6 +711,107 @@ impl Resolver { }) } + /// Checks if we rename `renamed` (currently named `current_name`) to `new_name`, will the meaning of this reference + /// (that contains `current_name` path) change from `renamed` to some another variable (returned as `Some`). + pub fn rename_will_conflict_with_another_variable( + &self, + db: &dyn DefDatabase, + current_name: &Name, + current_name_as_path: &ModPath, + mut hygiene_id: HygieneId, + new_name: &Symbol, + to_be_renamed: BindingId, + ) -> Option { + let mut hygiene_info = hygiene_info(db, hygiene_id); + let mut will_be_resolved_to = None; + for scope in self.scopes() { + match scope { + Scope::ExprScope(scope) => { + for entry in scope.expr_scopes.entries(scope.scope_id) { + if entry.hygiene() == hygiene_id { + if entry.binding() == to_be_renamed { + // This currently resolves to our renamed variable, now `will_be_resolved_to` + // contains `Some` if the meaning will change or `None` if not. + return will_be_resolved_to; + } else if entry.name().symbol() == new_name { + will_be_resolved_to = Some(entry.binding()); + } + } + } + } + Scope::MacroDefScope(macro_id) => { + handle_macro_def_scope(db, &mut hygiene_id, &mut hygiene_info, macro_id) + } + Scope::GenericParams { params, def } => { + if params.find_const_by_name(current_name, *def).is_some() { + // It does not resolve to our renamed variable. + return None; + } + } + Scope::AdtScope(_) | Scope::ImplDefScope(_) => continue, + Scope::BlockScope(m) => { + if m.resolve_path_in_value_ns(db, current_name_as_path).is_some() { + // It does not resolve to our renamed variable. + return None; + } + } + } + } + // It does not resolve to our renamed variable. + None + } + + /// Checks if we rename `renamed` to `name`, will the meaning of this reference (that contains `name` path) change + /// from some other variable (returned as `Some`) to `renamed`. + pub fn rename_will_conflict_with_renamed( + &self, + db: &dyn DefDatabase, + name: &Name, + name_as_path: &ModPath, + mut hygiene_id: HygieneId, + to_be_renamed: BindingId, + ) -> Option { + let mut hygiene_info = hygiene_info(db, hygiene_id); + let mut will_resolve_to_renamed = false; + for scope in self.scopes() { + match scope { + Scope::ExprScope(scope) => { + for entry in scope.expr_scopes.entries(scope.scope_id) { + if entry.binding() == to_be_renamed { + will_resolve_to_renamed = true; + } else if entry.hygiene() == hygiene_id && entry.name() == name { + if will_resolve_to_renamed { + // This will resolve to the renamed variable before it resolves to the original variable. + return Some(entry.binding()); + } else { + // This will resolve to the original variable. + return None; + } + } + } + } + Scope::MacroDefScope(macro_id) => { + handle_macro_def_scope(db, &mut hygiene_id, &mut hygiene_info, macro_id) + } + Scope::GenericParams { params, def } => { + if params.find_const_by_name(name, *def).is_some() { + // Here and below, it might actually resolve to our renamed variable - in which case it'll + // hide the generic parameter or some other thing (not a variable). We don't check for that + // because due to naming conventions, it is rare that variable will shadow a non-variable. + return None; + } + } + Scope::AdtScope(_) | Scope::ImplDefScope(_) => continue, + Scope::BlockScope(m) => { + if m.resolve_path_in_value_ns(db, name_as_path).is_some() { + return None; + } + } + } + } + None + } + /// `expr_id` is required to be an expression id that comes after the top level expression scope in the given resolver #[must_use] pub fn update_to_inner_scope( @@ -795,6 +877,44 @@ impl Resolver { } } +#[inline] +fn handle_macro_def_scope( + db: &dyn DefDatabase, + hygiene_id: &mut HygieneId, + hygiene_info: &mut Option<(SyntaxContextId, MacroDefId)>, + macro_id: &MacroDefId, +) { + if let Some((parent_ctx, label_macro_id)) = hygiene_info { + if label_macro_id == macro_id { + // A macro is allowed to refer to variables from before its declaration. + // Therefore, if we got to the rib of its declaration, give up its hygiene + // and use its parent expansion. + let parent_ctx = db.lookup_intern_syntax_context(*parent_ctx); + *hygiene_id = HygieneId::new(parent_ctx.opaque_and_semitransparent); + *hygiene_info = parent_ctx.outer_expn.map(|expansion| { + let expansion = db.lookup_intern_macro_call(expansion); + (parent_ctx.parent, expansion.def) + }); + } + } +} + +#[inline] +fn hygiene_info( + db: &dyn DefDatabase, + hygiene_id: HygieneId, +) -> Option<(SyntaxContextId, MacroDefId)> { + if !hygiene_id.is_root() { + let ctx = hygiene_id.lookup(db); + ctx.outer_expn.map(|expansion| { + let expansion = db.lookup_intern_macro_call(expansion); + (ctx.parent, expansion.def) + }) + } else { + None + } +} + pub struct UpdateGuard(usize); impl Resolver { diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index 1b8531209c1b4..b0c2feaac1d12 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -12,8 +12,8 @@ use std::{ use either::Either; use hir_def::{ - expr_store::ExprOrPatSource, - hir::{Expr, ExprOrPatId}, + expr_store::{Body, ExprOrPatSource}, + hir::{BindingId, Expr, ExprId, ExprOrPatId, Pat}, lower::LowerCtx, nameres::{MacroSubNs, ModuleOrigin}, path::ModPath, @@ -629,6 +629,31 @@ impl<'db> SemanticsImpl<'db> { ) } + /// Checks if renaming `renamed` to `new_name` may introduce conflicts with other locals, + /// and returns the conflicting locals. + pub fn rename_conflicts(&self, to_be_renamed: &Local, new_name: &str) -> Vec { + let body = self.db.body(to_be_renamed.parent); + let resolver = to_be_renamed.parent.resolver(self.db.upcast()); + let starting_expr = + body.binding_owners.get(&to_be_renamed.binding_id).copied().unwrap_or(body.body_expr); + let mut visitor = RenameConflictsVisitor { + body: &body, + conflicts: FxHashSet::default(), + db: self.db, + new_name: Symbol::intern(new_name), + old_name: to_be_renamed.name(self.db).symbol().clone(), + owner: to_be_renamed.parent, + to_be_renamed: to_be_renamed.binding_id, + resolver, + }; + visitor.rename_conflicts(starting_expr); + visitor + .conflicts + .into_iter() + .map(|binding_id| Local { parent: to_be_renamed.parent, binding_id }) + .collect() + } + /// Retrieves all the formatting parts of the format_args! (or `asm!`) template string. pub fn as_format_args_parts( &self, @@ -2094,3 +2119,69 @@ impl ops::Deref for VisibleTraits { &self.0 } } + +struct RenameConflictsVisitor<'a> { + db: &'a dyn HirDatabase, + owner: DefWithBodyId, + resolver: Resolver, + body: &'a Body, + to_be_renamed: BindingId, + new_name: Symbol, + old_name: Symbol, + conflicts: FxHashSet, +} + +impl RenameConflictsVisitor<'_> { + fn resolve_path(&mut self, node: ExprOrPatId, path: &Path) { + if let Path::BarePath(path) = path { + if let Some(name) = path.as_ident() { + if *name.symbol() == self.new_name { + if let Some(conflicting) = self.resolver.rename_will_conflict_with_renamed( + self.db.upcast(), + name, + path, + self.body.expr_or_pat_path_hygiene(node), + self.to_be_renamed, + ) { + self.conflicts.insert(conflicting); + } + } else if *name.symbol() == self.old_name { + if let Some(conflicting) = + self.resolver.rename_will_conflict_with_another_variable( + self.db.upcast(), + name, + path, + self.body.expr_or_pat_path_hygiene(node), + &self.new_name, + self.to_be_renamed, + ) + { + self.conflicts.insert(conflicting); + } + } + } + } + } + + fn rename_conflicts(&mut self, expr: ExprId) { + match &self.body[expr] { + Expr::Path(path) => { + let guard = self.resolver.update_to_inner_scope(self.db.upcast(), self.owner, expr); + self.resolve_path(expr.into(), path); + self.resolver.reset_to_guard(guard); + } + &Expr::Assignment { target, .. } => { + let guard = self.resolver.update_to_inner_scope(self.db.upcast(), self.owner, expr); + self.body.walk_pats(target, &mut |pat| { + if let Pat::Path(path) = &self.body[pat] { + self.resolve_path(pat.into(), path); + } + }); + self.resolver.reset_to_guard(guard); + } + _ => {} + } + + self.body.walk_child_exprs(expr, |expr| self.rename_conflicts(expr)); + } +} diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs index 11aeb21c77e5e..7d7012c462222 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs @@ -710,18 +710,22 @@ pub fn test_some_range(a: int) -> bool { Indel { insert: "let", delete: 45..47, + annotation: None, }, Indel { insert: "var_name", delete: 48..60, + annotation: None, }, Indel { insert: "=", delete: 61..81, + annotation: None, }, Indel { insert: "5;\n if let 2..6 = var_name {\n true\n } else {\n false\n }", delete: 82..108, + annotation: None, }, ], }, @@ -739,6 +743,8 @@ pub fn test_some_range(a: int) -> bool { }, file_system_edits: [], is_snippet: true, + annotations: {}, + next_annotation_id: 0, }, ), command: Some( @@ -839,18 +845,22 @@ pub fn test_some_range(a: int) -> bool { Indel { insert: "let", delete: 45..47, + annotation: None, }, Indel { insert: "var_name", delete: 48..60, + annotation: None, }, Indel { insert: "=", delete: 61..81, + annotation: None, }, Indel { insert: "5;\n if let 2..6 = var_name {\n true\n } else {\n false\n }", delete: 82..108, + annotation: None, }, ], }, @@ -868,6 +878,8 @@ pub fn test_some_range(a: int) -> bool { }, file_system_edits: [], is_snippet: true, + annotations: {}, + next_annotation_id: 0, }, ), command: Some( @@ -902,22 +914,27 @@ pub fn test_some_range(a: int) -> bool { Indel { insert: "const", delete: 45..47, + annotation: None, }, Indel { insert: "VAR_NAME:", delete: 48..60, + annotation: None, }, Indel { insert: "i32", delete: 61..81, + annotation: None, }, Indel { insert: "=", delete: 82..86, + annotation: None, }, Indel { insert: "5;\n if let 2..6 = VAR_NAME {\n true\n } else {\n false\n }", delete: 87..108, + annotation: None, }, ], }, @@ -935,6 +952,8 @@ pub fn test_some_range(a: int) -> bool { }, file_system_edits: [], is_snippet: true, + annotations: {}, + next_annotation_id: 0, }, ), command: Some( @@ -969,22 +988,27 @@ pub fn test_some_range(a: int) -> bool { Indel { insert: "static", delete: 45..47, + annotation: None, }, Indel { insert: "VAR_NAME:", delete: 48..60, + annotation: None, }, Indel { insert: "i32", delete: 61..81, + annotation: None, }, Indel { insert: "=", delete: 82..86, + annotation: None, }, Indel { insert: "5;\n if let 2..6 = VAR_NAME {\n true\n } else {\n false\n }", delete: 87..108, + annotation: None, }, ], }, @@ -1002,6 +1026,8 @@ pub fn test_some_range(a: int) -> bool { }, file_system_edits: [], is_snippet: true, + annotations: {}, + next_annotation_id: 0, }, ), command: Some( @@ -1036,10 +1062,12 @@ pub fn test_some_range(a: int) -> bool { Indel { insert: "fun_name()", delete: 59..60, + annotation: None, }, Indel { insert: "\n\nfn fun_name() -> i32 {\n 5\n}", delete: 110..110, + annotation: None, }, ], }, @@ -1057,6 +1085,8 @@ pub fn test_some_range(a: int) -> bool { }, file_system_edits: [], is_snippet: true, + annotations: {}, + next_annotation_id: 0, }, ), command: None, diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs index 4f6c4cb663930..af644d0fda78f 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs @@ -2686,10 +2686,12 @@ fn foo(f: Foo) { let _: &u32 = f.b$0 } Indel { insert: "(", delete: 107..107, + annotation: None, }, Indel { insert: "qux)()", delete: 109..110, + annotation: None, }, ], }, diff --git a/src/tools/rust-analyzer/crates/ide-db/src/rename.rs b/src/tools/rust-analyzer/crates/ide-db/src/rename.rs index 59914bedde434..1633065f65217 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/rename.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/rename.rs @@ -22,7 +22,10 @@ //! Our current behavior is ¯\_(ツ)_/¯. use std::fmt; -use crate::text_edit::{TextEdit, TextEditBuilder}; +use crate::{ + source_change::ChangeAnnotation, + text_edit::{TextEdit, TextEditBuilder}, +}; use base_db::AnchoredPathBuf; use either::Either; use hir::{FieldSource, FileRange, HirFileIdExt, InFile, ModuleSource, Semantics}; @@ -365,10 +368,12 @@ fn rename_reference( })); let mut insert_def_edit = |def| { - let (file_id, edit) = source_edit_from_def(sema, def, new_name)?; + let (file_id, edit) = source_edit_from_def(sema, def, new_name, &mut source_change)?; source_change.insert_source_edit(file_id, edit); Ok(()) }; + // This needs to come after the references edits, because we change the annotation of existing edits + // if a conflict is detected. insert_def_edit(def)?; Ok(source_change) } @@ -537,6 +542,7 @@ fn source_edit_from_def( sema: &Semantics<'_, RootDatabase>, def: Definition, new_name: &str, + source_change: &mut SourceChange, ) -> Result<(FileId, TextEdit)> { let new_name_edition_aware = |new_name: &str, file_id: EditionedFileId| { if is_raw_identifier(new_name, file_id.edition()) { @@ -548,6 +554,23 @@ fn source_edit_from_def( let mut edit = TextEdit::builder(); if let Definition::Local(local) = def { let mut file_id = None; + + let conflict_annotation = if !sema.rename_conflicts(&local, new_name).is_empty() { + Some( + source_change.insert_annotation(ChangeAnnotation { + label: "This rename will change the program's meaning".to_owned(), + needs_confirmation: true, + description: Some( + "Some variable(s) will shadow the renamed variable \ + or be shadowed by it if the rename is performed" + .to_owned(), + ), + }), + ) + } else { + None + }; + for source in local.sources(sema.db) { let source = match source.source.clone().original_ast_node_rooted(sema.db) { Some(source) => source, @@ -611,8 +634,15 @@ fn source_edit_from_def( } } } + let mut edit = edit.finish(); + + for (edit, _) in source_change.source_file_edits.values_mut() { + edit.set_annotation(conflict_annotation); + } + edit.set_annotation(conflict_annotation); + let Some(file_id) = file_id else { bail!("No file available to rename") }; - return Ok((EditionedFileId::file_id(file_id), edit.finish())); + return Ok((EditionedFileId::file_id(file_id), edit)); } let FileRange { file_id, range } = def .range_for_rename(sema) diff --git a/src/tools/rust-analyzer/crates/ide-db/src/source_change.rs b/src/tools/rust-analyzer/crates/ide-db/src/source_change.rs index 34642d7eaf9db..b4d0b0dc9f0af 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/source_change.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/source_change.rs @@ -3,7 +3,7 @@ //! //! It can be viewed as a dual for `Change`. -use std::{collections::hash_map::Entry, iter, mem}; +use std::{collections::hash_map::Entry, fmt, iter, mem}; use crate::text_edit::{TextEdit, TextEditBuilder}; use crate::{assists::Command, syntax_helpers::tree_diff::diff, SnippetCap}; @@ -18,23 +18,33 @@ use syntax::{ AstNode, SyntaxElement, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange, TextSize, }; +/// An annotation ID associated with an indel, to describe changes. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct ChangeAnnotationId(u32); + +impl fmt::Display for ChangeAnnotationId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&self.0, f) + } +} + +#[derive(Debug, Clone)] +pub struct ChangeAnnotation { + pub label: String, + pub needs_confirmation: bool, + pub description: Option, +} + #[derive(Default, Debug, Clone)] pub struct SourceChange { pub source_file_edits: IntMap)>, pub file_system_edits: Vec, pub is_snippet: bool, + pub annotations: FxHashMap, + next_annotation_id: u32, } impl SourceChange { - /// Creates a new SourceChange with the given label - /// from the edits. - pub fn from_edits( - source_file_edits: IntMap)>, - file_system_edits: Vec, - ) -> Self { - SourceChange { source_file_edits, file_system_edits, is_snippet: false } - } - pub fn from_text_edit(file_id: impl Into, edit: TextEdit) -> Self { SourceChange { source_file_edits: iter::once((file_id.into(), (edit, None))).collect(), @@ -42,6 +52,13 @@ impl SourceChange { } } + pub fn insert_annotation(&mut self, annotation: ChangeAnnotation) -> ChangeAnnotationId { + let id = ChangeAnnotationId(self.next_annotation_id); + self.next_annotation_id += 1; + self.annotations.insert(id, annotation); + id + } + /// Inserts a [`TextEdit`] for the given [`FileId`]. This properly handles merging existing /// edits for a file if some already exist. pub fn insert_source_edit(&mut self, file_id: impl Into, edit: TextEdit) { @@ -120,7 +137,12 @@ impl From> for SourceChange { fn from(source_file_edits: IntMap) -> SourceChange { let source_file_edits = source_file_edits.into_iter().map(|(file_id, edit)| (file_id, (edit, None))).collect(); - SourceChange { source_file_edits, file_system_edits: Vec::new(), is_snippet: false } + SourceChange { + source_file_edits, + file_system_edits: Vec::new(), + is_snippet: false, + ..SourceChange::default() + } } } @@ -482,6 +504,7 @@ impl From for SourceChange { source_file_edits: Default::default(), file_system_edits: vec![edit], is_snippet: false, + ..SourceChange::default() } } } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/text_edit.rs b/src/tools/rust-analyzer/crates/ide-db/src/text_edit.rs index 0c675f0619f2a..b59010f2f8c83 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/text_edit.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/text_edit.rs @@ -8,6 +8,8 @@ use itertools::Itertools; pub use span::{TextRange, TextSize}; use std::cmp::max; +use crate::source_change::ChangeAnnotationId; + /// `InsertDelete` -- a single "atomic" change to text /// /// Must not overlap with other `InDel`s @@ -16,6 +18,7 @@ pub struct Indel { pub insert: String, /// Refers to offsets in the original text pub delete: TextRange, + pub annotation: Option, } #[derive(Default, Debug, Clone)] @@ -37,7 +40,7 @@ impl Indel { Indel::replace(range, String::new()) } pub fn replace(range: TextRange, replace_with: String) -> Indel { - Indel { delete: range, insert: replace_with } + Indel { delete: range, insert: replace_with, annotation: None } } pub fn apply(&self, text: &mut String) { @@ -138,6 +141,14 @@ impl TextEdit { } Some(res) } + + pub fn set_annotation(&mut self, annotation: Option) { + if annotation.is_some() { + for indel in &mut self.indels { + indel.annotation = annotation; + } + } + } } impl IntoIterator for TextEdit { @@ -180,7 +191,7 @@ impl TextEditBuilder { pub fn invalidates_offset(&self, offset: TextSize) -> bool { self.indels.iter().any(|indel| indel.delete.contains_inclusive(offset)) } - fn indel(&mut self, indel: Indel) { + pub fn indel(&mut self, indel: Indel) { self.indels.push(indel); if self.indels.len() <= 16 { assert_disjoint_or_equal(&mut self.indels); diff --git a/src/tools/rust-analyzer/crates/ide/src/rename.rs b/src/tools/rust-analyzer/crates/ide/src/rename.rs index 3e8295e3f08ee..d0e1c2097a7a9 100644 --- a/src/tools/rust-analyzer/crates/ide/src/rename.rs +++ b/src/tools/rust-analyzer/crates/ide/src/rename.rs @@ -446,6 +446,7 @@ mod tests { use expect_test::{expect, Expect}; use ide_db::source_change::SourceChange; use ide_db::text_edit::TextEdit; + use itertools::Itertools; use stdx::trim_indent; use test_utils::assert_eq_text; @@ -496,6 +497,31 @@ mod tests { }; } + #[track_caller] + fn check_conflicts(new_name: &str, #[rust_analyzer::rust_fixture] ra_fixture: &str) { + let (analysis, position, conflicts) = fixture::annotations(ra_fixture); + let source_change = analysis.rename(position, new_name).unwrap().unwrap(); + let expected_conflicts = conflicts + .into_iter() + .map(|(file_range, _)| (file_range.file_id, file_range.range)) + .sorted_unstable_by_key(|(file_id, range)| (*file_id, range.start())) + .collect_vec(); + let found_conflicts = source_change + .source_file_edits + .iter() + .flat_map(|(file_id, (edit, _))| { + edit.into_iter() + .filter(|edit| edit.annotation.is_some()) + .map(move |edit| (*file_id, edit.delete)) + }) + .sorted_unstable_by_key(|(file_id, range)| (*file_id, range.start())) + .collect_vec(); + assert_eq!( + expected_conflicts, found_conflicts, + "rename conflicts mismatch: {source_change:#?}" + ); + } + fn check_expect( new_name: &str, #[rust_analyzer::rust_fixture] ra_fixture: &str, @@ -547,6 +573,37 @@ mod tests { ) } + #[test] + fn rename_will_shadow() { + check_conflicts( + "new_name", + r#" +fn foo() { + let mut new_name = 123; + let old_name$0 = 456; + // ^^^^^^^^ + new_name = 789 + new_name; +} + "#, + ); + } + + #[test] + fn rename_will_be_shadowed() { + check_conflicts( + "new_name", + r#" +fn foo() { + let mut old_name$0 = 456; + // ^^^^^^^^ + let new_name = 123; + old_name = 789 + old_name; + // ^^^^^^^^ ^^^^^^^^ +} + "#, + ); + } + #[test] fn test_prepare_rename_namelikes() { check_prepare(r"fn name$0<'lifetime>() {}", expect![[r#"3..7: name"#]]); @@ -1024,6 +1081,7 @@ mod foo$0; Indel { insert: "foo2", delete: 4..7, + annotation: None, }, ], ), @@ -1071,6 +1129,7 @@ use crate::foo$0::FooContent; Indel { insert: "quux", delete: 8..11, + annotation: None, }, ], ), @@ -1082,6 +1141,7 @@ use crate::foo$0::FooContent; Indel { insert: "quux", delete: 11..14, + annotation: None, }, ], ), @@ -1123,6 +1183,7 @@ mod fo$0o; Indel { insert: "foo2", delete: 4..7, + annotation: None, }, ], ), @@ -1171,6 +1232,7 @@ mod outer { mod fo$0o; } Indel { insert: "bar", delete: 16..19, + annotation: None, }, ], ), @@ -1242,6 +1304,7 @@ pub mod foo$0; Indel { insert: "foo2", delete: 27..30, + annotation: None, }, ], ), @@ -1253,6 +1316,7 @@ pub mod foo$0; Indel { insert: "foo2", delete: 8..11, + annotation: None, }, ], ), @@ -1308,6 +1372,7 @@ mod quux; Indel { insert: "foo2", delete: 4..7, + annotation: None, }, ], ), @@ -1441,10 +1506,12 @@ pub fn baz() {} Indel { insert: "r#fn", delete: 4..7, + annotation: None, }, Indel { insert: "r#fn", delete: 22..25, + annotation: None, }, ], ), @@ -1509,10 +1576,12 @@ pub fn baz() {} Indel { insert: "foo", delete: 4..8, + annotation: None, }, Indel { insert: "foo", delete: 23..27, + annotation: None, }, ], ), @@ -1574,6 +1643,7 @@ fn bar() { Indel { insert: "dyn", delete: 7..10, + annotation: None, }, ], ), @@ -1585,6 +1655,7 @@ fn bar() { Indel { insert: "r#dyn", delete: 18..21, + annotation: None, }, ], ), @@ -1614,6 +1685,7 @@ fn bar() { Indel { insert: "r#dyn", delete: 7..10, + annotation: None, }, ], ), @@ -1625,6 +1697,7 @@ fn bar() { Indel { insert: "dyn", delete: 18..21, + annotation: None, }, ], ), @@ -1654,6 +1727,7 @@ fn bar() { Indel { insert: "r#dyn", delete: 7..10, + annotation: None, }, ], ), @@ -1665,6 +1739,7 @@ fn bar() { Indel { insert: "dyn", delete: 18..21, + annotation: None, }, ], ), @@ -1701,10 +1776,12 @@ fn bar() { Indel { insert: "abc", delete: 7..10, + annotation: None, }, Indel { insert: "abc", delete: 32..35, + annotation: None, }, ], ), @@ -1716,6 +1793,7 @@ fn bar() { Indel { insert: "abc", delete: 18..23, + annotation: None, }, ], ), @@ -1749,10 +1827,12 @@ fn bar() { Indel { insert: "abc", delete: 7..12, + annotation: None, }, Indel { insert: "abc", delete: 34..39, + annotation: None, }, ], ), @@ -1764,6 +1844,7 @@ fn bar() { Indel { insert: "abc", delete: 18..21, + annotation: None, }, ], ), diff --git a/src/tools/rust-analyzer/crates/ide/src/ssr.rs b/src/tools/rust-analyzer/crates/ide/src/ssr.rs index 77a011cac1983..90e350949b81f 100644 --- a/src/tools/rust-analyzer/crates/ide/src/ssr.rs +++ b/src/tools/rust-analyzer/crates/ide/src/ssr.rs @@ -139,6 +139,7 @@ mod tests { Indel { insert: "3", delete: 33..34, + annotation: None, }, ], }, @@ -147,6 +148,8 @@ mod tests { }, file_system_edits: [], is_snippet: false, + annotations: {}, + next_annotation_id: 0, }, ), command: None, @@ -179,6 +182,7 @@ mod tests { Indel { insert: "3", delete: 33..34, + annotation: None, }, ], }, @@ -192,6 +196,7 @@ mod tests { Indel { insert: "3", delete: 11..12, + annotation: None, }, ], }, @@ -200,6 +205,8 @@ mod tests { }, file_system_edits: [], is_snippet: false, + annotations: {}, + next_annotation_id: 0, }, ), command: None, diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs index 4ab96e9e2d58e..68b2d6b696289 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs @@ -427,7 +427,12 @@ pub(crate) fn handle_on_enter( Some(it) => it, }; let line_index = snap.file_line_index(position.file_id)?; - let edit = to_proto::snippet_text_edit_vec(&line_index, true, edit); + let edit = to_proto::snippet_text_edit_vec( + &line_index, + true, + edit, + snap.config.change_annotation_support(), + ); Ok(Some(edit)) } @@ -464,7 +469,12 @@ pub(crate) fn handle_on_type_formatting( let (_, (text_edit, snippet_edit)) = edit.source_file_edits.into_iter().next().unwrap(); stdx::always!(snippet_edit.is_none(), "on type formatting shouldn't use structured snippets"); - let change = to_proto::snippet_text_edit_vec(&line_index, edit.is_snippet, text_edit); + let change = to_proto::snippet_text_edit_vec( + &line_index, + edit.is_snippet, + text_edit, + snap.config.change_annotation_support(), + ); Ok(Some(change)) } @@ -2025,7 +2035,12 @@ pub(crate) fn handle_move_item( match snap.analysis.move_item(range, direction)? { Some(text_edit) => { let line_index = snap.file_line_index(file_id)?; - Ok(to_proto::snippet_text_edit_vec(&line_index, true, text_edit)) + Ok(to_proto::snippet_text_edit_vec( + &line_index, + true, + text_edit, + snap.config.change_annotation_support(), + )) } None => Ok(vec![]), } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs index 3c206f47db5e5..6db7bcb11102c 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs @@ -200,7 +200,10 @@ pub(crate) fn snippet_text_edit( line_index: &LineIndex, is_snippet: bool, indel: Indel, + client_supports_annotations: bool, ) -> lsp_ext::SnippetTextEdit { + let annotation_id = + indel.annotation.filter(|_| client_supports_annotations).map(|it| it.to_string()); let text_edit = text_edit(line_index, indel); let insert_text_format = if is_snippet { Some(lsp_types::InsertTextFormat::SNIPPET) } else { None }; @@ -208,7 +211,7 @@ pub(crate) fn snippet_text_edit( range: text_edit.range, new_text: text_edit.new_text, insert_text_format, - annotation_id: None, + annotation_id, } } @@ -223,10 +226,13 @@ pub(crate) fn snippet_text_edit_vec( line_index: &LineIndex, is_snippet: bool, text_edit: TextEdit, + clients_support_annotations: bool, ) -> Vec { text_edit .into_iter() - .map(|indel| self::snippet_text_edit(line_index, is_snippet, indel)) + .map(|indel| { + self::snippet_text_edit(line_index, is_snippet, indel, clients_support_annotations) + }) .collect() } @@ -1072,6 +1078,7 @@ fn merge_text_and_snippet_edits( line_index: &LineIndex, edit: TextEdit, snippet_edit: SnippetEdit, + client_supports_annotations: bool, ) -> Vec { let mut edits: Vec = vec![]; let mut snippets = snippet_edit.into_edit_ranges().into_iter().peekable(); @@ -1120,7 +1127,12 @@ fn merge_text_and_snippet_edits( edits.push(snippet_text_edit( line_index, true, - Indel { insert: format!("${snippet_index}"), delete: snippet_range }, + Indel { + insert: format!("${snippet_index}"), + delete: snippet_range, + annotation: None, + }, + client_supports_annotations, )) } @@ -1178,12 +1190,22 @@ fn merge_text_and_snippet_edits( edits.push(snippet_text_edit( line_index, true, - Indel { insert: new_text, delete: current_indel.delete }, + Indel { + insert: new_text, + delete: current_indel.delete, + annotation: current_indel.annotation, + }, + client_supports_annotations, )) } else { // snippet edit was beyond the current one // since it wasn't consumed, it's available for the next pass - edits.push(snippet_text_edit(line_index, false, current_indel)); + edits.push(snippet_text_edit( + line_index, + false, + current_indel, + client_supports_annotations, + )); } // update the final source -> initial source mapping offset @@ -1208,7 +1230,8 @@ fn merge_text_and_snippet_edits( snippet_text_edit( line_index, true, - Indel { insert: format!("${snippet_index}"), delete: snippet_range }, + Indel { insert: format!("${snippet_index}"), delete: snippet_range, annotation: None }, + client_supports_annotations, ) })); @@ -1224,10 +1247,13 @@ pub(crate) fn snippet_text_document_edit( ) -> Cancellable { let text_document = optional_versioned_text_document_identifier(snap, file_id); let line_index = snap.file_line_index(file_id)?; + let client_supports_annotations = snap.config.change_annotation_support(); let mut edits = if let Some(snippet_edit) = snippet_edit { - merge_text_and_snippet_edits(&line_index, edit, snippet_edit) + merge_text_and_snippet_edits(&line_index, edit, snippet_edit, client_supports_annotations) } else { - edit.into_iter().map(|it| snippet_text_edit(&line_index, is_snippet, it)).collect() + edit.into_iter() + .map(|it| snippet_text_edit(&line_index, is_snippet, it, client_supports_annotations)) + .collect() }; if snap.analysis.is_library_file(file_id)? && snap.config.change_annotation_support() { @@ -1348,6 +1374,16 @@ pub(crate) fn snippet_workspace_edit( )), }, )) + .chain(source_change.annotations.into_iter().map(|(id, annotation)| { + ( + id.to_string(), + lsp_types::ChangeAnnotation { + label: annotation.label, + description: annotation.description, + needs_confirmation: Some(annotation.needs_confirmation), + }, + ) + })) .collect(), ) } @@ -2023,7 +2059,7 @@ fn bar(_: usize) {} encoding: PositionEncoding::Utf8, }; - let res = merge_text_and_snippet_edits(&line_index, edit, snippets); + let res = merge_text_and_snippet_edits(&line_index, edit, snippets, true); // Ensure that none of the ranges overlap { From b58fc9c2bc92d453d8d89269bbd2b93c6a2e8f69 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Fri, 7 Mar 2025 00:16:54 +0200 Subject: [PATCH 26/53] Mark `rust-analyzer.showSyntaxTree` config option as requiring server restart We register the provider when we start the server. It confused me why I set the option and it didn't work, so probably better to have it hint people. --- src/tools/rust-analyzer/editors/code/src/config.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/rust-analyzer/editors/code/src/config.ts b/src/tools/rust-analyzer/editors/code/src/config.ts index 2ae3291345200..896b3c10cbf5d 100644 --- a/src/tools/rust-analyzer/editors/code/src/config.ts +++ b/src/tools/rust-analyzer/editors/code/src/config.ts @@ -27,6 +27,7 @@ export class Config { "server", "files", "cfg", + "showSyntaxTree", ].map((opt) => `${this.rootSection}.${opt}`); private readonly requiresWindowReloadOpts = ["testExplorer"].map( From f68fd669f3d7a0847b5c2f3b789b6c95db0acdc1 Mon Sep 17 00:00:00 2001 From: Tongjun Gao Date: Fri, 7 Mar 2025 13:24:14 +0800 Subject: [PATCH 27/53] Fix logical error in relevance scoring implementation --- src/tools/rust-analyzer/crates/ide-completion/src/item.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs index ea52d69c7952e..294fbde1b6d5b 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs @@ -252,14 +252,14 @@ impl CompletionRelevance { /// Provides a relevance score. Higher values are more relevant. /// /// The absolute value of the relevance score is not meaningful, for - /// example a value of 0 doesn't mean "not relevant", rather + /// example a value of (!(0 as u32) / 2) doesn't mean "not relevant", rather /// it means "least relevant". The score value should only be used /// for relative ordering. /// /// See is_relevant if you need to make some judgement about score /// in an absolute sense. pub fn score(self) -> u32 { - let mut score = !0 / 2; + let mut score = !(0 as u32) / 2; let CompletionRelevance { exact_name_match, type_match, @@ -350,7 +350,7 @@ impl CompletionRelevance { /// some threshold such that we think it is especially likely /// to be relevant. pub fn is_relevant(&self) -> bool { - self.score() > (!0 / 2) + self.score() > !(0 as u32) / 2 } } From 16878eb02a27e5d8a4520851d88c33bd34170695 Mon Sep 17 00:00:00 2001 From: Tongjun Gao Date: Fri, 7 Mar 2025 14:44:57 +0800 Subject: [PATCH 28/53] Refactor relevance scoring to use a named constant BASE_SCORE Replace magic number with a named constant for improved readability and maintainability of the scoring logic --- src/tools/rust-analyzer/crates/ide-completion/src/item.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs index 294fbde1b6d5b..8d6dc4c801301 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs @@ -252,14 +252,16 @@ impl CompletionRelevance { /// Provides a relevance score. Higher values are more relevant. /// /// The absolute value of the relevance score is not meaningful, for - /// example a value of (!(0 as u32) / 2) doesn't mean "not relevant", rather + /// example a value of BASE_SCORE doesn't mean "not relevant", rather /// it means "least relevant". The score value should only be used /// for relative ordering. /// /// See is_relevant if you need to make some judgement about score /// in an absolute sense. + const BASE_SCORE: u32 = u32::MAX / 2; + pub fn score(self) -> u32 { - let mut score = !(0 as u32) / 2; + let mut score = Self::BASE_SCORE; let CompletionRelevance { exact_name_match, type_match, @@ -350,7 +352,7 @@ impl CompletionRelevance { /// some threshold such that we think it is especially likely /// to be relevant. pub fn is_relevant(&self) -> bool { - self.score() > !(0 as u32) / 2 + self.score() > Self::BASE_SCORE } } From c8d9d5a930cbe7a357cfa4ecc23d9a871b8fefee Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 7 Mar 2025 07:38:10 +0100 Subject: [PATCH 29/53] Move project MSRV back to 1.78 --- .../crates/project-model/src/project_json.rs | 2 +- .../crates/project-model/src/sysroot.rs | 137 +++++ .../crates/project-model/src/workspace.rs | 56 ++ .../output/rust_project_cfg_groups.txt | 501 +++++++++++++++++- ...rust_project_hello_world_project_model.txt | 454 +++++++++++++++- .../crates/rust-analyzer/src/lib.rs | 2 +- 6 files changed, 1145 insertions(+), 7 deletions(-) diff --git a/src/tools/rust-analyzer/crates/project-model/src/project_json.rs b/src/tools/rust-analyzer/crates/project-model/src/project_json.rs index 0282a714645b6..b2df8e4703ab3 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/project_json.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/project_json.rs @@ -86,7 +86,7 @@ impl ProjectJson { /// * `manifest` - The path to the `rust-project.json`. /// * `base` - The path to the workspace root (i.e. the folder containing `rust-project.json`) /// * `data` - The parsed contents of `rust-project.json`, or project json that's passed via - /// configuration. + /// configuration. pub fn new( manifest: Option, base: &AbsPath, diff --git a/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs b/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs index 1e3c5a94786f1..13812e96fe7a5 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs @@ -30,6 +30,7 @@ pub struct Sysroot { pub enum RustLibSrcWorkspace { Workspace(CargoWorkspace), Json(ProjectJson), + Stitched(stitched::Stitched), Empty, } @@ -60,6 +61,7 @@ impl Sysroot { match &self.workspace { RustLibSrcWorkspace::Workspace(ws) => ws.packages().next().is_none(), RustLibSrcWorkspace::Json(project_json) => project_json.n_crates() == 0, + RustLibSrcWorkspace::Stitched(stitched) => stitched.crates.is_empty(), RustLibSrcWorkspace::Empty => true, } } @@ -72,6 +74,7 @@ impl Sysroot { match &self.workspace { RustLibSrcWorkspace::Workspace(ws) => ws.packages().count(), RustLibSrcWorkspace::Json(project_json) => project_json.n_crates(), + RustLibSrcWorkspace::Stitched(stitched) => stitched.crates.len(), RustLibSrcWorkspace::Empty => 0, } } @@ -197,6 +200,51 @@ impl Sysroot { return Some(loaded); } } + tracing::debug!("Stitching sysroot library: {src_root}"); + + let mut stitched = stitched::Stitched { crates: Default::default() }; + + for path in stitched::SYSROOT_CRATES.trim().lines() { + let name = path.split('/').next_back().unwrap(); + let root = [format!("{path}/src/lib.rs"), format!("lib{path}/lib.rs")] + .into_iter() + .map(|it| src_root.join(it)) + .filter_map(|it| ManifestPath::try_from(it).ok()) + .find(|it| fs::metadata(it).is_ok()); + + if let Some(root) = root { + stitched.crates.alloc(stitched::RustLibSrcCrateData { + name: name.into(), + root, + deps: Vec::new(), + }); + } + } + + if let Some(std) = stitched.by_name("std") { + for dep in stitched::STD_DEPS.trim().lines() { + if let Some(dep) = stitched.by_name(dep) { + stitched.crates[std].deps.push(dep) + } + } + } + + if let Some(alloc) = stitched.by_name("alloc") { + for dep in stitched::ALLOC_DEPS.trim().lines() { + if let Some(dep) = stitched.by_name(dep) { + stitched.crates[alloc].deps.push(dep) + } + } + } + + if let Some(proc_macro) = stitched.by_name("proc_macro") { + for dep in stitched::PROC_MACRO_DEPS.trim().lines() { + if let Some(dep) = stitched.by_name(dep) { + stitched.crates[proc_macro].deps.push(dep) + } + } + } + return Some(RustLibSrcWorkspace::Stitched(stitched)); } else if let RustSourceWorkspaceConfig::Json(project_json) = sysroot_source_config { return Some(RustLibSrcWorkspace::Json(project_json.clone())); } @@ -216,6 +264,7 @@ impl Sysroot { .crates() .filter_map(|(_, krate)| krate.display_name.clone()) .any(|name| name.canonical_name().as_str() == "core"), + RustLibSrcWorkspace::Stitched(stitched) => stitched.by_name("core").is_some(), RustLibSrcWorkspace::Empty => true, }; if !has_core { @@ -391,3 +440,91 @@ fn get_rust_lib_src(sysroot_path: &AbsPath) -> Option { None } } + +// FIXME: Remove this, that will bump our project MSRV to 1.82 +pub(crate) mod stitched { + use std::ops; + + use base_db::CrateName; + use la_arena::{Arena, Idx}; + + use crate::ManifestPath; + + #[derive(Debug, Clone, Eq, PartialEq)] + pub struct Stitched { + pub(super) crates: Arena, + } + + impl ops::Index for Stitched { + type Output = RustLibSrcCrateData; + fn index(&self, index: RustLibSrcCrate) -> &RustLibSrcCrateData { + &self.crates[index] + } + } + + impl Stitched { + pub(crate) fn public_deps( + &self, + ) -> impl Iterator + '_ { + // core is added as a dependency before std in order to + // mimic rustcs dependency order + [("core", true), ("alloc", false), ("std", true), ("test", false)] + .into_iter() + .filter_map(move |(name, prelude)| { + Some((CrateName::new(name).unwrap(), self.by_name(name)?, prelude)) + }) + } + + pub(crate) fn proc_macro(&self) -> Option { + self.by_name("proc_macro") + } + + pub(crate) fn crates(&self) -> impl ExactSizeIterator + '_ { + self.crates.iter().map(|(id, _data)| id) + } + + pub(super) fn by_name(&self, name: &str) -> Option { + let (id, _data) = self.crates.iter().find(|(_id, data)| data.name == name)?; + Some(id) + } + } + + pub(crate) type RustLibSrcCrate = Idx; + + #[derive(Debug, Clone, Eq, PartialEq)] + pub(crate) struct RustLibSrcCrateData { + pub(crate) name: String, + pub(crate) root: ManifestPath, + pub(crate) deps: Vec, + } + + pub(super) const SYSROOT_CRATES: &str = " +alloc +backtrace +core +panic_abort +panic_unwind +proc_macro +profiler_builtins +std +stdarch/crates/std_detect +test +unwind"; + + pub(super) const ALLOC_DEPS: &str = "core"; + + pub(super) const STD_DEPS: &str = " +alloc +panic_unwind +panic_abort +core +profiler_builtins +unwind +std_detect +test"; + + // core is required for our builtin derives to work in the proc_macro lib currently + pub(super) const PROC_MACRO_DEPS: &str = " +std +core"; +} diff --git a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs index 89818be8d4702..62c13c7d9ec8d 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs @@ -692,6 +692,7 @@ impl ProjectWorkspace { exclude: krate.exclude.clone(), }) .collect(), + RustLibSrcWorkspace::Stitched(_) => vec![], RustLibSrcWorkspace::Empty => vec![], }; @@ -1630,7 +1631,62 @@ fn sysroot_to_crate_graph( extend_crate_graph_with_sysroot(crate_graph, cg, pm) } + RustLibSrcWorkspace::Stitched(stitched) => { + let cfg_options = Arc::new({ + let mut cfg_options = CfgOptions::default(); + cfg_options.extend(rustc_cfg); + cfg_options.insert_atom(sym::debug_assertions.clone()); + cfg_options.insert_atom(sym::miri.clone()); + cfg_options + }); + let sysroot_crates: FxHashMap = + stitched + .crates() + .filter_map(|krate| { + let file_id = load(&stitched[krate].root)?; + + let display_name = + CrateDisplayName::from_canonical_name(&stitched[krate].name); + let crate_id = crate_graph.add_crate_root( + file_id, + Edition::CURRENT_FIXME, + Some(display_name), + None, + cfg_options.clone(), + None, + Env::default(), + CrateOrigin::Lang(LangCrateOrigin::from(&*stitched[krate].name)), + false, + None, + ); + Some((krate, crate_id)) + }) + .collect(); + + for from in stitched.crates() { + for &to in stitched[from].deps.iter() { + let name = CrateName::new(&stitched[to].name).unwrap(); + if let (Some(&from), Some(&to)) = + (sysroot_crates.get(&from), sysroot_crates.get(&to)) + { + add_dep(crate_graph, from, name, to); + } + } + } + let public_deps = SysrootPublicDeps { + deps: stitched + .public_deps() + .filter_map(|(name, idx, prelude)| { + Some((name, *sysroot_crates.get(&idx)?, prelude)) + }) + .collect::>(), + }; + + let libproc_macro = + stitched.proc_macro().and_then(|it| sysroot_crates.get(&it).copied()); + (public_deps, libproc_macro) + } RustLibSrcWorkspace::Empty => (SysrootPublicDeps { deps: vec![] }, None), } } diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_cfg_groups.txt b/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_cfg_groups.txt index 28ca4eb53487a..9b4be19c41c83 100644 --- a/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_cfg_groups.txt +++ b/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_cfg_groups.txt @@ -3,6 +3,417 @@ root_file_id: FileId( 1, ), + edition: Edition2021, + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "alloc", + ), + canonical_name: "alloc", + }, + ), + cfg_options: CfgOptions( + [ + "debug_assertions", + "miri", + "true", + ], + ), + potential_cfg_options: None, + env: Env { + entries: {}, + }, + dependencies: [ + Dependency { + crate_id: Idx::(1), + name: CrateName( + "core", + ), + prelude: true, + sysroot: false, + }, + ], + origin: Lang( + Alloc, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + 1: CrateData { + root_file_id: FileId( + 2, + ), + edition: Edition2021, + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "core", + ), + canonical_name: "core", + }, + ), + cfg_options: CfgOptions( + [ + "debug_assertions", + "miri", + "true", + ], + ), + potential_cfg_options: None, + env: Env { + entries: {}, + }, + dependencies: [], + origin: Lang( + Core, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + 2: CrateData { + root_file_id: FileId( + 3, + ), + edition: Edition2021, + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "panic_abort", + ), + canonical_name: "panic_abort", + }, + ), + cfg_options: CfgOptions( + [ + "debug_assertions", + "miri", + "true", + ], + ), + potential_cfg_options: None, + env: Env { + entries: {}, + }, + dependencies: [], + origin: Lang( + Other, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + 3: CrateData { + root_file_id: FileId( + 4, + ), + edition: Edition2021, + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "panic_unwind", + ), + canonical_name: "panic_unwind", + }, + ), + cfg_options: CfgOptions( + [ + "debug_assertions", + "miri", + "true", + ], + ), + potential_cfg_options: None, + env: Env { + entries: {}, + }, + dependencies: [], + origin: Lang( + Other, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + 4: CrateData { + root_file_id: FileId( + 5, + ), + edition: Edition2021, + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "proc_macro", + ), + canonical_name: "proc_macro", + }, + ), + cfg_options: CfgOptions( + [ + "debug_assertions", + "miri", + "true", + ], + ), + potential_cfg_options: None, + env: Env { + entries: {}, + }, + dependencies: [ + Dependency { + crate_id: Idx::(6), + name: CrateName( + "std", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(1), + name: CrateName( + "core", + ), + prelude: true, + sysroot: false, + }, + ], + origin: Lang( + ProcMacro, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + 5: CrateData { + root_file_id: FileId( + 6, + ), + edition: Edition2021, + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "profiler_builtins", + ), + canonical_name: "profiler_builtins", + }, + ), + cfg_options: CfgOptions( + [ + "debug_assertions", + "miri", + "true", + ], + ), + potential_cfg_options: None, + env: Env { + entries: {}, + }, + dependencies: [], + origin: Lang( + Other, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + 6: CrateData { + root_file_id: FileId( + 7, + ), + edition: Edition2021, + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "std", + ), + canonical_name: "std", + }, + ), + cfg_options: CfgOptions( + [ + "debug_assertions", + "miri", + "true", + ], + ), + potential_cfg_options: None, + env: Env { + entries: {}, + }, + dependencies: [ + Dependency { + crate_id: Idx::(0), + name: CrateName( + "alloc", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(3), + name: CrateName( + "panic_unwind", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(2), + name: CrateName( + "panic_abort", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(1), + name: CrateName( + "core", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(5), + name: CrateName( + "profiler_builtins", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(9), + name: CrateName( + "unwind", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(7), + name: CrateName( + "std_detect", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(8), + name: CrateName( + "test", + ), + prelude: true, + sysroot: false, + }, + ], + origin: Lang( + Std, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + 7: CrateData { + root_file_id: FileId( + 8, + ), + edition: Edition2021, + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "std_detect", + ), + canonical_name: "std_detect", + }, + ), + cfg_options: CfgOptions( + [ + "debug_assertions", + "miri", + "true", + ], + ), + potential_cfg_options: None, + env: Env { + entries: {}, + }, + dependencies: [], + origin: Lang( + Other, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + 8: CrateData { + root_file_id: FileId( + 9, + ), + edition: Edition2021, + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "test", + ), + canonical_name: "test", + }, + ), + cfg_options: CfgOptions( + [ + "debug_assertions", + "miri", + "true", + ], + ), + potential_cfg_options: None, + env: Env { + entries: {}, + }, + dependencies: [], + origin: Lang( + Test, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + 9: CrateData { + root_file_id: FileId( + 10, + ), + edition: Edition2021, + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "unwind", + ), + canonical_name: "unwind", + }, + ), + cfg_options: CfgOptions( + [ + "debug_assertions", + "miri", + "true", + ], + ), + potential_cfg_options: None, + env: Env { + entries: {}, + }, + dependencies: [], + origin: Lang( + Other, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + 10: CrateData { + root_file_id: FileId( + 11, + ), edition: Edition2018, version: None, display_name: Some( @@ -27,7 +438,48 @@ env: Env { entries: {}, }, - dependencies: [], + dependencies: [ + Dependency { + crate_id: Idx::(1), + name: CrateName( + "core", + ), + prelude: true, + sysroot: true, + }, + Dependency { + crate_id: Idx::(0), + name: CrateName( + "alloc", + ), + prelude: false, + sysroot: true, + }, + Dependency { + crate_id: Idx::(6), + name: CrateName( + "std", + ), + prelude: true, + sysroot: true, + }, + Dependency { + crate_id: Idx::(8), + name: CrateName( + "test", + ), + prelude: false, + sysroot: true, + }, + Dependency { + crate_id: Idx::(4), + name: CrateName( + "proc_macro", + ), + prelude: false, + sysroot: true, + }, + ], origin: Local { repo: None, name: Some( @@ -37,9 +489,9 @@ is_proc_macro: false, proc_macro_cwd: None, }, - 1: CrateData { + 11: CrateData { root_file_id: FileId( - 1, + 11, ), edition: Edition2018, version: None, @@ -65,7 +517,48 @@ env: Env { entries: {}, }, - dependencies: [], + dependencies: [ + Dependency { + crate_id: Idx::(1), + name: CrateName( + "core", + ), + prelude: true, + sysroot: true, + }, + Dependency { + crate_id: Idx::(0), + name: CrateName( + "alloc", + ), + prelude: false, + sysroot: true, + }, + Dependency { + crate_id: Idx::(6), + name: CrateName( + "std", + ), + prelude: true, + sysroot: true, + }, + Dependency { + crate_id: Idx::(8), + name: CrateName( + "test", + ), + prelude: false, + sysroot: true, + }, + Dependency { + crate_id: Idx::(4), + name: CrateName( + "proc_macro", + ), + prelude: false, + sysroot: true, + }, + ], origin: Local { repo: None, name: Some( diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt b/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt index dde8d3023dc2d..4c8e66e8e968b 100644 --- a/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt +++ b/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt @@ -3,6 +3,417 @@ root_file_id: FileId( 1, ), + edition: Edition2021, + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "alloc", + ), + canonical_name: "alloc", + }, + ), + cfg_options: CfgOptions( + [ + "debug_assertions", + "miri", + "true", + ], + ), + potential_cfg_options: None, + env: Env { + entries: {}, + }, + dependencies: [ + Dependency { + crate_id: Idx::(1), + name: CrateName( + "core", + ), + prelude: true, + sysroot: false, + }, + ], + origin: Lang( + Alloc, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + 1: CrateData { + root_file_id: FileId( + 2, + ), + edition: Edition2021, + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "core", + ), + canonical_name: "core", + }, + ), + cfg_options: CfgOptions( + [ + "debug_assertions", + "miri", + "true", + ], + ), + potential_cfg_options: None, + env: Env { + entries: {}, + }, + dependencies: [], + origin: Lang( + Core, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + 2: CrateData { + root_file_id: FileId( + 3, + ), + edition: Edition2021, + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "panic_abort", + ), + canonical_name: "panic_abort", + }, + ), + cfg_options: CfgOptions( + [ + "debug_assertions", + "miri", + "true", + ], + ), + potential_cfg_options: None, + env: Env { + entries: {}, + }, + dependencies: [], + origin: Lang( + Other, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + 3: CrateData { + root_file_id: FileId( + 4, + ), + edition: Edition2021, + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "panic_unwind", + ), + canonical_name: "panic_unwind", + }, + ), + cfg_options: CfgOptions( + [ + "debug_assertions", + "miri", + "true", + ], + ), + potential_cfg_options: None, + env: Env { + entries: {}, + }, + dependencies: [], + origin: Lang( + Other, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + 4: CrateData { + root_file_id: FileId( + 5, + ), + edition: Edition2021, + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "proc_macro", + ), + canonical_name: "proc_macro", + }, + ), + cfg_options: CfgOptions( + [ + "debug_assertions", + "miri", + "true", + ], + ), + potential_cfg_options: None, + env: Env { + entries: {}, + }, + dependencies: [ + Dependency { + crate_id: Idx::(6), + name: CrateName( + "std", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(1), + name: CrateName( + "core", + ), + prelude: true, + sysroot: false, + }, + ], + origin: Lang( + ProcMacro, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + 5: CrateData { + root_file_id: FileId( + 6, + ), + edition: Edition2021, + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "profiler_builtins", + ), + canonical_name: "profiler_builtins", + }, + ), + cfg_options: CfgOptions( + [ + "debug_assertions", + "miri", + "true", + ], + ), + potential_cfg_options: None, + env: Env { + entries: {}, + }, + dependencies: [], + origin: Lang( + Other, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + 6: CrateData { + root_file_id: FileId( + 7, + ), + edition: Edition2021, + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "std", + ), + canonical_name: "std", + }, + ), + cfg_options: CfgOptions( + [ + "debug_assertions", + "miri", + "true", + ], + ), + potential_cfg_options: None, + env: Env { + entries: {}, + }, + dependencies: [ + Dependency { + crate_id: Idx::(0), + name: CrateName( + "alloc", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(3), + name: CrateName( + "panic_unwind", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(2), + name: CrateName( + "panic_abort", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(1), + name: CrateName( + "core", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(5), + name: CrateName( + "profiler_builtins", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(9), + name: CrateName( + "unwind", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(7), + name: CrateName( + "std_detect", + ), + prelude: true, + sysroot: false, + }, + Dependency { + crate_id: Idx::(8), + name: CrateName( + "test", + ), + prelude: true, + sysroot: false, + }, + ], + origin: Lang( + Std, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + 7: CrateData { + root_file_id: FileId( + 8, + ), + edition: Edition2021, + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "std_detect", + ), + canonical_name: "std_detect", + }, + ), + cfg_options: CfgOptions( + [ + "debug_assertions", + "miri", + "true", + ], + ), + potential_cfg_options: None, + env: Env { + entries: {}, + }, + dependencies: [], + origin: Lang( + Other, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + 8: CrateData { + root_file_id: FileId( + 9, + ), + edition: Edition2021, + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "test", + ), + canonical_name: "test", + }, + ), + cfg_options: CfgOptions( + [ + "debug_assertions", + "miri", + "true", + ], + ), + potential_cfg_options: None, + env: Env { + entries: {}, + }, + dependencies: [], + origin: Lang( + Test, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + 9: CrateData { + root_file_id: FileId( + 10, + ), + edition: Edition2021, + version: None, + display_name: Some( + CrateDisplayName { + crate_name: CrateName( + "unwind", + ), + canonical_name: "unwind", + }, + ), + cfg_options: CfgOptions( + [ + "debug_assertions", + "miri", + "true", + ], + ), + potential_cfg_options: None, + env: Env { + entries: {}, + }, + dependencies: [], + origin: Lang( + Other, + ), + is_proc_macro: false, + proc_macro_cwd: None, + }, + 10: CrateData { + root_file_id: FileId( + 11, + ), edition: Edition2018, version: None, display_name: Some( @@ -24,7 +435,48 @@ env: Env { entries: {}, }, - dependencies: [], + dependencies: [ + Dependency { + crate_id: Idx::(1), + name: CrateName( + "core", + ), + prelude: true, + sysroot: true, + }, + Dependency { + crate_id: Idx::(0), + name: CrateName( + "alloc", + ), + prelude: false, + sysroot: true, + }, + Dependency { + crate_id: Idx::(6), + name: CrateName( + "std", + ), + prelude: true, + sysroot: true, + }, + Dependency { + crate_id: Idx::(8), + name: CrateName( + "test", + ), + prelude: false, + sysroot: true, + }, + Dependency { + crate_id: Idx::(4), + name: CrateName( + "proc_macro", + ), + prelude: false, + sysroot: true, + }, + ], origin: Local { repo: None, name: Some( diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs index b9e38f2e69176..a0d6a0d6da6f8 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs @@ -12,7 +12,7 @@ /// Any toolchain less than this version will likely not work with rust-analyzer built from this revision. pub const MINIMUM_SUPPORTED_TOOLCHAIN_VERSION: semver::Version = semver::Version { major: 1, - minor: 82, + minor: 78, patch: 0, pre: semver::Prerelease::EMPTY, build: semver::BuildMetadata::EMPTY, From 5c6a1247fb7075682798f5b0d68823759fca571b Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 7 Mar 2025 07:49:36 +0100 Subject: [PATCH 30/53] Pop up a notification for the MSRV project loading warning --- .../crates/rust-analyzer/src/global_state.rs | 19 ++++++++++++++ .../crates/rust-analyzer/src/reload.rs | 26 +++++++------------ 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs index 70105cda006b2..54670b675984d 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs @@ -637,6 +637,25 @@ impl GlobalState { } }); } + + pub(crate) fn check_workspaces_msrv(&self) -> impl Iterator + '_ { + self.workspaces.iter().filter_map(|ws| { + if let Some(toolchain) = &ws.toolchain { + if *toolchain < crate::MINIMUM_SUPPORTED_TOOLCHAIN_VERSION { + return Some(format!( + "Workspace `{}` is using an outdated toolchain version `{}` but \ + rust-analyzer only supports `{}` and higher.\n\ + Consider using the rust-analyzer rustup component for your toolchain or + upgrade your toolchain to a supported version.\n\n", + ws.manifest_or_root(), + toolchain, + crate::MINIMUM_SUPPORTED_TOOLCHAIN_VERSION, + )); + } + } + None + }) + } } impl Drop for GlobalState { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs index 733a7c359b8e7..dffaa88240b1a 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs @@ -178,26 +178,15 @@ impl GlobalState { } if !self.workspaces.is_empty() { + self.check_workspaces_msrv().for_each(|e| { + status.health |= lsp_ext::Health::Warning; + format_to!(message, "{e}"); + }); + let proc_macro_clients = self.proc_macro_clients.iter().map(Some).chain(iter::repeat_with(|| None)); for (ws, proc_macro_client) in self.workspaces.iter().zip(proc_macro_clients) { - if let Some(toolchain) = &ws.toolchain { - if *toolchain < crate::MINIMUM_SUPPORTED_TOOLCHAIN_VERSION { - status.health |= lsp_ext::Health::Warning; - format_to!( - message, - "Workspace `{}` is using an outdated toolchain version `{}` but \ - rust-analyzer only supports `{}` and higher.\n\ - Consider using the rust-analyzer rustup component for your toolchain or - upgrade your toolchain to a supported version.\n\n", - ws.manifest_or_root(), - toolchain, - crate::MINIMUM_SUPPORTED_TOOLCHAIN_VERSION, - ); - } - } - if let ProjectWorkspaceKind::Cargo { error: Some(error), .. } | ProjectWorkspaceKind::DetachedFile { cargo: Some((_, _, Some(error))), .. @@ -529,6 +518,11 @@ impl GlobalState { // we don't care about build-script results, they are stale. // FIXME: can we abort the build scripts here if they are already running? self.workspaces = Arc::new(workspaces); + self.check_workspaces_msrv().for_each(|message| { + self.send_notification::( + lsp_types::ShowMessageParams { typ: lsp_types::MessageType::WARNING, message }, + ); + }); if self.config.run_build_scripts(None) { self.build_deps_changed = false; From bdf602a594dd009a694d000d6d910685af1ae330 Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Fri, 7 Mar 2025 16:07:35 +0100 Subject: [PATCH 31/53] Log build script error output in `load_cargo::load_workspace_at` --- src/tools/rust-analyzer/crates/load-cargo/src/lib.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs index 76f1a7f48b6bc..72ca85c6a2fde 100644 --- a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs +++ b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs @@ -45,10 +45,18 @@ pub fn load_workspace_at( ) -> anyhow::Result<(RootDatabase, vfs::Vfs, Option)> { let root = AbsPathBuf::assert_utf8(std::env::current_dir()?.join(root)); let root = ProjectManifest::discover_single(&root)?; + let manifest_path = root.manifest_path().clone(); let mut workspace = ProjectWorkspace::load(root, cargo_config, progress)?; if load_config.load_out_dirs_from_check { let build_scripts = workspace.run_build_scripts(cargo_config, progress)?; + if let Some(error) = build_scripts.error() { + tracing::debug!( + "Errors occurred while running build scripts for {}: {}", + manifest_path, + error + ); + } workspace.set_build_scripts(build_scripts) } From e98837f558db4d92429ef10576afcd5198cbb3fb Mon Sep 17 00:00:00 2001 From: Prajwal S N Date: Sat, 8 Mar 2025 01:25:27 +0530 Subject: [PATCH 32/53] fix(hir): `VariantDef` is `impl HasSource` A new syntax node `ast::VariantDef` has been introduced to map between the HIR node and the AST. The files have been updated with `cargo test -p xtask`. Signed-off-by: Prajwal S N --- .../crates/hir/src/has_source.rs | 12 ++++- .../parser/src/syntax_kind/generated.rs | 2 + .../rust-analyzer/crates/syntax/rust.ungram | 5 ++ .../crates/syntax/src/ast/generated/nodes.rs | 50 +++++++++++++++++++ .../docs/book/src/assists_generated.md | 4 +- 5 files changed, 70 insertions(+), 3 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir/src/has_source.rs b/src/tools/rust-analyzer/crates/hir/src/has_source.rs index a34b4980832c8..372c725293441 100644 --- a/src/tools/rust-analyzer/crates/hir/src/has_source.rs +++ b/src/tools/rust-analyzer/crates/hir/src/has_source.rs @@ -15,7 +15,7 @@ use tt::TextRange; use crate::{ db::HirDatabase, Adt, Callee, Const, Enum, ExternCrateDecl, Field, FieldSource, Function, Impl, InlineAsmOperand, Label, LifetimeParam, LocalSource, Macro, Module, Param, SelfParam, Static, - Struct, Trait, TraitAlias, TypeAlias, TypeOrConstParam, Union, Variant, + Struct, Trait, TraitAlias, TypeAlias, TypeOrConstParam, Union, Variant, VariantDef, }; pub trait HasSource { @@ -110,6 +110,16 @@ impl HasSource for Adt { } } } +impl HasSource for VariantDef { + type Ast = ast::VariantDef; + fn source(self, db: &dyn HirDatabase) -> Option> { + match self { + VariantDef::Struct(s) => Some(s.source(db)?.map(ast::VariantDef::Struct)), + VariantDef::Union(u) => Some(u.source(db)?.map(ast::VariantDef::Union)), + VariantDef::Variant(v) => Some(v.source(db)?.map(ast::VariantDef::Variant)), + } + } +} impl HasSource for Struct { type Ast = ast::Struct; fn source(self, db: &dyn HirDatabase) -> Option> { diff --git a/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs b/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs index e56e09eeb66b9..1ff0bbea8b1db 100644 --- a/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs +++ b/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs @@ -315,6 +315,7 @@ pub enum SyntaxKind { USE_TREE, USE_TREE_LIST, VARIANT, + VARIANT_DEF, VARIANT_LIST, VISIBILITY, WHERE_CLAUSE, @@ -501,6 +502,7 @@ impl SyntaxKind { | USE_TREE | USE_TREE_LIST | VARIANT + | VARIANT_DEF | VARIANT_LIST | VISIBILITY | WHERE_CLAUSE diff --git a/src/tools/rust-analyzer/crates/syntax/rust.ungram b/src/tools/rust-analyzer/crates/syntax/rust.ungram index 88d7beb897e03..70a91af6c4790 100644 --- a/src/tools/rust-analyzer/crates/syntax/rust.ungram +++ b/src/tools/rust-analyzer/crates/syntax/rust.ungram @@ -279,6 +279,11 @@ Adt = | Struct | Union +VariantDef = + Struct +| Union +| Variant + Const = Attr* Visibility? 'default'? diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs index 58c76a456ab10..ebee5e9af2c4d 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs @@ -2446,6 +2446,17 @@ pub enum UseBoundGenericArg { NameRef(NameRef), } +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum VariantDef { + Struct(Struct), + Union(Union), + Variant(Variant), +} +impl ast::HasAttrs for VariantDef {} +impl ast::HasDocComments for VariantDef {} +impl ast::HasName for VariantDef {} +impl ast::HasVisibility for VariantDef {} + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct AnyHasArgList { pub(crate) syntax: SyntaxNode, @@ -6738,6 +6749,40 @@ impl AstNode for UseBoundGenericArg { } } } +impl From for VariantDef { + #[inline] + fn from(node: Struct) -> VariantDef { VariantDef::Struct(node) } +} +impl From for VariantDef { + #[inline] + fn from(node: Union) -> VariantDef { VariantDef::Union(node) } +} +impl From for VariantDef { + #[inline] + fn from(node: Variant) -> VariantDef { VariantDef::Variant(node) } +} +impl AstNode for VariantDef { + #[inline] + fn can_cast(kind: SyntaxKind) -> bool { matches!(kind, STRUCT | UNION | VARIANT) } + #[inline] + fn cast(syntax: SyntaxNode) -> Option { + let res = match syntax.kind() { + STRUCT => VariantDef::Struct(Struct { syntax }), + UNION => VariantDef::Union(Union { syntax }), + VARIANT => VariantDef::Variant(Variant { syntax }), + _ => return None, + }; + Some(res) + } + #[inline] + fn syntax(&self) -> &SyntaxNode { + match self { + VariantDef::Struct(it) => &it.syntax, + VariantDef::Union(it) => &it.syntax, + VariantDef::Variant(it) => &it.syntax, + } + } +} impl AnyHasArgList { #[inline] pub fn new(node: T) -> AnyHasArgList { @@ -7753,6 +7798,11 @@ impl std::fmt::Display for UseBoundGenericArg { std::fmt::Display::fmt(self.syntax(), f) } } +impl std::fmt::Display for VariantDef { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} impl std::fmt::Display for Abi { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) diff --git a/src/tools/rust-analyzer/docs/book/src/assists_generated.md b/src/tools/rust-analyzer/docs/book/src/assists_generated.md index 918ae4a579443..a1433952e0ba1 100644 --- a/src/tools/rust-analyzer/docs/book/src/assists_generated.md +++ b/src/tools/rust-analyzer/docs/book/src/assists_generated.md @@ -1070,7 +1070,7 @@ pub use foo::{Bar, Baz}; ### `expand_record_rest_pattern` -**Source:** [expand_rest_pattern.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/expand_rest_pattern.rs#L24) +**Source:** [expand_rest_pattern.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/expand_rest_pattern.rs#L26) Fills fields by replacing rest pattern in record patterns. @@ -1094,7 +1094,7 @@ fn foo(bar: Bar) { ### `expand_tuple_struct_rest_pattern` -**Source:** [expand_rest_pattern.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/expand_rest_pattern.rs#L80) +**Source:** [expand_rest_pattern.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/expand_rest_pattern.rs#L82) Fills fields by replacing rest pattern in tuple struct patterns. From b6f1ce8071c70e0afd3bad39ee10404bfbf32f5c Mon Sep 17 00:00:00 2001 From: Prajwal S N Date: Sat, 8 Mar 2025 01:44:27 +0530 Subject: [PATCH 33/53] fix: do not apply editorconfig to git commit msg The `max_line_length` property was set to 100 for all filetypes, which led to git commit messages being wrapped at 100 characters instead of the usual 75. This introduces an exception for the special file used by git to write commit messages. Signed-off-by: Prajwal S N --- src/tools/rust-analyzer/.editorconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/tools/rust-analyzer/.editorconfig b/src/tools/rust-analyzer/.editorconfig index 6bb743a6736e5..2d28ebd4766a3 100644 --- a/src/tools/rust-analyzer/.editorconfig +++ b/src/tools/rust-analyzer/.editorconfig @@ -15,3 +15,6 @@ indent_size = 2 [*.{yml,yaml}] indent_size = 2 + +[COMMIT_EDITMSG] +max_line_length = unset From 871be8f54ace198c42780b366d1817ffc77e9fa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sat, 8 Mar 2025 12:46:24 +0100 Subject: [PATCH 34/53] Add missing `GH_TOKEN` environment variable It is needed for using the `gh` CLI commands. --- .github/workflows/post-merge.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/post-merge.yml b/.github/workflows/post-merge.yml index d3f42c5a9052c..919e1bb33206f 100644 --- a/.github/workflows/post-merge.yml +++ b/.github/workflows/post-merge.yml @@ -17,14 +17,15 @@ jobs: steps: - uses: actions/checkout@v4 - name: Perform analysis and send PR + env: + GH_TOKEN: ${{ github.token }} run: | # Get closest bors merge commit PARENT_COMMIT=`git rev-list --author='bors ' -n1 --first-parent HEAD^1` + echo "Parent: ${PARENT_COMMIT}" # Find PR for the current commit HEAD_PR=`gh pr list --search "${{ github.sha }}" --state merged --json number --jq '.[0].number'` - - echo "Parent: ${PARENT_COMMIT}" echo "HEAD: ${{ github.sha }} (#${HEAD_PR})" cd src/ci/citool From ff674232d198b196c8fa9d2092b8165b4bcce6b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sat, 8 Mar 2025 12:46:33 +0100 Subject: [PATCH 35/53] Fix checkout in post-merge workflow --- .github/workflows/post-merge.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/post-merge.yml b/.github/workflows/post-merge.yml index 919e1bb33206f..2bc06d83c5b7c 100644 --- a/.github/workflows/post-merge.yml +++ b/.github/workflows/post-merge.yml @@ -16,6 +16,11 @@ jobs: pull-requests: write steps: - uses: actions/checkout@v4 + with: + # Make sure that we have enough commits to find the parent merge commit. + # Since all merges should be through merge commits, fetching two commits + # should be enough to get the parent bors merge commit. + fetch-depth: 2 - name: Perform analysis and send PR env: GH_TOKEN: ${{ github.token }} From e88f892ecafcf9e0815552d219fe98c8f7084f6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A8Florian?= <¨flodiebold@gmail.com¨> Date: Fri, 28 Feb 2025 17:32:21 +0100 Subject: [PATCH 36/53] Fix syntax fixup producing invalid punctuation Fixes #19206. Fixes #18244. --- .../mbe/tt_conversion.rs | 8 +-- .../crates/hir-expand/src/fixup.rs | 68 +++++++----------- .../rust-analyzer/crates/mbe/src/tests.rs | 17 +++++ .../crates/syntax-bridge/src/lib.rs | 70 ++++++++++++++----- src/tools/rust-analyzer/crates/tt/src/lib.rs | 30 ++------ 5 files changed, 105 insertions(+), 88 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/tt_conversion.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/tt_conversion.rs index c365a603d2af0..138db1b498bb2 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/tt_conversion.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/tt_conversion.rs @@ -93,15 +93,15 @@ fn broken_parenthesis_sequence() { macro_rules! m1 { ($x:ident) => { ($x } } macro_rules! m2 { ($x:ident) => {} } -m1!(); -m2!(x +fn f1() { m1!(x); } +fn f2() { m2!(x } "#, expect![[r#" macro_rules! m1 { ($x:ident) => { ($x } } macro_rules! m2 { ($x:ident) => {} } -/* error: macro definition has parse errors */ -/* error: expected ident */ +fn f1() { (x); } +fn f2() { /* error: expected ident */ } "#]], ) } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs b/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs index eb430177390fa..28894537d48f7 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs @@ -148,7 +148,6 @@ pub(crate) fn fixup_syntax( } if it.then_branch().is_none() { append.insert(node.clone().into(), vec![ - // FIXME: THis should be a subtree no? Leaf::Punct(Punct { char: '{', spacing: Spacing::Alone, @@ -179,7 +178,6 @@ pub(crate) fn fixup_syntax( } if it.loop_body().is_none() { append.insert(node.clone().into(), vec![ - // FIXME: THis should be a subtree no? Leaf::Punct(Punct { char: '{', spacing: Spacing::Alone, @@ -196,7 +194,6 @@ pub(crate) fn fixup_syntax( ast::LoopExpr(it) => { if it.loop_body().is_none() { append.insert(node.clone().into(), vec![ - // FIXME: THis should be a subtree no? Leaf::Punct(Punct { char: '{', spacing: Spacing::Alone, @@ -228,7 +225,6 @@ pub(crate) fn fixup_syntax( if it.match_arm_list().is_none() { // No match arms append.insert(node.clone().into(), vec![ - // FIXME: THis should be a subtree no? Leaf::Punct(Punct { char: '{', spacing: Spacing::Alone, @@ -269,7 +265,6 @@ pub(crate) fn fixup_syntax( if it.loop_body().is_none() { append.insert(node.clone().into(), vec![ - // FIXME: THis should be a subtree no? Leaf::Punct(Punct { char: '{', spacing: Spacing::Alone, @@ -309,28 +304,6 @@ pub(crate) fn fixup_syntax( } } }, - ast::ArgList(it) => { - if it.r_paren_token().is_none() { - append.insert(node.into(), vec![ - Leaf::Punct(Punct { - span: fake_span(node_range), - char: ')', - spacing: Spacing::Alone - }) - ]); - } - }, - ast::ArgList(it) => { - if it.r_paren_token().is_none() { - append.insert(node.into(), vec![ - Leaf::Punct(Punct { - span: fake_span(node_range), - char: ')', - spacing: Spacing::Alone - }) - ]); - } - }, ast::ClosureExpr(it) => { if it.body().is_none() { append.insert(node.into(), vec![ @@ -476,12 +449,12 @@ fn reverse_fixups_(tt: &mut TopSubtree, undo_info: &[TopSubtree]) { } } tt::TokenTree::Subtree(tt) => { + // fixup should only create matching delimiters, but proc macros + // could just copy the span to one of the delimiters. We don't want + // to leak the dummy ID, so we remove both. if tt.delimiter.close.anchor.ast_id == FIXUP_DUMMY_AST_ID || tt.delimiter.open.anchor.ast_id == FIXUP_DUMMY_AST_ID { - // Even though fixup never creates subtrees with fixup spans, the old proc-macro server - // might copy them if the proc-macro asks for it, so we need to filter those out - // here as well. return TransformTtAction::remove(); } TransformTtAction::Keep @@ -571,6 +544,17 @@ mod tests { parse.syntax_node() ); + // the fixed-up tree should not contain braces as punct + // FIXME: should probably instead check that it's a valid punctuation character + for x in tt.token_trees().flat_tokens() { + match x { + ::tt::TokenTree::Leaf(::tt::Leaf::Punct(punct)) => { + assert!(!matches!(punct.char, '{' | '}' | '(' | ')' | '[' | ']')) + } + _ => (), + } + } + reverse_fixups(&mut tt, &fixups.undo_info); // the fixed-up + reversed version should be equivalent to the original input @@ -596,7 +580,7 @@ fn foo() { } "#, expect![[r#" -fn foo () {for _ in __ra_fixup { }} +fn foo () {for _ in __ra_fixup {}} "#]], ) } @@ -624,7 +608,7 @@ fn foo() { } "#, expect![[r#" -fn foo () {for bar in qux { }} +fn foo () {for bar in qux {}} "#]], ) } @@ -655,7 +639,7 @@ fn foo() { } "#, expect![[r#" -fn foo () {match __ra_fixup { }} +fn foo () {match __ra_fixup {}} "#]], ) } @@ -687,7 +671,7 @@ fn foo() { } "#, expect![[r#" -fn foo () {match __ra_fixup { }} +fn foo () {match __ra_fixup {}} "#]], ) } @@ -802,7 +786,7 @@ fn foo() { } "#, expect![[r#" -fn foo () {if a { }} +fn foo () {if a {}} "#]], ) } @@ -816,7 +800,7 @@ fn foo() { } "#, expect![[r#" -fn foo () {if __ra_fixup { }} +fn foo () {if __ra_fixup {}} "#]], ) } @@ -830,7 +814,7 @@ fn foo() { } "#, expect![[r#" -fn foo () {if __ra_fixup {} { }} +fn foo () {if __ra_fixup {} {}} "#]], ) } @@ -844,7 +828,7 @@ fn foo() { } "#, expect![[r#" -fn foo () {while __ra_fixup { }} +fn foo () {while __ra_fixup {}} "#]], ) } @@ -858,7 +842,7 @@ fn foo() { } "#, expect![[r#" -fn foo () {while foo { }} +fn foo () {while foo {}} "#]], ) } @@ -885,7 +869,7 @@ fn foo() { } "#, expect![[r#" -fn foo () {loop { }} +fn foo () {loop {}} "#]], ) } @@ -941,7 +925,7 @@ fn foo() { } "#, expect![[r#" -fn foo () { foo ( a ) } +fn foo () {foo (a)} "#]], ); check( @@ -951,7 +935,7 @@ fn foo() { } "#, expect![[r#" -fn foo () { bar . foo ( a ) } +fn foo () {bar . foo (a)} "#]], ); } diff --git a/src/tools/rust-analyzer/crates/mbe/src/tests.rs b/src/tools/rust-analyzer/crates/mbe/src/tests.rs index fb68d35a4c84f..4a73b6fa05a88 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/tests.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/tests.rs @@ -99,6 +99,23 @@ fn check( ); } +#[test] +fn unbalanced_brace() { + check( + Edition::CURRENT, + Edition::CURRENT, + r#" +() => { { } +"#, + r#""#, + expect![[r#" + SUBTREE $$ 1:0@0..0#2 1:0@0..0#2 + SUBTREE {} 0:0@9..10#2 0:0@11..12#2 + + {}"#]], + ); +} + #[test] fn token_mapping_smoke_test() { check( diff --git a/src/tools/rust-analyzer/crates/syntax-bridge/src/lib.rs b/src/tools/rust-analyzer/crates/syntax-bridge/src/lib.rs index 19801c49e4341..a59a3270c9d9d 100644 --- a/src/tools/rust-analyzer/crates/syntax-bridge/src/lib.rs +++ b/src/tools/rust-analyzer/crates/syntax-bridge/src/lib.rs @@ -12,7 +12,7 @@ use syntax::{ SyntaxKind::{self, *}, SyntaxNode, SyntaxToken, SyntaxTreeBuilder, TextRange, TextSize, WalkEvent, T, }; -use tt::{buffer::Cursor, token_to_literal}; +use tt::{buffer::Cursor, token_to_literal, Punct}; pub mod prettify_macro_expansion; mod to_parser_input; @@ -217,8 +217,39 @@ where tt::TopSubtreeBuilder::new(tt::Delimiter::invisible_spanned(conv.call_site())); while let Some((token, abs_range)) = conv.bump() { - let delimiter = builder.expected_delimiter().map(|it| it.kind); let tt = match token.as_leaf() { + // These delimiters are not actually valid punctuation, but we produce them in syntax fixup. + // So we need to handle them specially here. + Some(&tt::Leaf::Punct(Punct { + char: char @ ('(' | ')' | '{' | '}' | '[' | ']'), + span, + spacing: _, + })) => { + let found_expected_delimiter = + builder.expected_delimiters().enumerate().find(|(_, delim)| match delim.kind { + tt::DelimiterKind::Parenthesis => char == ')', + tt::DelimiterKind::Brace => char == '}', + tt::DelimiterKind::Bracket => char == ']', + tt::DelimiterKind::Invisible => false, + }); + if let Some((idx, _)) = found_expected_delimiter { + for _ in 0..=idx { + builder.close(span); + } + continue; + } + + let delim = match char { + '(' => tt::DelimiterKind::Parenthesis, + '{' => tt::DelimiterKind::Brace, + '[' => tt::DelimiterKind::Bracket, + _ => panic!("unmatched closing delimiter from syntax fixup"), + }; + + // Start a new subtree + builder.open(delim, span); + continue; + } Some(leaf) => leaf.clone(), None => match token.kind(conv) { // Desugar doc comments into doc attributes @@ -228,17 +259,24 @@ where continue; } kind if kind.is_punct() && kind != UNDERSCORE => { - let expected = match delimiter { - Some(tt::DelimiterKind::Parenthesis) => Some(T![')']), - Some(tt::DelimiterKind::Brace) => Some(T!['}']), - Some(tt::DelimiterKind::Bracket) => Some(T![']']), - Some(tt::DelimiterKind::Invisible) | None => None, - }; + let found_expected_delimiter = + builder.expected_delimiters().enumerate().find(|(_, delim)| { + match delim.kind { + tt::DelimiterKind::Parenthesis => kind == T![')'], + tt::DelimiterKind::Brace => kind == T!['}'], + tt::DelimiterKind::Bracket => kind == T![']'], + tt::DelimiterKind::Invisible => false, + } + }); // Current token is a closing delimiter that we expect, fix up the closing span - // and end the subtree here - if matches!(expected, Some(expected) if expected == kind) { - builder.close(conv.span_for(abs_range)); + // and end the subtree here. + // We also close any open inner subtrees that might be missing their delimiter. + if let Some((idx, _)) = found_expected_delimiter { + for _ in 0..=idx { + // FIXME: record an error somewhere if we're closing more than one tree here? + builder.close(conv.span_for(abs_range)); + } continue; } @@ -262,6 +300,7 @@ where let Some(char) = token.to_char(conv) else { panic!("Token from lexer must be single char: token = {token:#?}") }; + // FIXME: this might still be an unmatched closing delimiter? Maybe we should assert here tt::Leaf::from(tt::Punct { char, spacing, span: conv.span_for(abs_range) }) } kind => { @@ -317,11 +356,10 @@ where builder.push(tt); } - // If we get here, we've consumed all input tokens. - // We might have more than one subtree in the stack, if the delimiters are improperly balanced. - // Merge them so we're left with one. - builder.flatten_unclosed_subtrees(); - + while builder.expected_delimiters().next().is_some() { + // FIXME: record an error somewhere? + builder.close(conv.call_site()); + } builder.build_skip_top_subtree() } diff --git a/src/tools/rust-analyzer/crates/tt/src/lib.rs b/src/tools/rust-analyzer/crates/tt/src/lib.rs index 7705ba876e1ae..1cfead54f192d 100644 --- a/src/tools/rust-analyzer/crates/tt/src/lib.rs +++ b/src/tools/rust-analyzer/crates/tt/src/lib.rs @@ -243,8 +243,8 @@ impl TopSubtreeBuilder { self.token_trees.extend(tt.0.iter().cloned()); } - pub fn expected_delimiter(&self) -> Option<&Delimiter> { - self.unclosed_subtree_indices.last().map(|&subtree_idx| { + pub fn expected_delimiters(&self) -> impl Iterator> { + self.unclosed_subtree_indices.iter().rev().map(|&subtree_idx| { let TokenTree::Subtree(subtree) = &self.token_trees[subtree_idx] else { unreachable!("unclosed token tree is always a subtree") }; @@ -252,28 +252,6 @@ impl TopSubtreeBuilder { }) } - /// Converts unclosed subtree to a punct of their open delimiter. - // FIXME: This is incorrect to do, delimiters can never be puncts. See #18244. - pub fn flatten_unclosed_subtrees(&mut self) { - for &subtree_idx in &self.unclosed_subtree_indices { - let TokenTree::Subtree(subtree) = &self.token_trees[subtree_idx] else { - unreachable!("unclosed token tree is always a subtree") - }; - let char = match subtree.delimiter.kind { - DelimiterKind::Parenthesis => '(', - DelimiterKind::Brace => '{', - DelimiterKind::Bracket => '[', - DelimiterKind::Invisible => '$', - }; - self.token_trees[subtree_idx] = TokenTree::Leaf(Leaf::Punct(Punct { - char, - spacing: Spacing::Alone, - span: subtree.delimiter.open, - })); - } - self.unclosed_subtree_indices.clear(); - } - /// Builds, and remove the top subtree if it has only one subtree child. pub fn build_skip_top_subtree(mut self) -> TopSubtree { let top_tts = TokenTreesView::new(&self.token_trees[1..]); @@ -731,9 +709,9 @@ fn print_debug_subtree( }; write!(f, "{align}SUBTREE {delim} ",)?; - fmt::Debug::fmt(&open, f)?; + write!(f, "{:#?}", open)?; write!(f, " ")?; - fmt::Debug::fmt(&close, f)?; + write!(f, "{:#?}", close)?; for child in iter { writeln!(f)?; print_debug_token(f, level + 1, child)?; From fee83ba8527d595c155a05bf557cc00f743ade6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A8Florian?= <¨flodiebold@gmail.com¨> Date: Fri, 28 Feb 2025 18:03:53 +0100 Subject: [PATCH 37/53] Generated doc update --- src/tools/rust-analyzer/docs/book/src/assists_generated.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/rust-analyzer/docs/book/src/assists_generated.md b/src/tools/rust-analyzer/docs/book/src/assists_generated.md index 918ae4a579443..a1433952e0ba1 100644 --- a/src/tools/rust-analyzer/docs/book/src/assists_generated.md +++ b/src/tools/rust-analyzer/docs/book/src/assists_generated.md @@ -1070,7 +1070,7 @@ pub use foo::{Bar, Baz}; ### `expand_record_rest_pattern` -**Source:** [expand_rest_pattern.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/expand_rest_pattern.rs#L24) +**Source:** [expand_rest_pattern.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/expand_rest_pattern.rs#L26) Fills fields by replacing rest pattern in record patterns. @@ -1094,7 +1094,7 @@ fn foo(bar: Bar) { ### `expand_tuple_struct_rest_pattern` -**Source:** [expand_rest_pattern.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/expand_rest_pattern.rs#L80) +**Source:** [expand_rest_pattern.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/expand_rest_pattern.rs#L82) Fills fields by replacing rest pattern in tuple struct patterns. From bb82831126fbddd7946fab1acdd694ce40c02c81 Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Thu, 27 Feb 2025 03:42:57 +0900 Subject: [PATCH 38/53] Bump chalk for built-in supports of async closures --- src/tools/rust-analyzer/Cargo.lock | 16 ++++---- src/tools/rust-analyzer/Cargo.toml | 8 ++-- .../crates/hir-ty/src/chalk_db.rs | 8 ++++ .../crates/hir-ty/src/tests/simple.rs | 39 +++++++++++++++++++ .../docs/book/src/assists_generated.md | 4 +- 5 files changed, 61 insertions(+), 14 deletions(-) diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index c57953ba65476..30853cb799e1a 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -191,9 +191,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chalk-derive" -version = "0.99.0" +version = "0.100.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "572583d9b97f9d277e5c7607f8239a30e2e04d3ed3b47c87d1cb2152ae724073" +checksum = "ab2d131019373f0d0d1f2af0abd4f719739f6583c1b33965112455f643a910af" dependencies = [ "proc-macro2", "quote", @@ -203,9 +203,9 @@ dependencies = [ [[package]] name = "chalk-ir" -version = "0.99.0" +version = "0.100.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e60e0ef9c81dce1336a9ed3c76f08775f5b623151d96d85ba45f7b10de76d1c7" +checksum = "4f114996bda14c0213f014a4ef31a7867dcf5f539a3900477fc6b20138e7a17b" dependencies = [ "bitflags 2.7.0", "chalk-derive", @@ -213,9 +213,9 @@ dependencies = [ [[package]] name = "chalk-recursive" -version = "0.99.0" +version = "0.100.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a06350d614e22b03a69b8105e3541614450a7ea48bc58ecc6c6bd92731a3995" +checksum = "551e956e031c09057c7b21f17d48d91de99c9b6b6e34bceaf5e7202d71021268" dependencies = [ "chalk-derive", "chalk-ir", @@ -226,9 +226,9 @@ dependencies = [ [[package]] name = "chalk-solve" -version = "0.99.0" +version = "0.100.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e428761e9b55bee516bfe2457caed8b6d1b86353f92ae825bbe438a36ce91e8" +checksum = "cd7ca50181156ce649efe8e5dd00580f573651554e4dcd11afa4e2ac93f53324" dependencies = [ "chalk-derive", "chalk-ir", diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml index 1132acb647410..33a9a5695a066 100644 --- a/src/tools/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/Cargo.toml @@ -105,10 +105,10 @@ arrayvec = "0.7.4" bitflags = "2.4.1" cargo_metadata = "0.18.1" camino = "1.1.6" -chalk-solve = { version = "0.99.0", default-features = false } -chalk-ir = "0.99.0" -chalk-recursive = { version = "0.99.0", default-features = false } -chalk-derive = "0.99.0" +chalk-solve = { version = "0.100.0", default-features = false } +chalk-ir = "0.100.0" +chalk-recursive = { version = "0.100.0", default-features = false } +chalk-derive = "0.100.0" crossbeam-channel = "0.5.8" dissimilar = "1.0.7" dot = "0.1.4" diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs index c8ff6cba3dd18..67fb73696f766 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs @@ -708,6 +708,9 @@ fn well_known_trait_from_lang_item(item: LangItem) -> Option { LangItem::Fn => WellKnownTrait::Fn, LangItem::FnMut => WellKnownTrait::FnMut, LangItem::FnOnce => WellKnownTrait::FnOnce, + LangItem::AsyncFn => WellKnownTrait::AsyncFn, + LangItem::AsyncFnMut => WellKnownTrait::AsyncFnMut, + LangItem::AsyncFnOnce => WellKnownTrait::AsyncFnOnce, LangItem::Coroutine => WellKnownTrait::Coroutine, LangItem::Sized => WellKnownTrait::Sized, LangItem::Unpin => WellKnownTrait::Unpin, @@ -715,6 +718,7 @@ fn well_known_trait_from_lang_item(item: LangItem) -> Option { LangItem::Tuple => WellKnownTrait::Tuple, LangItem::PointeeTrait => WellKnownTrait::Pointee, LangItem::FnPtrTrait => WellKnownTrait::FnPtr, + LangItem::Future => WellKnownTrait::Future, _ => return None, }) } @@ -730,6 +734,9 @@ fn lang_item_from_well_known_trait(trait_: WellKnownTrait) -> LangItem { WellKnownTrait::Fn => LangItem::Fn, WellKnownTrait::FnMut => LangItem::FnMut, WellKnownTrait::FnOnce => LangItem::FnOnce, + WellKnownTrait::AsyncFn => LangItem::AsyncFn, + WellKnownTrait::AsyncFnMut => LangItem::AsyncFnMut, + WellKnownTrait::AsyncFnOnce => LangItem::AsyncFnOnce, WellKnownTrait::Coroutine => LangItem::Coroutine, WellKnownTrait::Sized => LangItem::Sized, WellKnownTrait::Tuple => LangItem::Tuple, @@ -737,6 +744,7 @@ fn lang_item_from_well_known_trait(trait_: WellKnownTrait) -> LangItem { WellKnownTrait::Unsize => LangItem::Unsize, WellKnownTrait::Pointee => LangItem::PointeeTrait, WellKnownTrait::FnPtr => LangItem::FnPtrTrait, + WellKnownTrait::Future => LangItem::Future, } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs index 50a1ecd006d8f..4c5cca21655d0 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs @@ -3861,3 +3861,42 @@ fn main() { "#]], ); } + +#[test] +fn regression_19196() { + check_infer( + r#" +//- minicore: async_fn +fn async_closure(f: F) {} +fn closure(f: F) {} + +fn main() { + async_closure(async |arg| { + arg; + }); + closure(|arg| { + arg; + }); +} +"#, + expect![[r#" + 38..39 'f': F + 44..46 '{}': () + 74..75 'f': F + 80..82 '{}': () + 94..191 '{ ... }); }': () + 100..113 'async_closure': fn async_closure impl Future>(impl AsyncFnOnce(i32) -> impl Future) + 100..147 'async_... })': () + 114..146 'async ... }': impl AsyncFnOnce(i32) -> impl Future + 121..124 'arg': i32 + 126..146 '{ ... }': () + 136..139 'arg': i32 + 153..160 'closure': fn closure(impl FnOnce(i32)) + 153..188 'closur... })': () + 161..187 '|arg| ... }': impl FnOnce(i32) + 162..165 'arg': i32 + 167..187 '{ ... }': () + 177..180 'arg': i32 + "#]], + ); +} diff --git a/src/tools/rust-analyzer/docs/book/src/assists_generated.md b/src/tools/rust-analyzer/docs/book/src/assists_generated.md index 918ae4a579443..a1433952e0ba1 100644 --- a/src/tools/rust-analyzer/docs/book/src/assists_generated.md +++ b/src/tools/rust-analyzer/docs/book/src/assists_generated.md @@ -1070,7 +1070,7 @@ pub use foo::{Bar, Baz}; ### `expand_record_rest_pattern` -**Source:** [expand_rest_pattern.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/expand_rest_pattern.rs#L24) +**Source:** [expand_rest_pattern.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/expand_rest_pattern.rs#L26) Fills fields by replacing rest pattern in record patterns. @@ -1094,7 +1094,7 @@ fn foo(bar: Bar) { ### `expand_tuple_struct_rest_pattern` -**Source:** [expand_rest_pattern.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/expand_rest_pattern.rs#L80) +**Source:** [expand_rest_pattern.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/expand_rest_pattern.rs#L82) Fills fields by replacing rest pattern in tuple struct patterns. From 0e4f189e80d6b8ec14cff20fba329a4332ce71a9 Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Sun, 9 Mar 2025 15:51:37 +0900 Subject: [PATCH 39/53] internal: Migrate `inline_local_variable` to `SyntaxEditor` --- .../src/handlers/inline_local_variable.rs | 66 ++++++++++--------- .../src/ast/syntax_factory/constructors.rs | 21 ++++++ 2 files changed, 55 insertions(+), 32 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs index cc7bea5152b66..0aa9970a72efe 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs @@ -5,7 +5,7 @@ use ide_db::{ EditionedFileId, RootDatabase, }; use syntax::{ - ast::{self, AstNode, AstToken, HasName}, + ast::{self, syntax_factory::SyntaxFactory, AstNode, AstToken, HasName}, SyntaxElement, TextRange, }; @@ -43,22 +43,6 @@ pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext<'_>) }?; let initializer_expr = let_stmt.initializer()?; - let delete_range = delete_let.then(|| { - if let Some(whitespace) = let_stmt - .syntax() - .next_sibling_or_token() - .and_then(SyntaxElement::into_token) - .and_then(ast::Whitespace::cast) - { - TextRange::new( - let_stmt.syntax().text_range().start(), - whitespace.syntax().text_range().end(), - ) - } else { - let_stmt.syntax().text_range() - } - }); - let wrap_in_parens = references .into_iter() .filter_map(|FileReference { range, name, .. }| match name { @@ -76,37 +60,55 @@ pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext<'_>) let usage_parent_option = usage_node.and_then(|it| it.parent()); let usage_parent = match usage_parent_option { Some(u) => u, - None => return Some((range, name_ref, false)), + None => return Some((name_ref, false)), }; - Some((range, name_ref, initializer_expr.needs_parens_in(&usage_parent))) + Some((name_ref, initializer_expr.needs_parens_in(&usage_parent))) }) .collect::>>()?; - let init_str = initializer_expr.syntax().text().to_string(); - let init_in_paren = format!("({init_str})"); - let target = match target { - ast::NameOrNameRef::Name(it) => it.syntax().text_range(), - ast::NameOrNameRef::NameRef(it) => it.syntax().text_range(), + ast::NameOrNameRef::Name(it) => it.syntax().clone(), + ast::NameOrNameRef::NameRef(it) => it.syntax().clone(), }; acc.add( AssistId("inline_local_variable", AssistKind::RefactorInline), "Inline variable", - target, + target.text_range(), move |builder| { - if let Some(range) = delete_range { - builder.delete(range); + let mut editor = builder.make_editor(&target); + if delete_let { + editor.delete(let_stmt.syntax()); + if let Some(whitespace) = let_stmt + .syntax() + .next_sibling_or_token() + .and_then(SyntaxElement::into_token) + .and_then(ast::Whitespace::cast) + { + editor.delete(whitespace.syntax()); + } } - for (range, name, should_wrap) in wrap_in_parens { - let replacement = if should_wrap { &init_in_paren } else { &init_str }; - if ast::RecordExprField::for_field_name(&name).is_some() { + + let make = SyntaxFactory::new(); + + for (name, should_wrap) in wrap_in_parens { + let replacement = if should_wrap { + make.expr_paren(initializer_expr.clone()).into() + } else { + initializer_expr.clone() + }; + + if let Some(record_field) = ast::RecordExprField::for_field_name(&name) { cov_mark::hit!(inline_field_shorthand); - builder.insert(range.end(), format!(": {replacement}")); + let replacement = make.record_expr_field(name, Some(replacement)); + editor.replace(record_field.syntax(), replacement.syntax()); } else { - builder.replace(range, replacement.clone()) + editor.replace(name.syntax(), replacement.syntax()); } } + + editor.add_mappings(make.finish_with_mappings()); + builder.add_file_edits(ctx.file_id(), editor); }, ) } diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs index 85393ca5b4ce0..44f13041c244f 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs @@ -783,6 +783,27 @@ impl SyntaxFactory { ast } + pub fn record_expr_field( + &self, + name: ast::NameRef, + expr: Option, + ) -> ast::RecordExprField { + let ast = make::record_expr_field(name.clone(), expr.clone()).clone_for_update(); + + if let Some(mut mapping) = self.mappings() { + let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone()); + + builder.map_node(name.syntax().clone(), ast.name_ref().unwrap().syntax().clone()); + if let Some(expr) = expr { + builder.map_node(expr.syntax().clone(), ast.expr().unwrap().syntax().clone()); + } + + builder.finish(&mut mapping); + } + + ast + } + pub fn record_field_list( &self, fields: impl IntoIterator, From 965a0c016677dad9ee8141e7a446ce376b7177c1 Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Sun, 9 Mar 2025 18:42:46 +0900 Subject: [PATCH 40/53] fix: Prevent wrong invocations of `needs_parens_in` with non-ancestral "parent"s --- .../src/handlers/apply_demorgan.rs | 14 +++-- .../src/handlers/inline_local_variable.rs | 54 +++++++++++++++- .../crates/syntax/src/ast/prec.rs | 63 ++++++++++++++++--- .../docs/book/src/assists_generated.md | 6 +- 4 files changed, 120 insertions(+), 17 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/apply_demorgan.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/apply_demorgan.rs index 77562c588e231..67bf8eed23df1 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/apply_demorgan.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/apply_demorgan.rs @@ -128,7 +128,9 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti let parent = neg_expr.syntax().parent(); editor = builder.make_editor(neg_expr.syntax()); - if parent.is_some_and(|parent| demorganed.needs_parens_in(&parent)) { + if parent.is_some_and(|parent| { + demorganed.needs_parens_in_place_of(&parent, neg_expr.syntax()) + }) { cov_mark::hit!(demorgan_keep_parens_for_op_precedence2); editor.replace(neg_expr.syntax(), make.expr_paren(demorganed).syntax()); } else { @@ -392,15 +394,19 @@ fn f() { !(S <= S || S < S) } #[test] fn demorgan_keep_pars_for_op_precedence3() { - check_assist(apply_demorgan, "fn f() { (a || !(b &&$0 c); }", "fn f() { (a || !b || !c; }"); + check_assist( + apply_demorgan, + "fn f() { (a || !(b &&$0 c); }", + "fn f() { (a || (!b || !c); }", + ); } #[test] - fn demorgan_removes_pars_in_eq_precedence() { + fn demorgan_keeps_pars_in_eq_precedence() { check_assist( apply_demorgan, "fn() { let x = a && !(!b |$0| !c); }", - "fn() { let x = a && b && c; }", + "fn() { let x = a && (b && c); }", ) } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs index 0aa9970a72efe..36eed290dc88d 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs @@ -57,12 +57,14 @@ pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext<'_>) } let usage_node = name_ref.syntax().ancestors().find(|it| ast::PathExpr::can_cast(it.kind())); - let usage_parent_option = usage_node.and_then(|it| it.parent()); + let usage_parent_option = usage_node.as_ref().and_then(|it| it.parent()); let usage_parent = match usage_parent_option { Some(u) => u, None => return Some((name_ref, false)), }; - Some((name_ref, initializer_expr.needs_parens_in(&usage_parent))) + let should_wrap = initializer_expr + .needs_parens_in_place_of(&usage_parent, usage_node.as_ref().unwrap()); + Some((name_ref, should_wrap)) }) .collect::>>()?; @@ -941,6 +943,54 @@ fn main() { fn main() { let _ = (|| 2)(); } +"#, + ); + } + + #[test] + fn test_wrap_in_parens() { + check_assist( + inline_local_variable, + r#" +fn main() { + let $0a = 123 < 456; + let b = !a; +} +"#, + r#" +fn main() { + let b = !(123 < 456); +} +"#, + ); + check_assist( + inline_local_variable, + r#" +trait Foo { + fn foo(&self); +} + +impl Foo for bool { + fn foo(&self) {} +} + +fn main() { + let $0a = 123 < 456; + let b = a.foo(); +} +"#, + r#" +trait Foo { + fn foo(&self); +} + +impl Foo for bool { + fn foo(&self) {} +} + +fn main() { + let b = (123 < 456).foo(); +} "#, ); } diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/prec.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/prec.rs index 0c4da7629926e..4f0e2cad1746f 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/prec.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/prec.rs @@ -1,5 +1,7 @@ //! Precedence representation. +use stdx::always; + use crate::{ ast::{self, BinaryOp, Expr, HasArgList, RangeItem}, match_ast, AstNode, SyntaxNode, @@ -140,6 +142,22 @@ pub fn precedence(expr: &ast::Expr) -> ExprPrecedence { } } +fn check_ancestry(ancestor: &SyntaxNode, descendent: &SyntaxNode) -> bool { + let bail = || always!(false, "{} is not an ancestor of {}", ancestor, descendent); + + if !ancestor.text_range().contains_range(descendent.text_range()) { + return bail(); + } + + for anc in descendent.ancestors() { + if anc == *ancestor { + return true; + } + } + + bail() +} + impl Expr { pub fn precedence(&self) -> ExprPrecedence { precedence(self) @@ -153,9 +171,19 @@ impl Expr { /// Returns `true` if `self` would need to be wrapped in parentheses given that its parent is `parent`. pub fn needs_parens_in(&self, parent: &SyntaxNode) -> bool { + self.needs_parens_in_place_of(parent, self.syntax()) + } + + /// Returns `true` if `self` would need to be wrapped in parentheses if it replaces `place_of` + /// given that `place_of`'s parent is `parent`. + pub fn needs_parens_in_place_of(&self, parent: &SyntaxNode, place_of: &SyntaxNode) -> bool { + if !check_ancestry(parent, place_of) { + return false; + } + match_ast! { match parent { - ast::Expr(e) => self.needs_parens_in_expr(&e), + ast::Expr(e) => self.needs_parens_in_expr(&e, place_of), ast::Stmt(e) => self.needs_parens_in_stmt(Some(&e)), ast::StmtList(_) => self.needs_parens_in_stmt(None), ast::ArgList(_) => false, @@ -165,7 +193,7 @@ impl Expr { } } - fn needs_parens_in_expr(&self, parent: &Expr) -> bool { + fn needs_parens_in_expr(&self, parent: &Expr, place_of: &SyntaxNode) -> bool { // Parentheses are necessary when calling a function-like pointer that is a member of a struct or union // (e.g. `(a.f)()`). let is_parent_call_expr = matches!(parent, ast::Expr::CallExpr(_)); @@ -199,13 +227,17 @@ impl Expr { if self.is_paren_like() || parent.is_paren_like() - || self.is_prefix() && (parent.is_prefix() || !self.is_ordered_before(parent)) - || self.is_postfix() && (parent.is_postfix() || self.is_ordered_before(parent)) + || self.is_prefix() + && (parent.is_prefix() + || !self.is_ordered_before_parent_in_place_of(parent, place_of)) + || self.is_postfix() + && (parent.is_postfix() + || self.is_ordered_before_parent_in_place_of(parent, place_of)) { return false; } - let (left, right, inv) = match self.is_ordered_before(parent) { + let (left, right, inv) = match self.is_ordered_before_parent_in_place_of(parent, place_of) { true => (self, parent, false), false => (parent, self, true), }; @@ -413,13 +445,28 @@ impl Expr { } } - fn is_ordered_before(&self, other: &Expr) -> bool { + fn is_ordered_before_parent_in_place_of(&self, parent: &Expr, place_of: &SyntaxNode) -> bool { + use rowan::TextSize; use Expr::*; - return order(self) < order(other); + let self_range = self.syntax().text_range(); + let place_of_range = place_of.text_range(); + + let self_order_adjusted = order(self) - self_range.start() + place_of_range.start(); + + let parent_order = order(parent); + let parent_order_adjusted = if parent_order <= place_of_range.start() { + parent_order + } else if parent_order >= place_of_range.end() { + parent_order - place_of_range.len() + self_range.len() + } else { + return false; + }; + + return self_order_adjusted < parent_order_adjusted; /// Returns text range that can be used to compare two expression for order (which goes first). - fn order(this: &Expr) -> rowan::TextSize { + fn order(this: &Expr) -> TextSize { // For non-paren-like operators: get the operator itself let token = match this { RangeExpr(e) => e.op_token(), diff --git a/src/tools/rust-analyzer/docs/book/src/assists_generated.md b/src/tools/rust-analyzer/docs/book/src/assists_generated.md index 918ae4a579443..9a80185179279 100644 --- a/src/tools/rust-analyzer/docs/book/src/assists_generated.md +++ b/src/tools/rust-analyzer/docs/book/src/assists_generated.md @@ -306,7 +306,7 @@ fn main() { ### `apply_demorgan_iterator` -**Source:** [apply_demorgan.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/apply_demorgan.rs#L154) +**Source:** [apply_demorgan.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/apply_demorgan.rs#L156) Apply [De Morgan's law](https://en.wikipedia.org/wiki/De_Morgan%27s_laws) to `Iterator::all` and `Iterator::any`. @@ -1070,7 +1070,7 @@ pub use foo::{Bar, Baz}; ### `expand_record_rest_pattern` -**Source:** [expand_rest_pattern.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/expand_rest_pattern.rs#L24) +**Source:** [expand_rest_pattern.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/expand_rest_pattern.rs#L26) Fills fields by replacing rest pattern in record patterns. @@ -1094,7 +1094,7 @@ fn foo(bar: Bar) { ### `expand_tuple_struct_rest_pattern` -**Source:** [expand_rest_pattern.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/expand_rest_pattern.rs#L80) +**Source:** [expand_rest_pattern.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/expand_rest_pattern.rs#L82) Fills fields by replacing rest pattern in tuple struct patterns. From e1912f8fa9b281a2d1ccd9f89082ecd724d7a4ba Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sun, 9 Mar 2025 15:36:53 +0100 Subject: [PATCH 41/53] Rank ADT constructors as constructors for completion scoring --- .../crates/ide-completion/src/render.rs | 104 ++++++++++++++++-- .../ide-completion/src/render/literal.rs | 10 +- 2 files changed, 102 insertions(+), 12 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs index 4f6c4cb663930..a61389ac55ac9 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs @@ -1151,6 +1151,24 @@ fn main() { Foo::Fo$0 } ), lookup: "Foo{}", detail: "Foo { x: i32, y: i32 }", + relevance: CompletionRelevance { + exact_name_match: false, + type_match: None, + is_local: false, + trait_: None, + is_name_already_imported: false, + requires_import: false, + is_private_editable: false, + postfix_match: None, + function: Some( + CompletionRelevanceFn { + has_params: true, + has_self_param: false, + return_type: DirectConstructor, + }, + ), + is_skipping_completion: false, + }, trigger_call_info: true, }, ] @@ -1183,6 +1201,24 @@ fn main() { Foo::Fo$0 } ), lookup: "Foo()", detail: "Foo(i32, i32)", + relevance: CompletionRelevance { + exact_name_match: false, + type_match: None, + is_local: false, + trait_: None, + is_name_already_imported: false, + requires_import: false, + is_private_editable: false, + postfix_match: None, + function: Some( + CompletionRelevanceFn { + has_params: true, + has_self_param: false, + return_type: DirectConstructor, + }, + ), + is_skipping_completion: false, + }, trigger_call_info: true, }, ] @@ -1261,6 +1297,24 @@ fn main() { Foo::Fo$0 } Variant, ), detail: "Foo", + relevance: CompletionRelevance { + exact_name_match: false, + type_match: None, + is_local: false, + trait_: None, + is_name_already_imported: false, + requires_import: false, + is_private_editable: false, + postfix_match: None, + function: Some( + CompletionRelevanceFn { + has_params: false, + has_self_param: false, + return_type: DirectConstructor, + }, + ), + is_skipping_completion: false, + }, trigger_call_info: true, }, ] @@ -1335,7 +1389,13 @@ fn main() { let _: m::Spam = S$0 } requires_import: false, is_private_editable: false, postfix_match: None, - function: None, + function: Some( + CompletionRelevanceFn { + has_params: true, + has_self_param: false, + return_type: DirectConstructor, + }, + ), is_skipping_completion: false, }, trigger_call_info: true, @@ -1365,7 +1425,13 @@ fn main() { let _: m::Spam = S$0 } requires_import: false, is_private_editable: false, postfix_match: None, - function: None, + function: Some( + CompletionRelevanceFn { + has_params: false, + has_self_param: false, + return_type: DirectConstructor, + }, + ), is_skipping_completion: false, }, trigger_call_info: true, @@ -1590,6 +1656,24 @@ use self::E::*; documentation: Documentation( "variant docs", ), + relevance: CompletionRelevance { + exact_name_match: false, + type_match: None, + is_local: false, + trait_: None, + is_name_already_imported: false, + requires_import: false, + is_private_editable: false, + postfix_match: None, + function: Some( + CompletionRelevanceFn { + has_params: false, + has_self_param: false, + return_type: DirectConstructor, + }, + ), + is_skipping_completion: false, + }, trigger_call_info: true, }, CompletionItem { @@ -2081,8 +2165,8 @@ fn main() { } "#, expect![[r#" - lc ssss S [type+local] st S S [type] + lc ssss S [type+local] st S S [type] ex ssss [type] ex S [type] @@ -2153,14 +2237,14 @@ fn main() { } "#, expect![[r#" + st S S [] + st &S [type] ex core::ops::Deref::deref(&t) [type_could_unify] lc m i32 [local] lc t T [local] lc &t [type+local] st S S [] st &S [type] - st S S [] - st &S [type] st T T [] st &T [type] fn foo(…) fn(&S) [] @@ -2202,14 +2286,14 @@ fn main() { } "#, expect![[r#" + st S S [] + st &mut S [type] ex core::ops::DerefMut::deref_mut(&mut t) [type_could_unify] lc m i32 [local] lc t T [local] lc &mut t [type+local] st S S [] st &mut S [type] - st S S [] - st &mut S [type] st T T [] st &mut T [type] fn foo(…) fn(&mut S) [] @@ -2306,9 +2390,9 @@ fn main() { } "#, expect![[r#" - ex core::ops::Deref::deref(&bar()) [type_could_unify] st S S [] st &S [type] + ex core::ops::Deref::deref(&bar()) [type_could_unify] st S S [] st &S [type] st T T [] @@ -2827,11 +2911,11 @@ fn foo() { } "#, expect![[r#" + ev Foo::B Foo::B [type_could_unify] + ev Foo::A(…) Foo::A(T) [type_could_unify] lc foo Foo [type+local] ex foo [type] ex Foo::B [type] - ev Foo::A(…) Foo::A(T) [type_could_unify] - ev Foo::B Foo::B [type_could_unify] en Foo Foo<{unknown}> [type_could_unify] fn foo() fn() [] fn bar() fn() -> Foo [] diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs index aab54ca5e0146..9e2bb8db54abd 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs @@ -8,7 +8,7 @@ use ide_db::{ use crate::{ context::{CompletionContext, PathCompletionCtx, PathKind}, - item::{Builder, CompletionItem}, + item::{Builder, CompletionItem, CompletionRelevanceFn}, render::{ compute_type_match, variant::{ @@ -17,7 +17,7 @@ use crate::{ }, RenderContext, }, - CompletionItemKind, CompletionRelevance, + CompletionItemKind, CompletionRelevance, CompletionRelevanceReturnType, }; pub(crate) fn render_variant_lit( @@ -131,6 +131,12 @@ fn render( let ty = thing.ty(db); item.set_relevance(CompletionRelevance { type_match: compute_type_match(ctx.completion, &ty), + // function is a misnomer here, this is more about constructor information + function: Some(CompletionRelevanceFn { + has_params: !fields.is_empty(), + has_self_param: false, + return_type: CompletionRelevanceReturnType::DirectConstructor, + }), ..ctx.completion_relevance() }); From 295c70ef03d442c608d0dda0c14c06598c034411 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sun, 9 Mar 2025 13:03:06 -0400 Subject: [PATCH 42/53] Fix O(tests) stack usage in edition 2024 mergeable doctests --- src/librustdoc/doctest/runner.rs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/librustdoc/doctest/runner.rs b/src/librustdoc/doctest/runner.rs index 234f40c6c1ab2..5ff90efe77c29 100644 --- a/src/librustdoc/doctest/runner.rs +++ b/src/librustdoc/doctest/runner.rs @@ -45,11 +45,8 @@ impl DocTestRunner { self.crate_attrs.insert(line.to_string()); } } - if !self.ids.is_empty() { - self.ids.push(','); - } self.ids.push_str(&format!( - "{}::TEST", + "tests.push({}::TEST);\n", generate_mergeable_doctest( doctest, scraped_test, @@ -136,7 +133,11 @@ mod __doctest_mod {{ #[rustc_main] fn main() -> std::process::ExitCode {{ -const TESTS: [test::TestDescAndFn; {nb_tests}] = [{ids}]; +let tests = {{ + let mut tests = Vec::with_capacity({nb_tests}); + {ids} + tests +}}; let test_marker = std::ffi::OsStr::new(__doctest_mod::RUN_OPTION); let test_args = &[{test_args}]; const ENV_BIN: &'static str = \"RUSTDOC_DOCTEST_BIN_PATH\"; @@ -144,11 +145,11 @@ const ENV_BIN: &'static str = \"RUSTDOC_DOCTEST_BIN_PATH\"; if let Ok(binary) = std::env::var(ENV_BIN) {{ let _ = crate::__doctest_mod::BINARY_PATH.set(binary.into()); unsafe {{ std::env::remove_var(ENV_BIN); }} - return std::process::Termination::report(test::test_main(test_args, Vec::from(TESTS), None)); + return std::process::Termination::report(test::test_main(test_args, tests, None)); }} else if let Ok(nb_test) = std::env::var(__doctest_mod::RUN_OPTION) {{ if let Ok(nb_test) = nb_test.parse::() {{ - if let Some(test) = TESTS.get(nb_test) {{ - if let test::StaticTestFn(f) = test.testfn {{ + if let Some(test) = tests.get(nb_test) {{ + if let test::StaticTestFn(f) = &test.testfn {{ return std::process::Termination::report(f()); }} }} @@ -158,7 +159,7 @@ if let Ok(binary) = std::env::var(ENV_BIN) {{ eprintln!(\"WARNING: No rustdoc doctest environment variable provided so doctests will be run in \ the same process\"); -std::process::Termination::report(test::test_main(test_args, Vec::from(TESTS), None)) +std::process::Termination::report(test::test_main(test_args, tests, None)) }}", nb_tests = self.nb_tests, output = self.output, From 7ee9ce8480305fdb5362145f80d5a4abfe087d78 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 10 Mar 2025 07:19:14 +0100 Subject: [PATCH 43/53] Fix `path` macro hygiene --- src/tools/rust-analyzer/crates/hir-expand/src/lib.rs | 2 ++ src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs | 4 ++-- src/tools/rust-analyzer/crates/hir/src/lib.rs | 1 + src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs | 1 + 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs index 41603e3c92e3f..c1d808cbf2c5a 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs @@ -5,6 +5,8 @@ //! expansion. #![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] +pub use intern; + pub mod attrs; pub mod builtin; pub mod change; diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs b/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs index f0cf7ebf479f8..75b5861454056 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs @@ -388,7 +388,7 @@ macro_rules! __path { ($start:ident $(:: $seg:ident)*) => ({ $crate::__known_path!($start $(:: $seg)*); $crate::mod_path::ModPath::from_segments($crate::mod_path::PathKind::Abs, vec![ - $crate::name::Name::new_symbol_root(intern::sym::$start.clone()), $($crate::name::Name::new_symbol_root(intern::sym::$seg.clone()),)* + $crate::name::Name::new_symbol_root($crate::intern::sym::$start.clone()), $($crate::name::Name::new_symbol_root($crate::intern::sym::$seg.clone()),)* ]) }); } @@ -399,7 +399,7 @@ pub use crate::__path as path; macro_rules! __tool_path { ($start:ident $(:: $seg:ident)*) => ({ $crate::mod_path::ModPath::from_segments($crate::mod_path::PathKind::Plain, vec![ - $crate::name::Name::new_symbol_root(intern::sym::rust_analyzer.clone()), $crate::name::Name::new_symbol_root(intern::sym::$start.clone()), $($crate::name::Name::new_symbol_root(intern::sym::$seg.clone()),)* + $crate::name::Name::new_symbol_root($crate::intern::sym::rust_analyzer.clone()), $crate::name::Name::new_symbol_root($crate::intern::sym::$start.clone()), $($crate::name::Name::new_symbol_root($crate::intern::sym::$seg.clone()),)* ]) }); } diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 7549d54a544e8..cb667767d7375 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -139,6 +139,7 @@ pub use { }, hygiene::{marks_rev, SyntaxContextExt}, inert_attr_macro::AttributeTemplate, + mod_path::tool_path, name::Name, prettify_macro_expansion, proc_macro::{ProcMacros, ProcMacrosBuilder}, diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs index be0de6c936615..6b77c72cee897 100644 --- a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs +++ b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs @@ -185,6 +185,7 @@ define_symbols! { Clone, coerce_unsized, column, + completion, compile_error, concat_bytes, concat_idents, From fdee1c1455481516e61381dcd93a0adab2b64dbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Mon, 10 Mar 2025 10:41:28 +0200 Subject: [PATCH 44/53] Preparing for merge from rust-lang/rust --- src/tools/rust-analyzer/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/rust-version b/src/tools/rust-analyzer/rust-version index e24e08d0687d6..0db4be8ff639b 100644 --- a/src/tools/rust-analyzer/rust-version +++ b/src/tools/rust-analyzer/rust-version @@ -1 +1 @@ -daf59857d6d2b87af4b846316bf1561a6083ed51 +2c6a12ec44d0426c8939123c2f2cf27d2217de13 From 1483cb67d91f493c9e8599cc969a03ae1b846435 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Mon, 10 Mar 2025 10:07:03 +0100 Subject: [PATCH 45/53] Handle empty test suites in job summary report --- src/ci/citool/src/metrics.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/ci/citool/src/metrics.rs b/src/ci/citool/src/metrics.rs index 8548602b31cb7..83b3d5ceed05a 100644 --- a/src/ci/citool/src/metrics.rs +++ b/src/ci/citool/src/metrics.rs @@ -67,6 +67,10 @@ fn render_table(suites: BTreeMap) -> String { let mut table = "| Test suite | Passed ✅ | Ignored 🚫 | Failed ❌ |\n".to_string(); writeln!(table, "|:------|------:|------:|------:|").unwrap(); + fn compute_pct(value: f64, total: f64) -> f64 { + if total == 0.0 { 0.0 } else { value / total } + } + fn write_row( buffer: &mut String, name: &str, @@ -75,9 +79,9 @@ fn render_table(suites: BTreeMap) -> String { ) -> std::fmt::Result { let TestSuiteRecord { passed, ignored, failed } = record; let total = (record.passed + record.ignored + record.failed) as f64; - let passed_pct = ((*passed as f64) / total) * 100.0; - let ignored_pct = ((*ignored as f64) / total) * 100.0; - let failed_pct = ((*failed as f64) / total) * 100.0; + let passed_pct = compute_pct(*passed as f64, total) * 100.0; + let ignored_pct = compute_pct(*ignored as f64, total) * 100.0; + let failed_pct = compute_pct(*failed as f64, total) * 100.0; write!(buffer, "| {surround}{name}{surround} |")?; write!(buffer, " {surround}{passed} ({passed_pct:.0}%){surround} |")?; From ee79f3e9dc6a7ebcb371ab6213f4b4a74b4a3d72 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 10 Mar 2025 09:39:02 +0100 Subject: [PATCH 46/53] Run proc-macro server tests are separate CI job Touch tt --- .../rust-analyzer/.github/workflows/ci.yaml | 70 ++++++++++++------- 1 file changed, 45 insertions(+), 25 deletions(-) diff --git a/src/tools/rust-analyzer/.github/workflows/ci.yaml b/src/tools/rust-analyzer/.github/workflows/ci.yaml index 1b011c90d031b..7a6b43a053155 100644 --- a/src/tools/rust-analyzer/.github/workflows/ci.yaml +++ b/src/tools/rust-analyzer/.github/workflows/ci.yaml @@ -35,19 +35,48 @@ jobs: typescript: - 'editors/code/**' proc_macros: + - 'crates/tt/**' - 'crates/proc-macro-api/**' - 'crates/proc-macro-srv/**' - 'crates/proc-macro-srv-cli/**' - rust: + proc-macro-srv: needs: changes + if: github.repository == 'rust-lang/rust-analyzer' && needs.changes.outputs.proc_macros == 'true' + name: proc-macro-srv + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + + - name: Install Rust toolchain + run: | + rustup update --no-self-update nightly + rustup default nightly + rustup component add --toolchain nightly rust-src rustfmt + # https://github.com/actions-rust-lang/setup-rust-toolchain/blob/main/rust.json + - name: Install Rust Problem Matcher + if: matrix.os == 'ubuntu-latest' + run: echo "::add-matcher::.github/rust.json" + + - name: Cache Dependencies + uses: Swatinem/rust-cache@9bdad043e88c75890e36ad3bbc8d27f0090dd609 + + - name: Bump opt-level + if: matrix.os == 'ubuntu-latest' + run: sed -i '/\[profile.dev]/a opt-level=1' Cargo.toml + + - name: Test + run: cargo test --features sysroot-abi -p rust-analyzer -p proc-macro-srv -p proc-macro-srv-cli -p proc-macro-api -- --quiet + + rust: if: github.repository == 'rust-lang/rust-analyzer' name: Rust runs-on: ${{ matrix.os }} env: CC: deny_c - RUST_CHANNEL: "${{ needs.changes.outputs.proc_macros == 'true' && 'nightly' || 'stable' }}" - USE_SYSROOT_ABI: "${{ needs.changes.outputs.proc_macros == 'true' && '--features sysroot-abi' || '' }}" strategy: fail-fast: false @@ -62,9 +91,9 @@ jobs: - name: Install Rust toolchain run: | - rustup update --no-self-update ${{ env.RUST_CHANNEL }} - rustup default ${{ env.RUST_CHANNEL }} - rustup component add --toolchain ${{ env.RUST_CHANNEL }} rust-src + rustup update --no-self-update stable + rustup default stable + rustup component add --toolchain stable rust-src # We always use a nightly rustfmt, regardless of channel, because we need # --file-lines. rustup toolchain install nightly --profile minimal --component rustfmt @@ -75,8 +104,6 @@ jobs: - name: Cache Dependencies uses: Swatinem/rust-cache@9bdad043e88c75890e36ad3bbc8d27f0090dd609 - with: - key: ${{ env.RUST_CHANNEL }} - name: Bump opt-level if: matrix.os == 'ubuntu-latest' @@ -86,16 +113,16 @@ jobs: run: cargo codegen --check - name: Compile (tests) - run: cargo test --no-run --locked ${{ env.USE_SYSROOT_ABI }} + run: cargo test --no-run --locked # It's faster to `test` before `build` ¯\_(ツ)_/¯ - name: Compile (rust-analyzer) if: matrix.os == 'ubuntu-latest' - run: cargo build --quiet ${{ env.USE_SYSROOT_ABI }} + run: cargo build --quiet - name: Test if: matrix.os == 'ubuntu-latest' || matrix.os == 'windows-latest' || github.event_name == 'push' - run: cargo test ${{ env.USE_SYSROOT_ABI }} -- --nocapture --quiet + run: cargo test -- --quiet - name: Switch to stable toolchain run: | @@ -156,7 +183,7 @@ jobs: typescript: needs: changes - if: github.repository == 'rust-lang/rust-analyzer' + if: github.repository == 'rust-lang/rust-analyzer' && needs.changes.outputs.typescript == 'true' name: TypeScript strategy: fail-fast: false @@ -168,21 +195,18 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 - if: needs.changes.outputs.typescript == 'true' - name: Install Nodejs uses: actions/setup-node@v4 with: node-version: 22 - if: needs.changes.outputs.typescript == 'true' - name: Install xvfb - if: matrix.os == 'ubuntu-latest' && needs.changes.outputs.typescript == 'true' + if: matrix.os == 'ubuntu-latest' run: sudo apt-get install -y xvfb - run: npm ci working-directory: ./editors/code - if: needs.changes.outputs.typescript == 'true' # - run: npm audit || { sleep 10 && npm audit; } || { sleep 30 && npm audit; } # if: runner.os == 'Linux' @@ -191,27 +215,24 @@ jobs: # If this steps fails, your code's type integrity might be wrong at some places at TypeScript level. - run: npm run typecheck working-directory: ./editors/code - if: needs.changes.outputs.typescript == 'true' # You may fix the code automatically by running `npm run lint:fix` if this steps fails. - run: npm run lint working-directory: ./editors/code - if: needs.changes.outputs.typescript == 'true' # To fix this steps, please run `npm run format`. - run: npm run format:check working-directory: ./editors/code - if: needs.changes.outputs.typescript == 'true' - name: Run VS Code tests (Linux) - if: matrix.os == 'ubuntu-latest' && needs.changes.outputs.typescript == 'true' + if: matrix.os == 'ubuntu-latest' env: VSCODE_CLI: 1 run: xvfb-run npm test working-directory: ./editors/code - name: Run VS Code tests (Windows) - if: matrix.os == 'windows-latest' && needs.changes.outputs.typescript == 'true' + if: matrix.os == 'windows-latest' env: VSCODE_CLI: 1 run: npm test @@ -219,7 +240,6 @@ jobs: - run: npm run package --scripts-prepend-node-path working-directory: ./editors/code - if: needs.changes.outputs.typescript == 'true' typo-check: name: Typo Check @@ -241,7 +261,7 @@ jobs: run: typos conclusion: - needs: [rust, rust-cross, typescript, typo-check] + needs: [rust, rust-cross, typescript, typo-check, proc-macro-srv] # We need to ensure this job does *not* get skipped if its dependencies fail, # because a skipped job is considered a success by GitHub. So we have to # overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run @@ -256,5 +276,5 @@ jobs: run: | # Print the dependent jobs to see them in the CI log jq -C <<< '${{ toJson(needs) }}' - # Check if all jobs that we depend on (in the needs array) were successful. - jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}' + # Check if all jobs that we depend on (in the needs array) were successful (or have been skipped). + jq --exit-status 'all(.result == "success" or .result == "skipped")' <<< '${{ toJson(needs) }}' From 87d5bf2b9287287f59f015558e090fbe35d5292b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Mon, 10 Mar 2025 11:20:56 +0200 Subject: [PATCH 47/53] Bump rustc crates --- src/tools/rust-analyzer/Cargo.lock | 29 +++++++++---------- src/tools/rust-analyzer/Cargo.toml | 12 ++++---- .../rust-analyzer/crates/hir-ty/Cargo.toml | 1 - .../rust-analyzer/crates/hir-ty/src/lib.rs | 3 -- 4 files changed, 20 insertions(+), 25 deletions(-) diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index c57953ba65476..5ff46abcfe39f 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -626,7 +626,6 @@ dependencies = [ "oorandom", "project-model", "ra-ap-rustc_abi", - "ra-ap-rustc_hashes", "ra-ap-rustc_index", "ra-ap-rustc_pattern_analysis", "rustc-hash 2.0.0", @@ -1504,9 +1503,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_abi" -version = "0.98.0" +version = "0.100.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b42cccfff8091a4c3397736518774dbad619e82f8def6f70d8e46dbbe396007" +checksum = "f1651b0f7e8c3eb7c27a88f39d277e69c32bfe58e3be174d286c1a24d6a7a4d8" dependencies = [ "bitflags 2.7.0", "ra-ap-rustc_hashes", @@ -1516,18 +1515,18 @@ dependencies = [ [[package]] name = "ra-ap-rustc_hashes" -version = "0.98.0" +version = "0.100.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46d8bd34ed6552c8cac1764106ef5adbeef3e5c7700e0ceb4c83a47a631894fe" +checksum = "2bcd85e93dc0ea850bcfe7957a115957df799ccbc9eea488bdee5ec6780d212b" dependencies = [ "rustc-stable-hash", ] [[package]] name = "ra-ap-rustc_index" -version = "0.98.0" +version = "0.100.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93799e4dccbbd47f8b66bc0aa42effc1b7077aaee09d8a40b86b8d659b80c7b7" +checksum = "62b295fc0640cd9fe0ecab872ee4a17a96f90a3998ec9f0c4765e9b8415c12cc" dependencies = [ "ra-ap-rustc_index_macros", "smallvec", @@ -1535,9 +1534,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_index_macros" -version = "0.98.0" +version = "0.100.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30baa5d00f94ba437a9dcaf7ae074ebe4f367bb05a4c2835e0aa2e7af3463aac" +checksum = "c675f4257023aa933882906f13802cae287e88cc39ab13cbb96809083db0c801" dependencies = [ "proc-macro2", "quote", @@ -1546,9 +1545,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_lexer" -version = "0.98.0" +version = "0.100.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3004d1d1b50afe3e1f9cdd428a282da7ffbf5f26dd8bf04af0d651d44e4873d8" +checksum = "c8358702c2a510ea84ba5801ddc047d9ad9520902cfb0e6173277610cdce2c9c" dependencies = [ "memchr", "unicode-properties", @@ -1557,9 +1556,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_parse_format" -version = "0.98.0" +version = "0.100.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb57e5124a64aaaf92c06130fbc1b8e1d547b5a2a96081f1f848e31c211df5d2" +checksum = "b98f402011d46732c35c47bfd111dec0495747fef2ec900ddee7fe15d78449a7" dependencies = [ "ra-ap-rustc_index", "ra-ap-rustc_lexer", @@ -1567,9 +1566,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_pattern_analysis" -version = "0.98.0" +version = "0.100.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e427c3d30e4bdff28abd6b0ef3e6f4dfab44acd9468a4954eeff8717d8df8819" +checksum = "bef3ff73fa4653252ffe1d1e9177a446f49ef46d97140e4816b7ff2dad59ed53" dependencies = [ "ra-ap-rustc_index", "rustc-hash 2.0.0", diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml index 1132acb647410..70b654433463c 100644 --- a/src/tools/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/Cargo.toml @@ -85,12 +85,12 @@ vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" } vfs = { path = "./crates/vfs", version = "0.0.0" } edition = { path = "./crates/edition", version = "0.0.0" } -ra-ap-rustc_hashes = { version = "0.98", default-features = false } -ra-ap-rustc_lexer = { version = "0.98", default-features = false } -ra-ap-rustc_parse_format = { version = "0.98", default-features = false } -ra-ap-rustc_index = { version = "0.98", default-features = false } -ra-ap-rustc_abi = { version = "0.98", default-features = false } -ra-ap-rustc_pattern_analysis = { version = "0.98", default-features = false } +ra-ap-rustc_hashes = { version = "0.100", default-features = false } +ra-ap-rustc_lexer = { version = "0.100", default-features = false } +ra-ap-rustc_parse_format = { version = "0.100", default-features = false } +ra-ap-rustc_index = { version = "0.100", default-features = false } +ra-ap-rustc_abi = { version = "0.100", default-features = false } +ra-ap-rustc_pattern_analysis = { version = "0.100", default-features = false } # local crates that aren't published to crates.io. These should not have versions. diff --git a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml index 27849f3b449d3..1d12bee646c4f 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml +++ b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml @@ -35,7 +35,6 @@ indexmap.workspace = true rustc_apfloat = "0.2.0" ra-ap-rustc_abi.workspace = true -ra-ap-rustc_hashes.workspace = true ra-ap-rustc_index.workspace = true ra-ap-rustc_pattern_analysis.workspace = true diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs index e0dcc01821ec3..f636de479c41e 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs @@ -21,9 +21,6 @@ extern crate rustc_pattern_analysis; #[cfg(not(feature = "in-rust-tree"))] extern crate ra_ap_rustc_pattern_analysis as rustc_pattern_analysis; -#[cfg(not(feature = "in-rust-tree"))] -extern crate ra_ap_rustc_hashes as rustc_hashes; - mod builder; mod chalk_db; mod chalk_ext; From c372c55f2b9fa1997619f7569e3a88b9d8a92024 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Mon, 10 Mar 2025 11:21:03 +0200 Subject: [PATCH 48/53] Fix simd layout test --- src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs index 4d3896660b479..8b74b7328bd83 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs @@ -342,7 +342,7 @@ fn simd_types() { check_size_and_align( r#" #[repr(simd)] - struct SimdType(i64, i64); + struct SimdType([i64; 2]); struct Goal(SimdType); "#, "", From 1d983bf7941bb89985d53e741cabcf113912a40d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Mon, 10 Mar 2025 11:37:21 +0200 Subject: [PATCH 49/53] Format code --- .../rust-analyzer/crates/hir-ty/src/layout.rs | 78 ++++++++++--------- 1 file changed, 43 insertions(+), 35 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs index 2ac1792ba8684..ba36c279f7f00 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs @@ -6,9 +6,8 @@ use base_db::ra_salsa::Cycle; use chalk_ir::{AdtId, FloatTy, IntTy, TyKind, UintTy}; use hir_def::{ layout::{ - Float, Integer, LayoutCalculator, LayoutCalculatorError, - LayoutData, Primitive, ReprOptions, Scalar, StructKind, TargetDataLayout, - WrappingRange, + Float, Integer, LayoutCalculator, LayoutCalculatorError, LayoutData, Primitive, + ReprOptions, Scalar, StructKind, TargetDataLayout, WrappingRange, }, LocalFieldId, StructId, }; @@ -192,43 +191,52 @@ pub fn layout_of_ty_query( valid_range: WrappingRange { start: 0, end: 0x10FFFF }, }, ), - chalk_ir::Scalar::Int(i) => Layout::scalar(dl, scalar_unit( + chalk_ir::Scalar::Int(i) => Layout::scalar( dl, - Primitive::Int( - match i { - IntTy::Isize => dl.ptr_sized_integer(), - IntTy::I8 => Integer::I8, - IntTy::I16 => Integer::I16, - IntTy::I32 => Integer::I32, - IntTy::I64 => Integer::I64, - IntTy::I128 => Integer::I128, - }, - true, + scalar_unit( + dl, + Primitive::Int( + match i { + IntTy::Isize => dl.ptr_sized_integer(), + IntTy::I8 => Integer::I8, + IntTy::I16 => Integer::I16, + IntTy::I32 => Integer::I32, + IntTy::I64 => Integer::I64, + IntTy::I128 => Integer::I128, + }, + true, + ), ), - )), - chalk_ir::Scalar::Uint(i) => Layout::scalar(dl, scalar_unit( + ), + chalk_ir::Scalar::Uint(i) => Layout::scalar( dl, - Primitive::Int( - match i { - UintTy::Usize => dl.ptr_sized_integer(), - UintTy::U8 => Integer::I8, - UintTy::U16 => Integer::I16, - UintTy::U32 => Integer::I32, - UintTy::U64 => Integer::I64, - UintTy::U128 => Integer::I128, - }, - false, + scalar_unit( + dl, + Primitive::Int( + match i { + UintTy::Usize => dl.ptr_sized_integer(), + UintTy::U8 => Integer::I8, + UintTy::U16 => Integer::I16, + UintTy::U32 => Integer::I32, + UintTy::U64 => Integer::I64, + UintTy::U128 => Integer::I128, + }, + false, + ), ), - )), - chalk_ir::Scalar::Float(f) => Layout::scalar(dl, scalar_unit( + ), + chalk_ir::Scalar::Float(f) => Layout::scalar( dl, - Primitive::Float(match f { - FloatTy::F16 => Float::F16, - FloatTy::F32 => Float::F32, - FloatTy::F64 => Float::F64, - FloatTy::F128 => Float::F128, - }), - )), + scalar_unit( + dl, + Primitive::Float(match f { + FloatTy::F16 => Float::F16, + FloatTy::F32 => Float::F32, + FloatTy::F64 => Float::F64, + FloatTy::F128 => Float::F128, + }), + ), + ), }, TyKind::Tuple(len, tys) => { let kind = if *len == 0 { StructKind::AlwaysSized } else { StructKind::MaybeUnsized }; From 063ef18fdc10cb0eb49e1af855e1a8e807e73eed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Mon, 10 Mar 2025 18:12:34 +0800 Subject: [PATCH 50/53] Revert "Use workspace lints for crates in `compiler/` #138084" Revert to buy time to consider options that avoids breaking downstream usages of cargo on distributed `rustc-src` artifacts, where such cargo invocations fail due to inability to inherit `lints` from workspace root manifest's `workspace.lints` (this is only valid for the source rust-lang/rust workspace, but not really the distributed `rustc-src` artifacts). This breakage was reported in . This reverts commit 48caf81484b50dca5a5cebb614899a3df81ca898, reversing changes made to c6662879b27f5161e95f39395e3c9513a7b97028. --- Cargo.toml | 14 -------------- compiler/rustc/Cargo.toml | 3 --- compiler/rustc_abi/Cargo.toml | 3 --- compiler/rustc_abi/src/lib.rs | 1 + compiler/rustc_arena/Cargo.toml | 3 --- compiler/rustc_arena/src/lib.rs | 1 + compiler/rustc_ast/Cargo.toml | 3 --- compiler/rustc_ast/src/lib.rs | 1 + compiler/rustc_ast_ir/Cargo.toml | 3 --- compiler/rustc_ast_ir/src/lib.rs | 1 + compiler/rustc_ast_lowering/Cargo.toml | 3 --- compiler/rustc_ast_lowering/src/lib.rs | 1 + compiler/rustc_ast_passes/Cargo.toml | 3 --- compiler/rustc_ast_passes/src/lib.rs | 1 + compiler/rustc_ast_pretty/Cargo.toml | 3 --- compiler/rustc_ast_pretty/src/lib.rs | 1 + compiler/rustc_attr_data_structures/Cargo.toml | 3 --- compiler/rustc_attr_data_structures/src/lib.rs | 1 + compiler/rustc_attr_parsing/Cargo.toml | 3 --- compiler/rustc_attr_parsing/src/lib.rs | 1 + compiler/rustc_baked_icu_data/Cargo.toml | 3 --- compiler/rustc_baked_icu_data/src/lib.rs | 2 +- compiler/rustc_borrowck/Cargo.toml | 3 --- compiler/rustc_borrowck/src/lib.rs | 1 + compiler/rustc_builtin_macros/Cargo.toml | 7 ++++--- compiler/rustc_builtin_macros/src/lib.rs | 1 + compiler/rustc_codegen_llvm/Cargo.toml | 3 --- compiler/rustc_codegen_llvm/src/lib.rs | 1 + compiler/rustc_codegen_ssa/Cargo.toml | 3 --- compiler/rustc_codegen_ssa/src/lib.rs | 1 + compiler/rustc_const_eval/Cargo.toml | 3 --- compiler/rustc_const_eval/src/lib.rs | 1 + compiler/rustc_data_structures/Cargo.toml | 3 --- compiler/rustc_data_structures/src/graph/tests.rs | 4 ++-- .../src/obligation_forest/mod.rs | 2 +- compiler/rustc_data_structures/src/sync.rs | 2 +- .../rustc_data_structures/src/sync/parallel.rs | 2 +- .../rustc_data_structures/src/tagged_ptr/tests.rs | 2 +- compiler/rustc_driver/Cargo.toml | 3 --- compiler/rustc_driver_impl/Cargo.toml | 3 --- compiler/rustc_driver_impl/src/lib.rs | 1 + compiler/rustc_error_codes/Cargo.toml | 3 --- compiler/rustc_error_codes/src/lib.rs | 1 + compiler/rustc_error_messages/Cargo.toml | 3 --- compiler/rustc_error_messages/src/lib.rs | 1 + compiler/rustc_errors/Cargo.toml | 3 --- compiler/rustc_errors/src/lib.rs | 1 + compiler/rustc_expand/Cargo.toml | 3 --- compiler/rustc_expand/src/lib.rs | 1 + compiler/rustc_feature/Cargo.toml | 3 --- compiler/rustc_feature/src/lib.rs | 1 + compiler/rustc_fluent_macro/Cargo.toml | 3 --- compiler/rustc_fluent_macro/src/lib.rs | 1 + compiler/rustc_fs_util/Cargo.toml | 3 --- compiler/rustc_graphviz/Cargo.toml | 3 --- compiler/rustc_graphviz/src/lib.rs | 1 + compiler/rustc_hashes/Cargo.toml | 3 --- compiler/rustc_hir/Cargo.toml | 3 --- compiler/rustc_hir/src/lib.rs | 1 + compiler/rustc_hir_analysis/Cargo.toml | 3 --- compiler/rustc_hir_analysis/src/lib.rs | 1 + compiler/rustc_hir_pretty/Cargo.toml | 3 --- compiler/rustc_hir_pretty/src/lib.rs | 1 + compiler/rustc_hir_typeck/Cargo.toml | 3 --- compiler/rustc_hir_typeck/src/lib.rs | 1 + compiler/rustc_incremental/Cargo.toml | 3 --- compiler/rustc_incremental/src/lib.rs | 1 + compiler/rustc_index/Cargo.toml | 3 --- compiler/rustc_index/src/lib.rs | 1 + compiler/rustc_index_macros/Cargo.toml | 3 --- compiler/rustc_index_macros/src/newtype.rs | 2 +- compiler/rustc_infer/Cargo.toml | 3 --- compiler/rustc_infer/src/lib.rs | 1 + compiler/rustc_interface/Cargo.toml | 3 --- compiler/rustc_interface/src/lib.rs | 1 + compiler/rustc_lexer/Cargo.toml | 3 --- compiler/rustc_lexer/src/lib.rs | 1 + compiler/rustc_lint/Cargo.toml | 3 --- compiler/rustc_lint/src/lib.rs | 1 + compiler/rustc_lint_defs/Cargo.toml | 3 --- compiler/rustc_lint_defs/src/lib.rs | 4 ++++ compiler/rustc_llvm/Cargo.toml | 3 --- compiler/rustc_llvm/src/lib.rs | 1 + compiler/rustc_log/Cargo.toml | 3 --- compiler/rustc_macros/Cargo.toml | 3 --- compiler/rustc_macros/src/lib.rs | 1 + compiler/rustc_metadata/Cargo.toml | 3 --- compiler/rustc_metadata/src/lib.rs | 1 + compiler/rustc_middle/Cargo.toml | 3 --- compiler/rustc_middle/src/lib.rs | 1 + compiler/rustc_mir_build/Cargo.toml | 3 --- compiler/rustc_mir_build/src/lib.rs | 1 + compiler/rustc_mir_dataflow/Cargo.toml | 3 --- compiler/rustc_mir_dataflow/src/lib.rs | 1 + compiler/rustc_mir_transform/Cargo.toml | 3 --- compiler/rustc_mir_transform/src/lib.rs | 1 + compiler/rustc_monomorphize/Cargo.toml | 3 --- compiler/rustc_monomorphize/src/lib.rs | 1 + compiler/rustc_next_trait_solver/Cargo.toml | 3 --- compiler/rustc_next_trait_solver/src/lib.rs | 1 + compiler/rustc_parse/Cargo.toml | 2 -- compiler/rustc_parse/src/lib.rs | 1 + compiler/rustc_parse_format/Cargo.toml | 3 --- compiler/rustc_parse_format/src/lib.rs | 1 + compiler/rustc_passes/Cargo.toml | 3 --- compiler/rustc_passes/src/lib.rs | 1 + compiler/rustc_pattern_analysis/Cargo.toml | 3 --- compiler/rustc_pattern_analysis/src/lib.rs | 1 + .../rustc_pattern_analysis/tests/common/mod.rs | 14 +++++++------- compiler/rustc_privacy/Cargo.toml | 3 --- compiler/rustc_privacy/src/lib.rs | 1 + compiler/rustc_query_impl/Cargo.toml | 3 --- compiler/rustc_query_impl/src/lib.rs | 1 + compiler/rustc_query_system/Cargo.toml | 3 --- compiler/rustc_query_system/src/lib.rs | 1 + compiler/rustc_resolve/Cargo.toml | 3 --- compiler/rustc_resolve/src/lib.rs | 1 + compiler/rustc_sanitizers/Cargo.toml | 3 --- compiler/rustc_sanitizers/src/lib.rs | 1 + compiler/rustc_serialize/Cargo.toml | 3 --- compiler/rustc_serialize/src/lib.rs | 1 + compiler/rustc_session/Cargo.toml | 3 --- compiler/rustc_session/src/lib.rs | 1 + compiler/rustc_smir/Cargo.toml | 3 --- compiler/rustc_smir/src/lib.rs | 1 + compiler/rustc_span/Cargo.toml | 3 --- compiler/rustc_span/src/lib.rs | 1 + compiler/rustc_symbol_mangling/Cargo.toml | 3 --- compiler/rustc_symbol_mangling/src/lib.rs | 1 + compiler/rustc_target/Cargo.toml | 3 --- compiler/rustc_target/src/lib.rs | 1 + compiler/rustc_trait_selection/Cargo.toml | 3 --- compiler/rustc_trait_selection/src/lib.rs | 1 + compiler/rustc_traits/Cargo.toml | 3 --- compiler/rustc_traits/src/lib.rs | 1 + compiler/rustc_transmute/Cargo.toml | 3 --- compiler/rustc_transmute/src/lib.rs | 1 + compiler/rustc_ty_utils/Cargo.toml | 3 --- compiler/rustc_ty_utils/src/lib.rs | 1 + compiler/rustc_type_ir/Cargo.toml | 4 ++-- compiler/rustc_type_ir/src/lib.rs | 1 + compiler/rustc_type_ir_macros/Cargo.toml | 3 --- compiler/stable_mir/Cargo.toml | 3 --- src/bootstrap/src/core/builder/cargo.rs | 13 ++++--------- 144 files changed, 90 insertions(+), 252 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e2d032e080660..20a43aaaeeb37 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -63,20 +63,6 @@ exclude = [ "src/tools/x", ] -# These lints are applied to many crates in the workspace. In practice, this is -# all crates under `compiler/`. -# -# NOTE: rustc-specific lints (e.g. `rustc::internal`) aren't supported by -# Cargo. (Support for them is possibly blocked by #44690 (attributes for -# tools).) Those lints are instead specified for `compiler/` crates in -# `src/bootstrap/src/core/builder/cargo.rs`. -[workspace.lints.rust] -# FIXME(edition_2024): Change this to `-Wrust_2024_idioms` when all of the -# individual lints are satisfied. -keyword_idents_2024 = "warn" -unreachable_pub = "warn" -unsafe_op_in_unsafe_fn = "warn" - [profile.release.package.rustc-rayon-core] # The rustc fork of Rayon has deadlock detection code which intermittently # causes overflows in the CI (see https://github.com/rust-lang/rust/issues/90227) diff --git a/compiler/rustc/Cargo.toml b/compiler/rustc/Cargo.toml index 7af0b34d2dafc..f4caa3ef769d5 100644 --- a/compiler/rustc/Cargo.toml +++ b/compiler/rustc/Cargo.toml @@ -32,6 +32,3 @@ llvm = ['rustc_driver_impl/llvm'] max_level_info = ['rustc_driver_impl/max_level_info'] rustc_randomized_layouts = ['rustc_driver_impl/rustc_randomized_layouts'] # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_abi/Cargo.toml b/compiler/rustc_abi/Cargo.toml index 4713b3474bdb5..86dc84e2016d6 100644 --- a/compiler/rustc_abi/Cargo.toml +++ b/compiler/rustc_abi/Cargo.toml @@ -31,6 +31,3 @@ nightly = [ ] randomize = ["dep:rand", "dep:rand_xoshiro", "nightly"] # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 078b676e40ebf..1b73758200939 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -5,6 +5,7 @@ #![cfg_attr(feature = "nightly", feature(rustc_attrs))] #![cfg_attr(feature = "nightly", feature(rustdoc_internals))] #![cfg_attr(feature = "nightly", feature(step_trait))] +#![warn(unreachable_pub)] // tidy-alphabetical-end /*! ABI handling for rustc diff --git a/compiler/rustc_arena/Cargo.toml b/compiler/rustc_arena/Cargo.toml index 1a600f0ee3f88..bbcd8ea6d389d 100644 --- a/compiler/rustc_arena/Cargo.toml +++ b/compiler/rustc_arena/Cargo.toml @@ -7,6 +7,3 @@ edition = "2024" # tidy-alphabetical-start smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index 6aaac072e4b28..3b44e99635810 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -23,6 +23,7 @@ #![feature(maybe_uninit_slice)] #![feature(rustc_attrs)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use std::alloc::Layout; diff --git a/compiler/rustc_ast/Cargo.toml b/compiler/rustc_ast/Cargo.toml index 259b51689e420..902287d032802 100644 --- a/compiler/rustc_ast/Cargo.toml +++ b/compiler/rustc_ast/Cargo.toml @@ -18,6 +18,3 @@ smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } thin-vec = "0.2.12" tracing = "0.1" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs index 294c6c9ba7a50..6372c66050e7c 100644 --- a/compiler/rustc_ast/src/lib.rs +++ b/compiler/rustc_ast/src/lib.rs @@ -19,6 +19,7 @@ #![feature(never_type)] #![feature(rustdoc_internals)] #![feature(stmt_expr_attributes)] +#![warn(unreachable_pub)] // tidy-alphabetical-end pub mod util { diff --git a/compiler/rustc_ast_ir/Cargo.toml b/compiler/rustc_ast_ir/Cargo.toml index 668c45438d6d6..f54e9687d8c7f 100644 --- a/compiler/rustc_ast_ir/Cargo.toml +++ b/compiler/rustc_ast_ir/Cargo.toml @@ -19,6 +19,3 @@ nightly = [ "dep:rustc_macros", "dep:rustc_span", ] - -[lints] -workspace = true diff --git a/compiler/rustc_ast_ir/src/lib.rs b/compiler/rustc_ast_ir/src/lib.rs index 6d05cd18cec12..9884e191ea7bd 100644 --- a/compiler/rustc_ast_ir/src/lib.rs +++ b/compiler/rustc_ast_ir/src/lib.rs @@ -9,6 +9,7 @@ #![cfg_attr(feature = "nightly", allow(internal_features))] #![cfg_attr(feature = "nightly", feature(never_type))] #![cfg_attr(feature = "nightly", feature(rustc_attrs))] +#![warn(unreachable_pub)] // tidy-alphabetical-end #[cfg(feature = "nightly")] diff --git a/compiler/rustc_ast_lowering/Cargo.toml b/compiler/rustc_ast_lowering/Cargo.toml index 358963c79975f..2ec4f4b055514 100644 --- a/compiler/rustc_ast_lowering/Cargo.toml +++ b/compiler/rustc_ast_lowering/Cargo.toml @@ -28,6 +28,3 @@ smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } thin-vec = "0.2.12" tracing = "0.1" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 4cecc56909e59..1c4edd8348f44 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -38,6 +38,7 @@ #![feature(if_let_guard)] #![feature(let_chains)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use std::sync::Arc; diff --git a/compiler/rustc_ast_passes/Cargo.toml b/compiler/rustc_ast_passes/Cargo.toml index 5966308a2626c..c738cb2aa2fd4 100644 --- a/compiler/rustc_ast_passes/Cargo.toml +++ b/compiler/rustc_ast_passes/Cargo.toml @@ -20,6 +20,3 @@ rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } thin-vec = "0.2.12" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs index 093199cf34212..b4ed70d83e570 100644 --- a/compiler/rustc_ast_passes/src/lib.rs +++ b/compiler/rustc_ast_passes/src/lib.rs @@ -10,6 +10,7 @@ #![feature(iter_is_partitioned)] #![feature(let_chains)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end pub mod ast_validation; diff --git a/compiler/rustc_ast_pretty/Cargo.toml b/compiler/rustc_ast_pretty/Cargo.toml index b120bdc2f05e5..2634dd1fdf93e 100644 --- a/compiler/rustc_ast_pretty/Cargo.toml +++ b/compiler/rustc_ast_pretty/Cargo.toml @@ -12,6 +12,3 @@ rustc_lexer = { path = "../rustc_lexer" } rustc_span = { path = "../rustc_span" } thin-vec = "0.2.12" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_ast_pretty/src/lib.rs b/compiler/rustc_ast_pretty/src/lib.rs index 84d9ce278a21a..602ab69ee5b5d 100644 --- a/compiler/rustc_ast_pretty/src/lib.rs +++ b/compiler/rustc_ast_pretty/src/lib.rs @@ -3,6 +3,7 @@ #![doc(rust_logo)] #![feature(box_patterns)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end mod helpers; diff --git a/compiler/rustc_attr_data_structures/Cargo.toml b/compiler/rustc_attr_data_structures/Cargo.toml index 8fbc21f3ba28d..b18923c337ff8 100644 --- a/compiler/rustc_attr_data_structures/Cargo.toml +++ b/compiler/rustc_attr_data_structures/Cargo.toml @@ -14,6 +14,3 @@ rustc_serialize = {path = "../rustc_serialize"} rustc_span = {path = "../rustc_span"} thin-vec = "0.2.12" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_attr_data_structures/src/lib.rs b/compiler/rustc_attr_data_structures/src/lib.rs index be00d1c10e0c4..f4986d1d1872a 100644 --- a/compiler/rustc_attr_data_structures/src/lib.rs +++ b/compiler/rustc_attr_data_structures/src/lib.rs @@ -3,6 +3,7 @@ #![doc(rust_logo)] #![feature(let_chains)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end mod attributes; diff --git a/compiler/rustc_attr_parsing/Cargo.toml b/compiler/rustc_attr_parsing/Cargo.toml index 24b552e2de4b6..6b4ce957630ff 100644 --- a/compiler/rustc_attr_parsing/Cargo.toml +++ b/compiler/rustc_attr_parsing/Cargo.toml @@ -22,6 +22,3 @@ rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } thin-vec = "0.2.12" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_attr_parsing/src/lib.rs b/compiler/rustc_attr_parsing/src/lib.rs index 249e71ef70dcf..386f2c98447b4 100644 --- a/compiler/rustc_attr_parsing/src/lib.rs +++ b/compiler/rustc_attr_parsing/src/lib.rs @@ -80,6 +80,7 @@ #![doc(rust_logo)] #![feature(let_chains)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end #[macro_use] diff --git a/compiler/rustc_baked_icu_data/Cargo.toml b/compiler/rustc_baked_icu_data/Cargo.toml index 1480b59f1e029..cb0e145386b83 100644 --- a/compiler/rustc_baked_icu_data/Cargo.toml +++ b/compiler/rustc_baked_icu_data/Cargo.toml @@ -11,6 +11,3 @@ icu_locid_transform = "1.3.2" icu_provider = { version = "1.2", features = ["sync"] } zerovec = "0.10.0" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_baked_icu_data/src/lib.rs b/compiler/rustc_baked_icu_data/src/lib.rs index df9bee0ebf518..f86a9db61c600 100644 --- a/compiler/rustc_baked_icu_data/src/lib.rs +++ b/compiler/rustc_baked_icu_data/src/lib.rs @@ -23,9 +23,9 @@ // tidy-alphabetical-start #![allow(elided_lifetimes_in_paths)] #![allow(internal_features)] -#![allow(unreachable_pub)] // because this crate is mostly generated code #![doc(rust_logo)] #![feature(rustdoc_internals)] +// #![warn(unreachable_pub)] // don't use because this crate is mostly generated code // tidy-alphabetical-end mod data { diff --git a/compiler/rustc_borrowck/Cargo.toml b/compiler/rustc_borrowck/Cargo.toml index 15338eeb37a89..9e7d55180a233 100644 --- a/compiler/rustc_borrowck/Cargo.toml +++ b/compiler/rustc_borrowck/Cargo.toml @@ -27,6 +27,3 @@ rustc_traits = { path = "../rustc_traits" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } tracing = "0.1" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 4d3774682ce83..64a533e05ffd4 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -13,6 +13,7 @@ #![feature(rustdoc_internals)] #![feature(stmt_expr_attributes)] #![feature(try_blocks)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use std::borrow::Cow; diff --git a/compiler/rustc_builtin_macros/Cargo.toml b/compiler/rustc_builtin_macros/Cargo.toml index da3572eebeea0..b5f4f2efd1f5b 100644 --- a/compiler/rustc_builtin_macros/Cargo.toml +++ b/compiler/rustc_builtin_macros/Cargo.toml @@ -3,6 +3,10 @@ name = "rustc_builtin_macros" version = "0.0.0" edition = "2024" + +[lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(llvm_enzyme)'] } + [lib] doctest = false @@ -30,6 +34,3 @@ smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } thin-vec = "0.2.12" tracing = "0.1" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index c23ce1e5e4a2f..ca16583a45de7 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -18,6 +18,7 @@ #![feature(rustdoc_internals)] #![feature(string_from_utf8_lossy_owned)] #![feature(try_blocks)] +#![warn(unreachable_pub)] // tidy-alphabetical-end extern crate proc_macro; diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml index 1741c3bacc778..d3ce7c5a1130f 100644 --- a/compiler/rustc_codegen_llvm/Cargo.toml +++ b/compiler/rustc_codegen_llvm/Cargo.toml @@ -43,6 +43,3 @@ serde_json = "1" smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } tracing = "0.1" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 2f3c8c75b0bfa..e51d4852db280 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -19,6 +19,7 @@ #![feature(rustdoc_internals)] #![feature(slice_as_array)] #![feature(try_blocks)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use std::any::Any; diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index c00be0e992635..1346efcb87c2a 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -63,6 +63,3 @@ features = ["read_core", "elf", "macho", "pe", "xcoff", "unaligned", "archive", [target.'cfg(windows)'.dependencies.windows] version = "0.59.0" features = ["Win32_Globalization"] - -[lints] -workspace = true diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 8ad040324147f..4e758bfdec394 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -14,6 +14,7 @@ #![feature(rustdoc_internals)] #![feature(trait_alias)] #![feature(try_blocks)] +#![warn(unreachable_pub)] // tidy-alphabetical-end //! This crate contains codegen code that is used by all codegen backends (LLVM and others). diff --git a/compiler/rustc_const_eval/Cargo.toml b/compiler/rustc_const_eval/Cargo.toml index d76238a3992f0..a0cc2c65e6e03 100644 --- a/compiler/rustc_const_eval/Cargo.toml +++ b/compiler/rustc_const_eval/Cargo.toml @@ -26,6 +26,3 @@ rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_type_ir = { path = "../rustc_type_ir" } tracing = "0.1" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index da52d60ae59fd..ed5489652fba6 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -16,6 +16,7 @@ #![feature(unqualified_local_imports)] #![feature(yeet_expr)] #![warn(unqualified_local_imports)] +#![warn(unreachable_pub)] // tidy-alphabetical-end pub mod check_consts; diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml index b364ab0dde4f4..bdf5494f2107b 100644 --- a/compiler/rustc_data_structures/Cargo.toml +++ b/compiler/rustc_data_structures/Cargo.toml @@ -54,6 +54,3 @@ memmap2 = "0.2.1" [target.'cfg(not(target_has_atomic = "64"))'.dependencies] portable-atomic = "1.5.1" - -[lints] -workspace = true diff --git a/compiler/rustc_data_structures/src/graph/tests.rs b/compiler/rustc_data_structures/src/graph/tests.rs index e48b9686c260f..b69b9dbc4a8e6 100644 --- a/compiler/rustc_data_structures/src/graph/tests.rs +++ b/compiler/rustc_data_structures/src/graph/tests.rs @@ -3,7 +3,7 @@ use std::cmp::max; use super::*; use crate::fx::FxHashMap; -pub(super) struct TestGraph { +pub struct TestGraph { num_nodes: usize, start_node: usize, successors: FxHashMap>, @@ -11,7 +11,7 @@ pub(super) struct TestGraph { } impl TestGraph { - pub(super) fn new(start_node: usize, edges: &[(usize, usize)]) -> Self { + pub fn new(start_node: usize, edges: &[(usize, usize)]) -> Self { let mut graph = TestGraph { num_nodes: start_node + 1, start_node, diff --git a/compiler/rustc_data_structures/src/obligation_forest/mod.rs b/compiler/rustc_data_structures/src/obligation_forest/mod.rs index 8d19fc5f9ccf1..78d69a66edc8b 100644 --- a/compiler/rustc_data_structures/src/obligation_forest/mod.rs +++ b/compiler/rustc_data_structures/src/obligation_forest/mod.rs @@ -313,7 +313,7 @@ pub struct Error { mod helper { use super::*; - pub(super) type ObligationTreeIdGenerator = impl Iterator; + pub type ObligationTreeIdGenerator = impl Iterator; impl ObligationForest { pub fn new() -> ObligationForest { ObligationForest { diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs index 616a18a72ab7e..a1cc75c498503 100644 --- a/compiler/rustc_data_structures/src/sync.rs +++ b/compiler/rustc_data_structures/src/sync.rs @@ -88,7 +88,7 @@ mod mode { // Whether thread safety might be enabled. #[inline] - pub(super) fn might_be_dyn_thread_safe() -> bool { + pub fn might_be_dyn_thread_safe() -> bool { DYN_THREAD_SAFE_MODE.load(Ordering::Relaxed) != DYN_NOT_THREAD_SAFE } diff --git a/compiler/rustc_data_structures/src/sync/parallel.rs b/compiler/rustc_data_structures/src/sync/parallel.rs index 8ef8a3f358569..1ba631b862376 100644 --- a/compiler/rustc_data_structures/src/sync/parallel.rs +++ b/compiler/rustc_data_structures/src/sync/parallel.rs @@ -46,7 +46,7 @@ pub fn parallel_guard(f: impl FnOnce(&ParallelGuard) -> R) -> R { ret } -fn serial_join(oper_a: A, oper_b: B) -> (RA, RB) +pub fn serial_join(oper_a: A, oper_b: B) -> (RA, RB) where A: FnOnce() -> RA, B: FnOnce() -> RB, diff --git a/compiler/rustc_data_structures/src/tagged_ptr/tests.rs b/compiler/rustc_data_structures/src/tagged_ptr/tests.rs index 85b21a7c8ecdf..9c1e4cefa6923 100644 --- a/compiler/rustc_data_structures/src/tagged_ptr/tests.rs +++ b/compiler/rustc_data_structures/src/tagged_ptr/tests.rs @@ -7,7 +7,7 @@ use crate::stable_hasher::{HashStable, StableHasher}; /// A tag type used in [`TaggedRef`] tests. #[derive(Copy, Clone, Debug, PartialEq, Eq)] -enum Tag2 { +pub enum Tag2 { B00 = 0b00, B01 = 0b01, B10 = 0b10, diff --git a/compiler/rustc_driver/Cargo.toml b/compiler/rustc_driver/Cargo.toml index d27895a5e7a21..e3ee83512952a 100644 --- a/compiler/rustc_driver/Cargo.toml +++ b/compiler/rustc_driver/Cargo.toml @@ -10,6 +10,3 @@ crate-type = ["dylib"] # tidy-alphabetical-start rustc_driver_impl = { path = "../rustc_driver_impl" } # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index 4469fa4e1f3ad..8593d1faba264 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -79,6 +79,3 @@ rustc_randomized_layouts = [ 'rustc_middle/rustc_randomized_layouts' ] # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 6e4020c6eca18..a2ddff7183e60 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -16,6 +16,7 @@ #![feature(result_flattening)] #![feature(rustdoc_internals)] #![feature(try_blocks)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use std::cmp::max; diff --git a/compiler/rustc_error_codes/Cargo.toml b/compiler/rustc_error_codes/Cargo.toml index d89e4526016c6..55b4e89905126 100644 --- a/compiler/rustc_error_codes/Cargo.toml +++ b/compiler/rustc_error_codes/Cargo.toml @@ -6,6 +6,3 @@ edition = "2024" [dependencies] # tidy-alphabetical-start # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_error_codes/src/lib.rs b/compiler/rustc_error_codes/src/lib.rs index dfeef5a957d69..d53d5678832b7 100644 --- a/compiler/rustc_error_codes/src/lib.rs +++ b/compiler/rustc_error_codes/src/lib.rs @@ -6,6 +6,7 @@ #![deny(rustdoc::invalid_codeblock_attributes)] #![doc(rust_logo)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end // This higher-order macro defines the error codes that are in use. It is used diff --git a/compiler/rustc_error_messages/Cargo.toml b/compiler/rustc_error_messages/Cargo.toml index e9047ba16e501..578af7fc51d40 100644 --- a/compiler/rustc_error_messages/Cargo.toml +++ b/compiler/rustc_error_messages/Cargo.toml @@ -19,6 +19,3 @@ rustc_span = { path = "../rustc_span" } tracing = "0.1" unic-langid = { version = "0.9.0", features = ["macros"] } # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index a6fbbb29ccd3c..ba1c3e185c2d9 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -4,6 +4,7 @@ #![feature(rustc_attrs)] #![feature(rustdoc_internals)] #![feature(type_alias_impl_trait)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use std::borrow::Cow; diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml index fc39a726093a4..b11793c190a14 100644 --- a/compiler/rustc_errors/Cargo.toml +++ b/compiler/rustc_errors/Cargo.toml @@ -39,6 +39,3 @@ features = [ "Win32_Security", "Win32_System_Threading", ] - -[lints] -workspace = true diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 80e43ede4453a..86959b28e5381 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -25,6 +25,7 @@ #![feature(trait_alias)] #![feature(try_blocks)] #![feature(yeet_expr)] +#![warn(unreachable_pub)] // tidy-alphabetical-end extern crate self as rustc_errors; diff --git a/compiler/rustc_expand/Cargo.toml b/compiler/rustc_expand/Cargo.toml index f051ea0c2ac17..0ba139ea5cc57 100644 --- a/compiler/rustc_expand/Cargo.toml +++ b/compiler/rustc_expand/Cargo.toml @@ -29,6 +29,3 @@ smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } thin-vec = "0.2.12" tracing = "0.1" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index 4222c9fe90616..777044e3f33bf 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs @@ -13,6 +13,7 @@ #![feature(rustdoc_internals)] #![feature(try_blocks)] #![feature(yeet_expr)] +#![warn(unreachable_pub)] // tidy-alphabetical-end extern crate proc_macro as pm; diff --git a/compiler/rustc_feature/Cargo.toml b/compiler/rustc_feature/Cargo.toml index 1aaace75404bf..a5ae06473cbe3 100644 --- a/compiler/rustc_feature/Cargo.toml +++ b/compiler/rustc_feature/Cargo.toml @@ -10,6 +10,3 @@ rustc_span = { path = "../rustc_span" } serde = { version = "1.0.125", features = [ "derive" ] } serde_json = "1.0.59" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs index 25764755a8fc9..0b034a2ae1075 100644 --- a/compiler/rustc_feature/src/lib.rs +++ b/compiler/rustc_feature/src/lib.rs @@ -15,6 +15,7 @@ #![allow(internal_features)] #![doc(rust_logo)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end mod accepted; diff --git a/compiler/rustc_fluent_macro/Cargo.toml b/compiler/rustc_fluent_macro/Cargo.toml index 695e8b3fd5db9..ce76b2745eaad 100644 --- a/compiler/rustc_fluent_macro/Cargo.toml +++ b/compiler/rustc_fluent_macro/Cargo.toml @@ -16,6 +16,3 @@ quote = "1" syn = { version = "2", features = ["full"] } unic-langid = { version = "0.9.0", features = ["macros"] } # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_fluent_macro/src/lib.rs b/compiler/rustc_fluent_macro/src/lib.rs index c6e0484b92106..3ad51fa1e64d0 100644 --- a/compiler/rustc_fluent_macro/src/lib.rs +++ b/compiler/rustc_fluent_macro/src/lib.rs @@ -7,6 +7,7 @@ #![feature(proc_macro_span)] #![feature(rustdoc_internals)] #![feature(track_path)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use proc_macro::TokenStream; diff --git a/compiler/rustc_fs_util/Cargo.toml b/compiler/rustc_fs_util/Cargo.toml index 3518209ea5b7f..baca3bc7d49eb 100644 --- a/compiler/rustc_fs_util/Cargo.toml +++ b/compiler/rustc_fs_util/Cargo.toml @@ -6,6 +6,3 @@ edition = "2024" [dependencies] # tidy-alphabetical-start # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_graphviz/Cargo.toml b/compiler/rustc_graphviz/Cargo.toml index 2672a624eabe7..d84943760baeb 100644 --- a/compiler/rustc_graphviz/Cargo.toml +++ b/compiler/rustc_graphviz/Cargo.toml @@ -6,6 +6,3 @@ edition = "2024" [dependencies] # tidy-alphabetical-start # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_graphviz/src/lib.rs b/compiler/rustc_graphviz/src/lib.rs index c8f8fd5be0237..b5774f64b66b2 100644 --- a/compiler/rustc_graphviz/src/lib.rs +++ b/compiler/rustc_graphviz/src/lib.rs @@ -277,6 +277,7 @@ )] #![doc(rust_logo)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use std::borrow::Cow; diff --git a/compiler/rustc_hashes/Cargo.toml b/compiler/rustc_hashes/Cargo.toml index ff46696c4c06d..c7a273cff88c9 100644 --- a/compiler/rustc_hashes/Cargo.toml +++ b/compiler/rustc_hashes/Cargo.toml @@ -7,6 +7,3 @@ edition = "2024" # tidy-alphabetical-start rustc-stable-hash = { version = "0.1.0" } # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_hir/Cargo.toml b/compiler/rustc_hir/Cargo.toml index e45c49cd7dbf1..7ca8539845a04 100644 --- a/compiler/rustc_hir/Cargo.toml +++ b/compiler/rustc_hir/Cargo.toml @@ -21,6 +21,3 @@ smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } thin-vec = "0.2.12" tracing = "0.1" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 84d369f1eddb2..270d4fbec30f8 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -13,6 +13,7 @@ #![feature(never_type)] #![feature(rustc_attrs)] #![feature(variant_count)] +#![warn(unreachable_pub)] // tidy-alphabetical-end extern crate self as rustc_hir; diff --git a/compiler/rustc_hir_analysis/Cargo.toml b/compiler/rustc_hir_analysis/Cargo.toml index 99ced5ff0a91d..55a816a855af4 100644 --- a/compiler/rustc_hir_analysis/Cargo.toml +++ b/compiler/rustc_hir_analysis/Cargo.toml @@ -32,6 +32,3 @@ rustc_type_ir = { path = "../rustc_type_ir" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } tracing = "0.1" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 26a20690a95c4..50b0e32b95ebf 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -73,6 +73,7 @@ This API is completely unstable and subject to change. #![feature(slice_partition_dedup)] #![feature(try_blocks)] #![feature(unwrap_infallible)] +#![warn(unreachable_pub)] // tidy-alphabetical-end // These are used by Clippy. diff --git a/compiler/rustc_hir_pretty/Cargo.toml b/compiler/rustc_hir_pretty/Cargo.toml index bc6431d02712c..91da8cb3fc5fb 100644 --- a/compiler/rustc_hir_pretty/Cargo.toml +++ b/compiler/rustc_hir_pretty/Cargo.toml @@ -12,6 +12,3 @@ rustc_attr_data_structures = { path = "../rustc_attr_data_structures" } rustc_hir = { path = "../rustc_hir" } rustc_span = { path = "../rustc_span" } # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 0e3721126fb33..2572ff50eb74f 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -3,6 +3,7 @@ // tidy-alphabetical-start #![recursion_limit = "256"] +#![warn(unreachable_pub)] // tidy-alphabetical-end use std::cell::Cell; diff --git a/compiler/rustc_hir_typeck/Cargo.toml b/compiler/rustc_hir_typeck/Cargo.toml index 1d6486fb7dc0c..f1afb7b712d59 100644 --- a/compiler/rustc_hir_typeck/Cargo.toml +++ b/compiler/rustc_hir_typeck/Cargo.toml @@ -27,6 +27,3 @@ rustc_type_ir = { path = "../rustc_type_ir" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } tracing = "0.1" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 263fb84206e0b..8b9c2b4a6ca0f 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -8,6 +8,7 @@ #![feature(let_chains)] #![feature(never_type)] #![feature(try_blocks)] +#![warn(unreachable_pub)] // tidy-alphabetical-end mod _match; diff --git a/compiler/rustc_incremental/Cargo.toml b/compiler/rustc_incremental/Cargo.toml index 754881309bf5f..4939bfb3a1cdd 100644 --- a/compiler/rustc_incremental/Cargo.toml +++ b/compiler/rustc_incremental/Cargo.toml @@ -22,6 +22,3 @@ rustc_span = { path = "../rustc_span" } thin-vec = "0.2.12" tracing = "0.1" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_incremental/src/lib.rs b/compiler/rustc_incremental/src/lib.rs index 299ee4876389c..563ed7614c609 100644 --- a/compiler/rustc_incremental/src/lib.rs +++ b/compiler/rustc_incremental/src/lib.rs @@ -7,6 +7,7 @@ #![doc(rust_logo)] #![feature(file_buffered)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end mod assert_dep_graph; diff --git a/compiler/rustc_index/Cargo.toml b/compiler/rustc_index/Cargo.toml index ee6fe11f9a5be..3d83a3c98daf8 100644 --- a/compiler/rustc_index/Cargo.toml +++ b/compiler/rustc_index/Cargo.toml @@ -21,6 +21,3 @@ nightly = [ ] rustc_randomized_layouts = [] # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_index/src/lib.rs b/compiler/rustc_index/src/lib.rs index cc680838e7e7b..3441a5f65c785 100644 --- a/compiler/rustc_index/src/lib.rs +++ b/compiler/rustc_index/src/lib.rs @@ -4,6 +4,7 @@ #![cfg_attr(feature = "nightly", feature(extend_one, step_trait, test))] #![cfg_attr(feature = "nightly", feature(new_range_api))] #![cfg_attr(feature = "nightly", feature(new_zeroed_alloc))] +#![warn(unreachable_pub)] // tidy-alphabetical-end pub mod bit_set; diff --git a/compiler/rustc_index_macros/Cargo.toml b/compiler/rustc_index_macros/Cargo.toml index de100bd0e2c16..891e7ded61996 100644 --- a/compiler/rustc_index_macros/Cargo.toml +++ b/compiler/rustc_index_macros/Cargo.toml @@ -13,6 +13,3 @@ quote = "1" [features] nightly = [] - -[lints] -workspace = true diff --git a/compiler/rustc_index_macros/src/newtype.rs b/compiler/rustc_index_macros/src/newtype.rs index f0b58eabbff9a..67ec776113399 100644 --- a/compiler/rustc_index_macros/src/newtype.rs +++ b/compiler/rustc_index_macros/src/newtype.rs @@ -305,7 +305,7 @@ impl Parse for Newtype { } } -pub(crate) fn newtype(input: proc_macro::TokenStream) -> proc_macro::TokenStream { +pub fn newtype(input: proc_macro::TokenStream) -> proc_macro::TokenStream { let input = parse_macro_input!(input as Newtype); input.0.into() } diff --git a/compiler/rustc_infer/Cargo.toml b/compiler/rustc_infer/Cargo.toml index 242886a92482c..08c0361488493 100644 --- a/compiler/rustc_infer/Cargo.toml +++ b/compiler/rustc_infer/Cargo.toml @@ -21,6 +21,3 @@ smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } thin-vec = "0.2.12" tracing = "0.1" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index ece18f4ea64ee..a04b2bb2b08b5 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -24,6 +24,7 @@ #![feature(let_chains)] #![feature(rustdoc_internals)] #![recursion_limit = "512"] // For rustdoc +#![warn(unreachable_pub)] // tidy-alphabetical-end mod errors; diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml index add8c0e20e634..9c9660cf50469 100644 --- a/compiler/rustc_interface/Cargo.toml +++ b/compiler/rustc_interface/Cargo.toml @@ -56,6 +56,3 @@ tracing = "0.1" # tidy-alphabetical-start llvm = ['dep:rustc_codegen_llvm'] # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs index 67e0be93523d9..54cd341698f0b 100644 --- a/compiler/rustc_interface/src/lib.rs +++ b/compiler/rustc_interface/src/lib.rs @@ -4,6 +4,7 @@ #![feature(iter_intersperse)] #![feature(let_chains)] #![feature(try_blocks)] +#![warn(unreachable_pub)] // tidy-alphabetical-end mod callbacks; diff --git a/compiler/rustc_lexer/Cargo.toml b/compiler/rustc_lexer/Cargo.toml index b9b16eebc5489..448a50faf458e 100644 --- a/compiler/rustc_lexer/Cargo.toml +++ b/compiler/rustc_lexer/Cargo.toml @@ -24,6 +24,3 @@ features = ["emoji"] [dev-dependencies] expect-test = "1.4.0" - -[lints] -workspace = true diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index 61638e45253fd..bf18845a0830d 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -23,6 +23,7 @@ // We want to be able to build this crate with a stable compiler, // so no `#![feature]` attributes should be added. #![deny(unstable_features)] +#![warn(unreachable_pub)] // tidy-alphabetical-end mod cursor; diff --git a/compiler/rustc_lint/Cargo.toml b/compiler/rustc_lint/Cargo.toml index f6c10aa974418..d6014f5006ad0 100644 --- a/compiler/rustc_lint/Cargo.toml +++ b/compiler/rustc_lint/Cargo.toml @@ -28,6 +28,3 @@ smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } tracing = "0.1" unicode-security = "0.1.0" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 35867d8c9efef..7018774e5c6bc 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -32,6 +32,7 @@ #![feature(rustc_attrs)] #![feature(rustdoc_internals)] #![feature(try_blocks)] +#![warn(unreachable_pub)] // tidy-alphabetical-end mod async_closures; diff --git a/compiler/rustc_lint_defs/Cargo.toml b/compiler/rustc_lint_defs/Cargo.toml index f9b45a00ec104..9ab350daf69d7 100644 --- a/compiler/rustc_lint_defs/Cargo.toml +++ b/compiler/rustc_lint_defs/Cargo.toml @@ -15,6 +15,3 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } serde = { version = "1.0.125", features = ["derive"] } # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 46b4b1d438386..e564235c41a5e 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -1,3 +1,7 @@ +// tidy-alphabetical-start +#![warn(unreachable_pub)] +// tidy-alphabetical-end + use rustc_abi::ExternAbi; use rustc_ast::AttrId; use rustc_ast::attr::AttributeExt; diff --git a/compiler/rustc_llvm/Cargo.toml b/compiler/rustc_llvm/Cargo.toml index dcfaf9a0282e6..061562b2ec5ed 100644 --- a/compiler/rustc_llvm/Cargo.toml +++ b/compiler/rustc_llvm/Cargo.toml @@ -14,6 +14,3 @@ libc = "0.2.73" # pinned `cc` in `rustc_codegen_ssa` if you update `cc` here. cc = "=1.2.16" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_llvm/src/lib.rs b/compiler/rustc_llvm/src/lib.rs index 68058250a2671..eda9b2b1fc092 100644 --- a/compiler/rustc_llvm/src/lib.rs +++ b/compiler/rustc_llvm/src/lib.rs @@ -4,6 +4,7 @@ #![doc(rust_logo)] #![feature(extern_types)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use std::cell::RefCell; diff --git a/compiler/rustc_log/Cargo.toml b/compiler/rustc_log/Cargo.toml index 665ebd52f4745..30f6e9ba8053f 100644 --- a/compiler/rustc_log/Cargo.toml +++ b/compiler/rustc_log/Cargo.toml @@ -20,6 +20,3 @@ rustc_span = { path = "../rustc_span" } # tidy-alphabetical-start max_level_info = ['tracing/max_level_info'] # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_macros/Cargo.toml b/compiler/rustc_macros/Cargo.toml index b937f75e892ae..f9d3b75835907 100644 --- a/compiler/rustc_macros/Cargo.toml +++ b/compiler/rustc_macros/Cargo.toml @@ -13,6 +13,3 @@ quote = "1" syn = { version = "2.0.9", features = ["full"] } synstructure = "0.13.0" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index 44ba064dd824c..34fc0f00320c0 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -6,6 +6,7 @@ #![feature(proc_macro_diagnostic)] #![feature(proc_macro_span)] #![feature(proc_macro_tracked_env)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use proc_macro::TokenStream; diff --git a/compiler/rustc_metadata/Cargo.toml b/compiler/rustc_metadata/Cargo.toml index 5fa3047d14e0b..a8821640f048e 100644 --- a/compiler/rustc_metadata/Cargo.toml +++ b/compiler/rustc_metadata/Cargo.toml @@ -31,6 +31,3 @@ rustc_type_ir = { path = "../rustc_type_ir" } tempfile = "3.2" tracing = "0.1" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index 8898c5824fa25..ebcc0efd5a67a 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -15,6 +15,7 @@ #![feature(proc_macro_internals)] #![feature(rustdoc_internals)] #![feature(trusted_len)] +#![warn(unreachable_pub)] // tidy-alphabetical-end extern crate proc_macro; diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml index 3a6216e63a9a6..43c1af642dd56 100644 --- a/compiler/rustc_middle/Cargo.toml +++ b/compiler/rustc_middle/Cargo.toml @@ -43,6 +43,3 @@ tracing = "0.1" # tidy-alphabetical-start rustc_randomized_layouts = [] # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 8fe2cc7101ba3..48ea7df5c23fd 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -61,6 +61,7 @@ #![feature(try_trait_v2_yeet)] #![feature(type_alias_impl_trait)] #![feature(yeet_expr)] +#![warn(unreachable_pub)] // tidy-alphabetical-end #[cfg(test)] diff --git a/compiler/rustc_mir_build/Cargo.toml b/compiler/rustc_mir_build/Cargo.toml index a29c011626647..d70d70a31a4a7 100644 --- a/compiler/rustc_mir_build/Cargo.toml +++ b/compiler/rustc_mir_build/Cargo.toml @@ -28,6 +28,3 @@ rustc_span = { path = "../rustc_span" } rustc_trait_selection = { path = "../rustc_trait_selection" } tracing = "0.1" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs index 8e96d46dac272..fa5db32d9134c 100644 --- a/compiler/rustc_mir_build/src/lib.rs +++ b/compiler/rustc_mir_build/src/lib.rs @@ -8,6 +8,7 @@ #![feature(if_let_guard)] #![feature(let_chains)] #![feature(try_blocks)] +#![warn(unreachable_pub)] // tidy-alphabetical-end // The `builder` module used to be named `build`, but that was causing GitHub's diff --git a/compiler/rustc_mir_dataflow/Cargo.toml b/compiler/rustc_mir_dataflow/Cargo.toml index a171f9641bb60..293bcbef21b85 100644 --- a/compiler/rustc_mir_dataflow/Cargo.toml +++ b/compiler/rustc_mir_dataflow/Cargo.toml @@ -21,6 +21,3 @@ rustc_span = { path = "../rustc_span" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } tracing = "0.1" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index a0efc623b8e7e..a8a56baa1ffc0 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -7,6 +7,7 @@ #![feature(let_chains)] #![feature(never_type)] #![feature(try_blocks)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use rustc_middle::ty; diff --git a/compiler/rustc_mir_transform/Cargo.toml b/compiler/rustc_mir_transform/Cargo.toml index 4dc91723f03fa..fb8d0ac5e74ac 100644 --- a/compiler/rustc_mir_transform/Cargo.toml +++ b/compiler/rustc_mir_transform/Cargo.toml @@ -30,6 +30,3 @@ rustc_type_ir = { path = "../rustc_type_ir" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } tracing = "0.1" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 739cee5d7f4c9..8aa14d15644b0 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -12,6 +12,7 @@ #![feature(never_type)] #![feature(try_blocks)] #![feature(yeet_expr)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use hir::ConstContext; diff --git a/compiler/rustc_monomorphize/Cargo.toml b/compiler/rustc_monomorphize/Cargo.toml index 51be8e55fa711..36b76d261de68 100644 --- a/compiler/rustc_monomorphize/Cargo.toml +++ b/compiler/rustc_monomorphize/Cargo.toml @@ -22,6 +22,3 @@ serde = "1" serde_json = "1" tracing = "0.1" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs index 8f6914f3d7242..714b64b3a231c 100644 --- a/compiler/rustc_monomorphize/src/lib.rs +++ b/compiler/rustc_monomorphize/src/lib.rs @@ -4,6 +4,7 @@ #![feature(if_let_guard)] #![feature(impl_trait_in_assoc_type)] #![feature(let_chains)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use rustc_hir::lang_items::LangItem; diff --git a/compiler/rustc_next_trait_solver/Cargo.toml b/compiler/rustc_next_trait_solver/Cargo.toml index e119d23d41a10..63aa60f2f26b9 100644 --- a/compiler/rustc_next_trait_solver/Cargo.toml +++ b/compiler/rustc_next_trait_solver/Cargo.toml @@ -24,6 +24,3 @@ nightly = [ "rustc_index/nightly", "rustc_type_ir/nightly", ] - -[lints] -workspace = true diff --git a/compiler/rustc_next_trait_solver/src/lib.rs b/compiler/rustc_next_trait_solver/src/lib.rs index f6963a790675f..d67ae2550d967 100644 --- a/compiler/rustc_next_trait_solver/src/lib.rs +++ b/compiler/rustc_next_trait_solver/src/lib.rs @@ -6,6 +6,7 @@ // tidy-alphabetical-start #![allow(rustc::usage_of_type_ir_inherent)] +#![warn(unreachable_pub)] // tidy-alphabetical-end pub mod canonicalizer; diff --git a/compiler/rustc_parse/Cargo.toml b/compiler/rustc_parse/Cargo.toml index b78ac197dbba6..c9dcab0c871dd 100644 --- a/compiler/rustc_parse/Cargo.toml +++ b/compiler/rustc_parse/Cargo.toml @@ -26,5 +26,3 @@ unicode-width = "0.2.0" [dev-dependencies] termcolor = "1.2" -[lints] -workspace = true diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 2edc8c83017d8..1a104ff5e3375 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -12,6 +12,7 @@ #![feature(iter_intersperse)] #![feature(let_chains)] #![feature(string_from_utf8_lossy_owned)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use std::path::{Path, PathBuf}; diff --git a/compiler/rustc_parse_format/Cargo.toml b/compiler/rustc_parse_format/Cargo.toml index a720903097aea..a39cca716d23e 100644 --- a/compiler/rustc_parse_format/Cargo.toml +++ b/compiler/rustc_parse_format/Cargo.toml @@ -8,6 +8,3 @@ edition = "2024" rustc_index = { path = "../rustc_index", default-features = false } rustc_lexer = { path = "../rustc_lexer" } # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index 287bd8678da25..3b985621b5772 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -13,6 +13,7 @@ html_playground_url = "https://play.rust-lang.org/", test(attr(deny(warnings))) )] +#![warn(unreachable_pub)] // tidy-alphabetical-end pub use Alignment::*; diff --git a/compiler/rustc_passes/Cargo.toml b/compiler/rustc_passes/Cargo.toml index 4cd7fde603480..ba81ef3103bd9 100644 --- a/compiler/rustc_passes/Cargo.toml +++ b/compiler/rustc_passes/Cargo.toml @@ -26,6 +26,3 @@ rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } tracing = "0.1" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index 93ff0f66d695b..1aa077ad2bb57 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -12,6 +12,7 @@ #![feature(map_try_insert)] #![feature(rustdoc_internals)] #![feature(try_blocks)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use rustc_middle::query::Providers; diff --git a/compiler/rustc_pattern_analysis/Cargo.toml b/compiler/rustc_pattern_analysis/Cargo.toml index 0624fe96cd918..40d549630acae 100644 --- a/compiler/rustc_pattern_analysis/Cargo.toml +++ b/compiler/rustc_pattern_analysis/Cargo.toml @@ -43,6 +43,3 @@ rustc = [ "smallvec/may_dangle", "rustc_index/nightly", ] - -[lints] -workspace = true diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs index eeea724a29b45..a3400ebb79937 100644 --- a/compiler/rustc_pattern_analysis/src/lib.rs +++ b/compiler/rustc_pattern_analysis/src/lib.rs @@ -6,6 +6,7 @@ #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] #![cfg_attr(feature = "rustc", feature(let_chains))] +#![warn(unreachable_pub)] // tidy-alphabetical-end pub mod constructor; diff --git a/compiler/rustc_pattern_analysis/tests/common/mod.rs b/compiler/rustc_pattern_analysis/tests/common/mod.rs index 8980b644f59b1..365bc2d863f47 100644 --- a/compiler/rustc_pattern_analysis/tests/common/mod.rs +++ b/compiler/rustc_pattern_analysis/tests/common/mod.rs @@ -5,7 +5,7 @@ use rustc_pattern_analysis::usefulness::{PlaceValidity, UsefulnessReport}; use rustc_pattern_analysis::{MatchArm, PatCx, PrivateUninhabitedField}; /// Sets up `tracing` for easier debugging. Tries to look like the `rustc` setup. -fn init_tracing() { +pub fn init_tracing() { use tracing_subscriber::Layer; use tracing_subscriber::layer::SubscriberExt; use tracing_subscriber::util::SubscriberInitExt; @@ -24,7 +24,7 @@ fn init_tracing() { /// A simple set of types. #[allow(dead_code)] #[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub(super) enum Ty { +pub enum Ty { /// Booleans Bool, /// 8-bit unsigned integers @@ -41,7 +41,7 @@ pub(super) enum Ty { /// The important logic. impl Ty { - pub(super) fn sub_tys(&self, ctor: &Constructor) -> Vec { + pub fn sub_tys(&self, ctor: &Constructor) -> Vec { use Constructor::*; match (ctor, *self) { (Struct, Ty::Tuple(tys)) => tys.iter().copied().collect(), @@ -63,7 +63,7 @@ impl Ty { } } - fn ctor_set(&self) -> ConstructorSet { + pub fn ctor_set(&self) -> ConstructorSet { match *self { Ty::Bool => ConstructorSet::Bool, Ty::U8 => ConstructorSet::Integers { @@ -104,7 +104,7 @@ impl Ty { } } - fn write_variant_name( + pub fn write_variant_name( &self, f: &mut std::fmt::Formatter<'_>, ctor: &Constructor, @@ -120,7 +120,7 @@ impl Ty { } /// Compute usefulness in our simple context (and set up tracing for easier debugging). -pub(super) fn compute_match_usefulness<'p>( +pub fn compute_match_usefulness<'p>( arms: &[MatchArm<'p, Cx>], ty: Ty, scrut_validity: PlaceValidity, @@ -137,7 +137,7 @@ pub(super) fn compute_match_usefulness<'p>( } #[derive(Debug)] -pub(super) struct Cx; +pub struct Cx; /// The context for pattern analysis. Forwards anything interesting to `Ty` methods. impl PatCx for Cx { diff --git a/compiler/rustc_privacy/Cargo.toml b/compiler/rustc_privacy/Cargo.toml index dc00ea8af43ae..242c67d732aff 100644 --- a/compiler/rustc_privacy/Cargo.toml +++ b/compiler/rustc_privacy/Cargo.toml @@ -18,6 +18,3 @@ rustc_span = { path = "../rustc_span" } rustc_ty_utils = { path = "../rustc_ty_utils" } tracing = "0.1" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 5e3e8d69b6031..5271d03a6f617 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -6,6 +6,7 @@ #![feature(let_chains)] #![feature(rustdoc_internals)] #![feature(try_blocks)] +#![warn(unreachable_pub)] // tidy-alphabetical-end mod errors; diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml index 42f7844815156..c85156e059e5a 100644 --- a/compiler/rustc_query_impl/Cargo.toml +++ b/compiler/rustc_query_impl/Cargo.toml @@ -20,6 +20,3 @@ rustc_span = { path = "../rustc_span" } thin-vec = "0.2.12" tracing = "0.1" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 40da46a027dfe..73c205fdb17d1 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -8,6 +8,7 @@ #![feature(min_specialization)] #![feature(rustc_attrs)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use rustc_data_structures::stable_hasher::HashStable; diff --git a/compiler/rustc_query_system/Cargo.toml b/compiler/rustc_query_system/Cargo.toml index c34d1170f0e1c..3e8ccb51021e1 100644 --- a/compiler/rustc_query_system/Cargo.toml +++ b/compiler/rustc_query_system/Cargo.toml @@ -25,6 +25,3 @@ smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } thin-vec = "0.2.12" tracing = "0.1" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs index a546362414cf4..ee984095ad84b 100644 --- a/compiler/rustc_query_system/src/lib.rs +++ b/compiler/rustc_query_system/src/lib.rs @@ -6,6 +6,7 @@ #![feature(hash_raw_entry)] #![feature(let_chains)] #![feature(min_specialization)] +#![warn(unreachable_pub)] // tidy-alphabetical-end pub mod cache; diff --git a/compiler/rustc_resolve/Cargo.toml b/compiler/rustc_resolve/Cargo.toml index 8958a3ac3048e..f4771f1af2cfd 100644 --- a/compiler/rustc_resolve/Cargo.toml +++ b/compiler/rustc_resolve/Cargo.toml @@ -28,6 +28,3 @@ smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } thin-vec = "0.2.12" tracing = "0.1" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index f724ecf76b3cc..ccdca8552320f 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -20,6 +20,7 @@ #![feature(let_chains)] #![feature(rustc_attrs)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use std::cell::{Cell, RefCell}; diff --git a/compiler/rustc_sanitizers/Cargo.toml b/compiler/rustc_sanitizers/Cargo.toml index e18ed121ca50d..900cd4243b13c 100644 --- a/compiler/rustc_sanitizers/Cargo.toml +++ b/compiler/rustc_sanitizers/Cargo.toml @@ -15,6 +15,3 @@ rustc_middle = { path = "../rustc_middle" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } - -[lints] -workspace = true diff --git a/compiler/rustc_sanitizers/src/lib.rs b/compiler/rustc_sanitizers/src/lib.rs index e4792563e71ea..55be931bcd6d4 100644 --- a/compiler/rustc_sanitizers/src/lib.rs +++ b/compiler/rustc_sanitizers/src/lib.rs @@ -5,6 +5,7 @@ // tidy-alphabetical-start #![feature(let_chains)] +#![warn(unreachable_pub)] // tidy-alphabetical-end pub mod cfi; diff --git a/compiler/rustc_serialize/Cargo.toml b/compiler/rustc_serialize/Cargo.toml index 10bfe14abde0b..948242352e7a8 100644 --- a/compiler/rustc_serialize/Cargo.toml +++ b/compiler/rustc_serialize/Cargo.toml @@ -16,6 +16,3 @@ thin-vec = "0.2.12" rustc_macros = { path = "../rustc_macros" } tempfile = "3.2" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_serialize/src/lib.rs b/compiler/rustc_serialize/src/lib.rs index 13c1a273eb816..9e9b78cfdd57c 100644 --- a/compiler/rustc_serialize/src/lib.rs +++ b/compiler/rustc_serialize/src/lib.rs @@ -14,6 +14,7 @@ #![feature(min_specialization)] #![feature(never_type)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end pub use self::serialize::{Decodable, Decoder, Encodable, Encoder}; diff --git a/compiler/rustc_session/Cargo.toml b/compiler/rustc_session/Cargo.toml index 4b2b41ba845a6..a087725d34dd1 100644 --- a/compiler/rustc_session/Cargo.toml +++ b/compiler/rustc_session/Cargo.toml @@ -37,6 +37,3 @@ features = [ "Win32_Foundation", "Win32_System_LibraryLoader", ] - -[lints] -workspace = true diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs index 0e19b982a133e..d432e84fdb224 100644 --- a/compiler/rustc_session/src/lib.rs +++ b/compiler/rustc_session/src/lib.rs @@ -7,6 +7,7 @@ // To generate CodegenOptionsTargetModifiers and UnstableOptionsTargetModifiers enums // with macro_rules, it is necessary to use recursive mechanic ("Incremental TT Munchers"). #![recursion_limit = "256"] +#![warn(unreachable_pub)] // tidy-alphabetical-end pub mod errors; diff --git a/compiler/rustc_smir/Cargo.toml b/compiler/rustc_smir/Cargo.toml index d14bff73b8b42..a11df9a9c9bc9 100644 --- a/compiler/rustc_smir/Cargo.toml +++ b/compiler/rustc_smir/Cargo.toml @@ -18,6 +18,3 @@ scoped-tls = "1.0" stable_mir = {path = "../stable_mir" } tracing = "0.1" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_smir/src/lib.rs b/compiler/rustc_smir/src/lib.rs index 9f88887530614..2215e2f01ade0 100644 --- a/compiler/rustc_smir/src/lib.rs +++ b/compiler/rustc_smir/src/lib.rs @@ -15,6 +15,7 @@ )] #![doc(rust_logo)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end pub mod rustc_internal; diff --git a/compiler/rustc_span/Cargo.toml b/compiler/rustc_span/Cargo.toml index a6f86151b8129..43a2d692577eb 100644 --- a/compiler/rustc_span/Cargo.toml +++ b/compiler/rustc_span/Cargo.toml @@ -22,6 +22,3 @@ sha2 = "0.10.1" tracing = "0.1" unicode-width = "0.2.0" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index f19d4d9f3624e..798e186a94b1a 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -32,6 +32,7 @@ #![feature(rustc_attrs)] #![feature(rustdoc_internals)] #![feature(slice_as_chunks)] +#![warn(unreachable_pub)] // tidy-alphabetical-end // The code produced by the `Encodable`/`Decodable` derive macros refer to diff --git a/compiler/rustc_symbol_mangling/Cargo.toml b/compiler/rustc_symbol_mangling/Cargo.toml index 89fe7ef2e408d..90ddf4c8a0403 100644 --- a/compiler/rustc_symbol_mangling/Cargo.toml +++ b/compiler/rustc_symbol_mangling/Cargo.toml @@ -19,6 +19,3 @@ rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } tracing = "0.1" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index 269401ef3a2de..4312c82815c16 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -93,6 +93,7 @@ #![doc(rust_logo)] #![feature(let_chains)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use rustc_hir::def::DefKind; diff --git a/compiler/rustc_target/Cargo.toml b/compiler/rustc_target/Cargo.toml index 6a0268cdee760..189b19b028617 100644 --- a/compiler/rustc_target/Cargo.toml +++ b/compiler/rustc_target/Cargo.toml @@ -22,6 +22,3 @@ default-features = false features = ["elf", "macho"] version = "0.36.2" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs index a8d7da5692de4..7ebe96960ed0f 100644 --- a/compiler/rustc_target/src/lib.rs +++ b/compiler/rustc_target/src/lib.rs @@ -16,6 +16,7 @@ #![feature(let_chains)] #![feature(rustc_attrs)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use std::path::{Path, PathBuf}; diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml index 5def437bd8078..1c61e23362a83 100644 --- a/compiler/rustc_trait_selection/Cargo.toml +++ b/compiler/rustc_trait_selection/Cargo.toml @@ -26,6 +26,3 @@ smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } thin-vec = "0.2" tracing = "0.1" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index b18fb0fb8fd31..b235d0da83cca 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -31,6 +31,7 @@ #![feature(unwrap_infallible)] #![feature(yeet_expr)] #![recursion_limit = "512"] // For rustdoc +#![warn(unreachable_pub)] // For rustdoc // tidy-alphabetical-end pub mod error_reporting; diff --git a/compiler/rustc_traits/Cargo.toml b/compiler/rustc_traits/Cargo.toml index 49bcaae857148..04aef4e7b9e03 100644 --- a/compiler/rustc_traits/Cargo.toml +++ b/compiler/rustc_traits/Cargo.toml @@ -13,6 +13,3 @@ rustc_span = { path = "../rustc_span" } rustc_trait_selection = { path = "../rustc_trait_selection" } tracing = "0.1" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_traits/src/lib.rs b/compiler/rustc_traits/src/lib.rs index 697c839180312..d2f979bd6d9dc 100644 --- a/compiler/rustc_traits/src/lib.rs +++ b/compiler/rustc_traits/src/lib.rs @@ -2,6 +2,7 @@ // tidy-alphabetical-start #![recursion_limit = "256"] +#![warn(unreachable_pub)] // tidy-alphabetical-end mod codegen; diff --git a/compiler/rustc_transmute/Cargo.toml b/compiler/rustc_transmute/Cargo.toml index ae1beb107288d..f0c783b30020e 100644 --- a/compiler/rustc_transmute/Cargo.toml +++ b/compiler/rustc_transmute/Cargo.toml @@ -25,6 +25,3 @@ rustc = [ # tidy-alphabetical-start itertools = "0.12" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs index 00928137d2976..81a11f7cfb267 100644 --- a/compiler/rustc_transmute/src/lib.rs +++ b/compiler/rustc_transmute/src/lib.rs @@ -1,5 +1,6 @@ // tidy-alphabetical-start #![feature(never_type)] +#![warn(unreachable_pub)] // tidy-alphabetical-end pub(crate) use rustc_data_structures::fx::{FxIndexMap as Map, FxIndexSet as Set}; diff --git a/compiler/rustc_ty_utils/Cargo.toml b/compiler/rustc_ty_utils/Cargo.toml index 61acc12d0eb90..4c7a57f2931bf 100644 --- a/compiler/rustc_ty_utils/Cargo.toml +++ b/compiler/rustc_ty_utils/Cargo.toml @@ -23,6 +23,3 @@ rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_type_ir = { path = "../rustc_type_ir" } tracing = "0.1" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs index 35cc6f3985652..8be1611bb9ac2 100644 --- a/compiler/rustc_ty_utils/src/lib.rs +++ b/compiler/rustc_ty_utils/src/lib.rs @@ -16,6 +16,7 @@ #![feature(let_chains)] #![feature(never_type)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use rustc_middle::query::Providers; diff --git a/compiler/rustc_type_ir/Cargo.toml b/compiler/rustc_type_ir/Cargo.toml index 0381797d7e92d..7b2593b96e37f 100644 --- a/compiler/rustc_type_ir/Cargo.toml +++ b/compiler/rustc_type_ir/Cargo.toml @@ -34,5 +34,5 @@ nightly = [ "rustc_ast_ir/nightly", ] -[lints] -workspace = true +[lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(bootstrap)'] } diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index e2dfd9173fab8..15ef4e7d6c1d2 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -6,6 +6,7 @@ feature(associated_type_defaults, never_type, rustc_attrs, negative_impls) )] #![cfg_attr(feature = "nightly", allow(internal_features))] +#![warn(unreachable_pub)] // tidy-alphabetical-end extern crate self as rustc_type_ir; diff --git a/compiler/rustc_type_ir_macros/Cargo.toml b/compiler/rustc_type_ir_macros/Cargo.toml index a3fa462385588..15a5557509929 100644 --- a/compiler/rustc_type_ir_macros/Cargo.toml +++ b/compiler/rustc_type_ir_macros/Cargo.toml @@ -13,6 +13,3 @@ quote = "1" syn = { version = "2.0.9", features = ["full"] } synstructure = "0.13.0" # tidy-alphabetical-end - -[lints] -workspace = true diff --git a/compiler/stable_mir/Cargo.toml b/compiler/stable_mir/Cargo.toml index 358a39154024c..d691a0e4f22f5 100644 --- a/compiler/stable_mir/Cargo.toml +++ b/compiler/stable_mir/Cargo.toml @@ -6,6 +6,3 @@ edition = "2024" [dependencies] scoped-tls = "1.0" serde = { version = "1.0.125", features = [ "derive" ] } - -[lints] -workspace = true diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index 2cbf82ccda366..12dd40d14e9bf 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -1072,17 +1072,12 @@ impl Builder<'_> { } if mode == Mode::Rustc { - // NOTE: rustc-specific lints are specified here. Normal rust lints - // are specified in the `[workspace.lints.rust]` section in the - // top-level `Cargo.toml`. If/when tool lints are supported by - // Cargo, these lints can be move to a `[workspace.lints.rustc]` - // section in the top-level `Cargo.toml`. - // - // NOTE: these flags are added to RUSTFLAGS, which is ignored when - // compiling proc macro crates such as `rustc_macros`, - // unfortunately. rustflags.arg("-Wrustc::internal"); rustflags.arg("-Drustc::symbol_intern_string_literal"); + // FIXME(edition_2024): Change this to `-Wrust_2024_idioms` when all + // of the individual lints are satisfied. + rustflags.arg("-Wkeyword_idents_2024"); + rustflags.arg("-Wunsafe_op_in_unsafe_fn"); } if self.config.rust_frame_pointers { From dc576cb67fcf713de44482a1a5aa586dfeff628e Mon Sep 17 00:00:00 2001 From: xizheyin Date: Mon, 10 Mar 2025 17:36:49 +0800 Subject: [PATCH 51/53] Add remark for missing llvm-tools component re. rustc_private linker failures related to not finding LLVM libraries Signed-off-by: xizheyin --- .../src/language-features/rustc-private.md | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/doc/unstable-book/src/language-features/rustc-private.md b/src/doc/unstable-book/src/language-features/rustc-private.md index 3b83a3cf4df8a..57ed857cdfe1b 100644 --- a/src/doc/unstable-book/src/language-features/rustc-private.md +++ b/src/doc/unstable-book/src/language-features/rustc-private.md @@ -12,3 +12,33 @@ The presence of this feature changes the way the linkage format for dylibs is ca that is necessary for linking against dylibs that statically link `std` (such as `rustc_driver`). This makes this feature "viral" in linkage; its use in a given crate makes its use required in dependent crates which link to it (including integration tests, which are built as separate crates). + +## Common linker failures related to missing LLVM libraries + +### When using `rustc-private` with Official Toolchains + +When using the `rustc_private` feature with official toolchains distributed via rustup, you'll need to install: + +1. The `rustc-dev` component (provides compiler libraries) +2. The `llvm-tools` component (provides LLVM libraries needed for linking) + +You can install these components using `rustup`: + +```text +rustup component add rustc-dev llvm-tools +``` + +Without the `llvm-tools` component, you may encounter linking errors like: + +```text +error: linking with `cc` failed: exit status: 1 + | + = note: rust-lld: error: unable to find library -lLLVM-{version} +``` + +### When using `rustc-private` with Custom Toolchains + +For custom-built toolchains or environments not using rustup, different configuration may be required: + +- Ensure LLVM libraries are available in your library search paths +- You might need to configure library paths explicitly depending on your LLVM installation From 61122d18298d1b82829a4717db896003b7d14c4d Mon Sep 17 00:00:00 2001 From: Bryanskiy Date: Mon, 10 Mar 2025 17:08:29 +0300 Subject: [PATCH 52/53] Delegation: fix ICE with invalid MethodCall generation --- compiler/rustc_ast_lowering/src/delegation.rs | 30 ++++++++++--------- compiler/rustc_ast_lowering/src/item.rs | 4 +-- tests/crashes/127916.rs | 16 ---------- tests/crashes/128119.rs | 15 ---------- tests/crashes/128190.rs | 7 ----- tests/ui/delegation/ice-isssue-128190.rs | 9 ++++++ tests/ui/delegation/ice-isssue-128190.stderr | 10 +++++++ 7 files changed, 37 insertions(+), 54 deletions(-) delete mode 100644 tests/crashes/127916.rs delete mode 100644 tests/crashes/128119.rs delete mode 100644 tests/crashes/128190.rs create mode 100644 tests/ui/delegation/ice-isssue-128190.rs create mode 100644 tests/ui/delegation/ice-isssue-128190.stderr diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index d8b7cb0c3225b..571172be4ed16 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -60,25 +60,27 @@ pub(crate) struct DelegationResults<'hir> { } impl<'hir> LoweringContext<'_, 'hir> { - pub(crate) fn delegation_has_self(&self, item_id: NodeId, path_id: NodeId, span: Span) -> bool { + /// Defines whether the delegatee is an associated function whose first parameter is `self`. + pub(crate) fn delegatee_is_method(&self, item_id: NodeId, path_id: NodeId, span: Span) -> bool { let sig_id = self.get_delegation_sig_id(item_id, path_id, span); let Ok(sig_id) = sig_id else { return false; }; - self.has_self(sig_id, span) + self.is_method(sig_id, span) } - fn has_self(&self, def_id: DefId, span: Span) -> bool { - if let Some(local_sig_id) = def_id.as_local() { - // The value may be missing due to recursive delegation. - // Error will be emitted later during HIR ty lowering. - self.resolver.delegation_fn_sigs.get(&local_sig_id).is_some_and(|sig| sig.has_self) - } else { - match self.tcx.def_kind(def_id) { - DefKind::Fn => false, - DefKind::AssocFn => self.tcx.associated_item(def_id).fn_has_self_parameter, - _ => span_bug!(span, "unexpected DefKind for delegation item"), - } + fn is_method(&self, def_id: DefId, span: Span) -> bool { + match self.tcx.def_kind(def_id) { + DefKind::Fn => false, + DefKind::AssocFn => match def_id.as_local() { + Some(local_def_id) => self + .resolver + .delegation_fn_sigs + .get(&local_def_id) + .is_some_and(|sig| sig.has_self), + None => self.tcx.associated_item(def_id).fn_has_self_parameter, + }, + _ => span_bug!(span, "unexpected DefKind for delegation item"), } } @@ -324,7 +326,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let call = if self .get_resolution_id(delegation.id, span) - .and_then(|def_id| Ok(self.has_self(def_id, span))) + .and_then(|def_id| Ok(self.is_method(def_id, span))) .unwrap_or_default() && delegation.qself.is_none() && !has_generic_args diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 5e89321e6ecc3..b01ca54fb6f41 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -871,7 +871,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::AssocItemKind::Fn { has_self: sig.decl.has_self() } } AssocItemKind::Delegation(box delegation) => hir::AssocItemKind::Fn { - has_self: self.delegation_has_self(i.id, delegation.id, i.span), + has_self: self.delegatee_is_method(i.id, delegation.id, i.span), }, AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => { panic!("macros should have been expanded by now") @@ -1000,7 +1000,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::AssocItemKind::Fn { has_self: sig.decl.has_self() } } AssocItemKind::Delegation(box delegation) => hir::AssocItemKind::Fn { - has_self: self.delegation_has_self(i.id, delegation.id, i.span), + has_self: self.delegatee_is_method(i.id, delegation.id, i.span), }, AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => { panic!("macros should have been expanded by now") diff --git a/tests/crashes/127916.rs b/tests/crashes/127916.rs deleted file mode 100644 index 295c88df85746..0000000000000 --- a/tests/crashes/127916.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ known-bug: #127916 - -trait Trait { - fn foo(&self) -> u32 { 0 } -} - -struct F; -struct S; - -mod to_reuse { - pub fn foo(&self) -> u32 {} -} - -impl Trait S { - reuse to_reuse::foo { self } -} diff --git a/tests/crashes/128119.rs b/tests/crashes/128119.rs deleted file mode 100644 index 7677b15a2f33f..0000000000000 --- a/tests/crashes/128119.rs +++ /dev/null @@ -1,15 +0,0 @@ -//@ known-bug: #128119 - -trait Trait { - reuse to_reuse::foo { self } -} - -struct S; - -mod to_reuse { - pub fn foo(&self) -> u32 {} -} - -impl Trait S { - reuse to_reuse::foo { self } -} diff --git a/tests/crashes/128190.rs b/tests/crashes/128190.rs deleted file mode 100644 index 0fa7027ae6091..0000000000000 --- a/tests/crashes/128190.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ known-bug: rust-lang/rust#128190 - -fn a(&self) { - 15 -} - -reuse a as b { struct S; } diff --git a/tests/ui/delegation/ice-isssue-128190.rs b/tests/ui/delegation/ice-isssue-128190.rs new file mode 100644 index 0000000000000..dab3bbee663cb --- /dev/null +++ b/tests/ui/delegation/ice-isssue-128190.rs @@ -0,0 +1,9 @@ +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +fn a(&self) {} +//~^ ERROR `self` parameter is only allowed in associated functions + +reuse a as b; + +fn main() {} diff --git a/tests/ui/delegation/ice-isssue-128190.stderr b/tests/ui/delegation/ice-isssue-128190.stderr new file mode 100644 index 0000000000000..18f676642c2b9 --- /dev/null +++ b/tests/ui/delegation/ice-isssue-128190.stderr @@ -0,0 +1,10 @@ +error: `self` parameter is only allowed in associated functions + --> $DIR/ice-isssue-128190.rs:4:6 + | +LL | fn a(&self) {} + | ^^^^^ not semantically valid as function parameter + | + = note: associated functions are those in `impl` or `trait` definitions + +error: aborting due to 1 previous error + From bc4f0bb486bcba6e6e40d0dd7c9df0f9e6aebca9 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 6 Mar 2025 22:01:01 +0000 Subject: [PATCH 53/53] Pass InferCtxt to InlineAsmCtxt to properly taint on error Split up some of the tests bc tainting causes some errors to become suppressed --- .../src/check/intrinsicck.rs | 110 +++++++++--------- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 15 +-- tests/ui/asm/invalid-const-operand.rs | 8 +- tests/ui/asm/invalid-const-operand.stderr | 8 +- tests/ui/asm/tainting-on-error.rs | 13 +++ tests/ui/asm/tainting-on-error.stderr | 10 ++ tests/ui/asm/x86_64/type-check-2.rs | 8 +- tests/ui/asm/x86_64/type-check-2.stderr | 16 +-- 8 files changed, 109 insertions(+), 79 deletions(-) create mode 100644 tests/ui/asm/tainting-on-error.rs create mode 100644 tests/ui/asm/tainting-on-error.stderr diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs index 590ade516ec64..d63165f0f1698 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs @@ -3,8 +3,11 @@ use rustc_ast::InlineAsmTemplatePiece; use rustc_data_structures::fx::FxIndexSet; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, LangItem}; +use rustc_infer::infer::InferCtxt; use rustc_middle::bug; -use rustc_middle::ty::{self, Article, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, UintTy}; +use rustc_middle::ty::{ + self, Article, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, TypeckResults, UintTy, +}; use rustc_session::lint; use rustc_span::def_id::LocalDefId; use rustc_span::{Symbol, sym}; @@ -14,12 +17,11 @@ use rustc_target::asm::{ use crate::errors::RegisterTypeUnstable; -pub struct InlineAsmCtxt<'a, 'tcx: 'a> { - tcx: TyCtxt<'tcx>, +pub struct InlineAsmCtxt<'a, 'tcx> { typing_env: ty::TypingEnv<'tcx>, target_features: &'tcx FxIndexSet, - expr_ty: Box) -> Ty<'tcx> + 'a>, - node_ty: Box Ty<'tcx> + 'a>, + infcx: &'a InferCtxt<'tcx>, + typeck_results: &'a TypeckResults<'tcx>, } enum NonAsmTypeReason<'tcx> { @@ -31,34 +33,38 @@ enum NonAsmTypeReason<'tcx> { impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { pub fn new( - tcx: TyCtxt<'tcx>, def_id: LocalDefId, + infcx: &'a InferCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, - expr_ty: impl Fn(&hir::Expr<'tcx>) -> Ty<'tcx> + 'a, - node_ty: impl Fn(hir::HirId) -> Ty<'tcx> + 'a, + typeck_results: &'a TypeckResults<'tcx>, ) -> Self { InlineAsmCtxt { - tcx, typing_env, - target_features: tcx.asm_target_features(def_id), - expr_ty: Box::new(expr_ty), - node_ty: Box::new(node_ty), + target_features: infcx.tcx.asm_target_features(def_id), + infcx, + typeck_results, } } - fn expr_ty(&self, expr: &hir::Expr<'tcx>) -> Ty<'tcx> { - (self.expr_ty)(expr) + fn tcx(&self) -> TyCtxt<'tcx> { + self.infcx.tcx } - fn node_ty(&self, hir_id: hir::HirId) -> Ty<'tcx> { - (self.node_ty)(hir_id) + fn expr_ty(&self, expr: &hir::Expr<'tcx>) -> Ty<'tcx> { + let ty = self.typeck_results.expr_ty_adjusted(expr); + let ty = self.infcx.resolve_vars_if_possible(ty); + if ty.has_non_region_infer() { + Ty::new_misc_error(self.tcx()) + } else { + self.tcx().erase_regions(ty) + } } // FIXME(compiler-errors): This could use `<$ty as Pointee>::Metadata == ()` fn is_thin_ptr_ty(&self, ty: Ty<'tcx>) -> bool { // Type still may have region variables, but `Sized` does not depend // on those, so just erase them before querying. - if ty.is_sized(self.tcx, self.typing_env) { + if ty.is_sized(self.tcx(), self.typing_env) { return true; } if let ty::Foreign(..) = ty.kind() { @@ -68,7 +74,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { } fn get_asm_ty(&self, ty: Ty<'tcx>) -> Result> { - let asm_ty_isize = match self.tcx.sess.target.pointer_width { + let asm_ty_isize = match self.tcx().sess.target.pointer_width { 16 => InlineAsmType::I16, 32 => InlineAsmType::I32, 64 => InlineAsmType::I64, @@ -97,12 +103,12 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { ty::Adt(adt, args) if adt.repr().simd() => { let fields = &adt.non_enum_variant().fields; let field = &fields[FieldIdx::ZERO]; - let elem_ty = field.ty(self.tcx, args); + let elem_ty = field.ty(self.tcx(), args); let (size, ty) = match elem_ty.kind() { ty::Array(ty, len) => { - let len = self.tcx.normalize_erasing_regions(self.typing_env, *len); - if let Some(len) = len.try_to_target_usize(self.tcx) { + let len = self.tcx().normalize_erasing_regions(self.typing_env, *len); + if let Some(len) = len.try_to_target_usize(self.tcx()) { (len, *ty) } else { return Err(NonAsmTypeReason::UnevaluatedSIMDArrayLength( @@ -122,7 +128,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { Ok(InlineAsmType::VecI128(size)) } ty::Int(IntTy::Isize) | ty::Uint(UintTy::Usize) => { - Ok(match self.tcx.sess.target.pointer_width { + Ok(match self.tcx().sess.target.pointer_width { 16 => InlineAsmType::VecI16(size), 32 => InlineAsmType::VecI32(size), 64 => InlineAsmType::VecI64(size), @@ -159,9 +165,9 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { // `!` is allowed for input but not for output (issue #87802) ty::Never if is_input => return None, _ if ty.references_error() => return None, - ty::Adt(adt, args) if self.tcx.is_lang_item(adt.did(), LangItem::MaybeUninit) => { + ty::Adt(adt, args) if self.tcx().is_lang_item(adt.did(), LangItem::MaybeUninit) => { let fields = &adt.non_enum_variant().fields; - let ty = fields[FieldIdx::from_u32(1)].ty(self.tcx, args); + let ty = fields[FieldIdx::from_u32(1)].ty(self.tcx(), args); // FIXME: Are we just trying to map to the `T` in `MaybeUninit`? // If so, just get it from the args. let ty::Adt(ty, args) = ty.kind() else { @@ -172,7 +178,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { "expected first field of `MaybeUninit` to be `ManuallyDrop`" ); let fields = &ty.non_enum_variant().fields; - let ty = fields[FieldIdx::ZERO].ty(self.tcx, args); + let ty = fields[FieldIdx::ZERO].ty(self.tcx(), args); self.get_asm_ty(ty) } _ => self.get_asm_ty(ty), @@ -183,9 +189,9 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { match reason { NonAsmTypeReason::UnevaluatedSIMDArrayLength(did, len) => { let msg = format!("cannot evaluate SIMD vector length `{len}`"); - self.tcx + self.infcx .dcx() - .struct_span_err(self.tcx.def_span(did), msg) + .struct_span_err(self.tcx().def_span(did), msg) .with_span_note( expr.span, "SIMD vector length needs to be known statically for use in `asm!`", @@ -194,7 +200,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { } NonAsmTypeReason::Invalid(ty) => { let msg = format!("cannot use value of type `{ty}` for inline assembly"); - self.tcx.dcx().struct_span_err(expr.span, msg).with_note( + self.infcx.dcx().struct_span_err(expr.span, msg).with_note( "only integers, floats, SIMD vectors, pointers and function pointers \ can be used as arguments for inline assembly", ).emit(); @@ -203,7 +209,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { let msg = format!( "cannot use value of unsized pointer type `{ty}` for inline assembly" ); - self.tcx + self.infcx .dcx() .struct_span_err(expr.span, msg) .with_note("only sized pointers can be used in inline assembly") @@ -213,8 +219,8 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { let msg = format!( "cannot use SIMD vector with element type `{ty}` for inline assembly" ); - self.tcx.dcx() - .struct_span_err(self.tcx.def_span(did), msg).with_span_note( + self.infcx.dcx() + .struct_span_err(self.tcx().def_span(did), msg).with_span_note( expr.span, "only integers, floats, SIMD vectors, pointers and function pointers \ can be used as arguments for inline assembly", @@ -227,9 +233,9 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { // Check that the type implements Copy. The only case where this can // possibly fail is for SIMD types which don't #[derive(Copy)]. - if !self.tcx.type_is_copy_modulo_regions(self.typing_env, ty) { + if !self.tcx().type_is_copy_modulo_regions(self.typing_env, ty) { let msg = "arguments for inline assembly must be copyable"; - self.tcx + self.infcx .dcx() .struct_span_err(expr.span, msg) .with_note(format!("`{ty}` does not implement the Copy trait")) @@ -249,7 +255,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { if in_asm_ty != asm_ty { let msg = "incompatible types for asm inout argument"; let in_expr_ty = self.expr_ty(in_expr); - self.tcx + self.infcx .dcx() .struct_span_err(vec![in_expr.span, expr.span], msg) .with_span_label(in_expr.span, format!("type `{in_expr_ty}`")) @@ -268,21 +274,21 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { // Check the type against the list of types supported by the selected // register class. - let asm_arch = self.tcx.sess.asm_arch.unwrap(); - let allow_experimental_reg = self.tcx.features().asm_experimental_reg(); + let asm_arch = self.tcx().sess.asm_arch.unwrap(); + let allow_experimental_reg = self.tcx().features().asm_experimental_reg(); let reg_class = reg.reg_class(); let supported_tys = reg_class.supported_types(asm_arch, allow_experimental_reg); let Some((_, feature)) = supported_tys.iter().find(|&&(t, _)| t == asm_ty) else { let mut err = if !allow_experimental_reg && reg_class.supported_types(asm_arch, true).iter().any(|&(t, _)| t == asm_ty) { - self.tcx.sess.create_feature_err( + self.tcx().sess.create_feature_err( RegisterTypeUnstable { span: expr.span, ty }, sym::asm_experimental_reg, ) } else { let msg = format!("type `{ty}` cannot be used with this register class"); - let mut err = self.tcx.dcx().struct_span_err(expr.span, msg); + let mut err = self.infcx.dcx().struct_span_err(expr.span, msg); let supported_tys: Vec<_> = supported_tys.iter().map(|(t, _)| t.to_string()).collect(); err.note(format!( @@ -312,7 +318,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { if let Some(feature) = feature { if !self.target_features.contains(feature) { let msg = format!("`{feature}` target feature is not enabled"); - self.tcx + self.infcx .dcx() .struct_span_err(expr.span, msg) .with_note(format!( @@ -349,7 +355,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { result: default_result, size: default_size, } = reg_class.default_modifier(asm_arch).unwrap(); - self.tcx.node_span_lint( + self.tcx().node_span_lint( lint::builtin::ASM_SUB_REGISTER, expr.hir_id, spans, @@ -371,11 +377,11 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { } pub fn check_asm(&self, asm: &hir::InlineAsm<'tcx>) { - let Some(asm_arch) = self.tcx.sess.asm_arch else { - self.tcx.dcx().delayed_bug("target architecture does not support asm"); + let Some(asm_arch) = self.tcx().sess.asm_arch else { + self.infcx.dcx().delayed_bug("target architecture does not support asm"); return; }; - let allow_experimental_reg = self.tcx.features().asm_experimental_reg(); + let allow_experimental_reg = self.tcx().features().asm_experimental_reg(); for (idx, &(op, op_sp)) in asm.operands.iter().enumerate() { // Validate register classes against currently enabled target // features. We check that at least one type is available for @@ -398,13 +404,13 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { } if let Err(msg) = reg.validate( asm_arch, - self.tcx.sess.relocation_model(), + self.tcx().sess.relocation_model(), self.target_features, - &self.tcx.sess.target, + &self.tcx().sess.target, op.is_clobber(), ) { let msg = format!("cannot use register `{}`: {}", reg.name(), msg); - self.tcx.dcx().span_err(op_sp, msg); + self.infcx.dcx().span_err(op_sp, msg); continue; } } @@ -444,7 +450,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { reg_class.name(), feature ); - self.tcx.dcx().span_err(op_sp, msg); + self.infcx.dcx().span_err(op_sp, msg); // register isn't enabled, don't do more checks continue; } @@ -458,7 +464,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { .intersperse(", ") .collect::(), ); - self.tcx.dcx().span_err(op_sp, msg); + self.infcx.dcx().span_err(op_sp, msg); // register isn't enabled, don't do more checks continue; } @@ -493,16 +499,16 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { } } hir::InlineAsmOperand::Const { anon_const } => { - let ty = self.node_ty(anon_const.hir_id); + let ty = self.expr_ty(self.tcx().hir_body(anon_const.body).value); match ty.kind() { ty::Error(_) => {} _ if ty.is_integral() => {} _ => { - self.tcx + self.infcx .dcx() .struct_span_err(op_sp, "invalid type for `const` operand") .with_span_label( - self.tcx.def_span(anon_const.def_id), + self.tcx().def_span(anon_const.def_id), format!("is {} `{}`", ty.kind().article(), ty), ) .with_help("`const` operands must be of an integer type") @@ -517,7 +523,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { ty::FnDef(..) => {} ty::Error(_) => {} _ => { - self.tcx + self.infcx .dcx() .struct_span_err(op_sp, "invalid `sym` operand") .with_span_label( diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index db947b6744da6..ac911c202220b 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -99,22 +99,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!("FnCtxt::check_asm: {} deferred checks", deferred_asm_checks.len()); for (asm, hir_id) in deferred_asm_checks.drain(..) { let enclosing_id = self.tcx.hir_enclosing_body_owner(hir_id); - let expr_ty = |expr: &hir::Expr<'tcx>| { - let ty = self.typeck_results.borrow().expr_ty_adjusted(expr); - let ty = self.resolve_vars_if_possible(ty); - if ty.has_non_region_infer() { - Ty::new_misc_error(self.tcx) - } else { - self.tcx.erase_regions(ty) - } - }; - let node_ty = |hir_id: HirId| self.typeck_results.borrow().node_type(hir_id); InlineAsmCtxt::new( - self.tcx, enclosing_id, + &self.infcx, self.typing_env(self.param_env), - expr_ty, - node_ty, + &*self.typeck_results.borrow(), ) .check_asm(asm); } diff --git a/tests/ui/asm/invalid-const-operand.rs b/tests/ui/asm/invalid-const-operand.rs index a688f5042db5c..bbf4001752a4b 100644 --- a/tests/ui/asm/invalid-const-operand.rs +++ b/tests/ui/asm/invalid-const-operand.rs @@ -14,7 +14,7 @@ global_asm!("{}", const 0f32); global_asm!("{}", const 0 as *mut u8); //~^ ERROR invalid type for `const` operand -fn main() { +fn test1() { unsafe { // Const operands must be integers and must be constants. @@ -27,7 +27,11 @@ fn main() { //~^ ERROR invalid type for `const` operand asm!("{}", const &0); //~^ ERROR invalid type for `const` operand + } +} +fn test2() { + unsafe { // Constants must be... constant let x = 0; @@ -47,3 +51,5 @@ fn main() { //~^ ERROR attempt to use a non-constant value in a constant } } + +fn main() {} diff --git a/tests/ui/asm/invalid-const-operand.stderr b/tests/ui/asm/invalid-const-operand.stderr index 1cedabeef2892..01aa843c6fb19 100644 --- a/tests/ui/asm/invalid-const-operand.stderr +++ b/tests/ui/asm/invalid-const-operand.stderr @@ -1,5 +1,5 @@ error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/invalid-const-operand.rs:40:26 + --> $DIR/invalid-const-operand.rs:44:26 | LL | asm!("{}", const x); | ^ non-constant value @@ -11,7 +11,7 @@ LL + const x: /* Type */ = 0; | error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/invalid-const-operand.rs:43:36 + --> $DIR/invalid-const-operand.rs:47:36 | LL | asm!("{}", const const_foo(x)); | ^ non-constant value @@ -23,7 +23,7 @@ LL + const x: /* Type */ = 0; | error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/invalid-const-operand.rs:46:36 + --> $DIR/invalid-const-operand.rs:50:36 | LL | asm!("{}", const const_bar(x)); | ^ non-constant value @@ -80,7 +80,7 @@ error: invalid type for `const` operand LL | asm!("{}", const &0); | ^^^^^^-- | | - | is a `&{integer}` + | is a `&i32` | = help: `const` operands must be of an integer type diff --git a/tests/ui/asm/tainting-on-error.rs b/tests/ui/asm/tainting-on-error.rs new file mode 100644 index 0000000000000..a8e9af911580d --- /dev/null +++ b/tests/ui/asm/tainting-on-error.rs @@ -0,0 +1,13 @@ +//@ needs-asm-support + +use std::arch::asm; + +fn main() { + unsafe { + asm!( + "/* {} */", + sym None::<()>, + //~^ ERROR invalid `sym` operand + ); + } +} diff --git a/tests/ui/asm/tainting-on-error.stderr b/tests/ui/asm/tainting-on-error.stderr new file mode 100644 index 0000000000000..bd706d1f310bf --- /dev/null +++ b/tests/ui/asm/tainting-on-error.stderr @@ -0,0 +1,10 @@ +error: invalid `sym` operand + --> $DIR/tainting-on-error.rs:9:13 + | +LL | sym None::<()>, + | ^^^^^^^^^^^^^^ is an `Option<()>` + | + = help: `sym` operands must refer to either a function or a static + +error: aborting due to 1 previous error + diff --git a/tests/ui/asm/x86_64/type-check-2.rs b/tests/ui/asm/x86_64/type-check-2.rs index 1650c595faebb..c63042298da30 100644 --- a/tests/ui/asm/x86_64/type-check-2.rs +++ b/tests/ui/asm/x86_64/type-check-2.rs @@ -7,7 +7,7 @@ use std::arch::{asm, global_asm}; #[repr(simd)] struct SimdNonCopy([f32; 4]); -fn main() { +fn test1() { unsafe { // Inputs must be initialized @@ -26,7 +26,11 @@ fn main() { asm!("{}", in(reg) v[0]); asm!("{}", out(reg) v[0]); asm!("{}", inout(reg) v[0]); + } +} +fn test2() { + unsafe { // Register operands must be Copy asm!("{}", in(xmm_reg) SimdNonCopy([0.0, 0.0, 0.0, 0.0])); @@ -68,3 +72,5 @@ fn main() { asm!("{}", in(reg) u); } } + +fn main() {} diff --git a/tests/ui/asm/x86_64/type-check-2.stderr b/tests/ui/asm/x86_64/type-check-2.stderr index 8b1bfa85fa2c4..d5c5a3ff1f843 100644 --- a/tests/ui/asm/x86_64/type-check-2.stderr +++ b/tests/ui/asm/x86_64/type-check-2.stderr @@ -1,13 +1,13 @@ error: arguments for inline assembly must be copyable - --> $DIR/type-check-2.rs:32:32 + --> $DIR/type-check-2.rs:36:32 | LL | asm!("{}", in(xmm_reg) SimdNonCopy([0.0, 0.0, 0.0, 0.0])); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `SimdNonCopy` does not implement the Copy trait -error: cannot use value of type `{closure@$DIR/type-check-2.rs:44:28: 44:36}` for inline assembly - --> $DIR/type-check-2.rs:44:28 +error: cannot use value of type `{closure@$DIR/type-check-2.rs:48:28: 48:36}` for inline assembly + --> $DIR/type-check-2.rs:48:28 | LL | asm!("{}", in(reg) |x: i32| x); | ^^^^^^^^^^ @@ -15,7 +15,7 @@ LL | asm!("{}", in(reg) |x: i32| x); = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `Vec` for inline assembly - --> $DIR/type-check-2.rs:46:28 + --> $DIR/type-check-2.rs:50:28 | LL | asm!("{}", in(reg) vec![0]); | ^^^^^^^ @@ -24,7 +24,7 @@ LL | asm!("{}", in(reg) vec![0]); = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) error: cannot use value of type `(i32, i32, i32)` for inline assembly - --> $DIR/type-check-2.rs:48:28 + --> $DIR/type-check-2.rs:52:28 | LL | asm!("{}", in(reg) (1, 2, 3)); | ^^^^^^^^^ @@ -32,7 +32,7 @@ LL | asm!("{}", in(reg) (1, 2, 3)); = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `[i32; 3]` for inline assembly - --> $DIR/type-check-2.rs:50:28 + --> $DIR/type-check-2.rs:54:28 | LL | asm!("{}", in(reg) [1, 2, 3]); | ^^^^^^^^^ @@ -40,7 +40,7 @@ LL | asm!("{}", in(reg) [1, 2, 3]); = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `fn() {main}` for inline assembly - --> $DIR/type-check-2.rs:58:31 + --> $DIR/type-check-2.rs:62:31 | LL | asm!("{}", inout(reg) f); | ^ @@ -48,7 +48,7 @@ LL | asm!("{}", inout(reg) f); = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `&mut i32` for inline assembly - --> $DIR/type-check-2.rs:61:31 + --> $DIR/type-check-2.rs:65:31 | LL | asm!("{}", inout(reg) r); | ^