From fa46a9e2b605de60b11a29f5951e650c3c0f5089 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Mon, 11 Nov 2024 15:50:04 +0100 Subject: [PATCH 1/7] Use completion item indices instead of property matching when searching for the completion item to resolve --- .../rust-analyzer/src/handlers/request.rs | 18 +++++------- .../crates/rust-analyzer/src/lsp/ext.rs | 1 + .../crates/rust-analyzer/src/lsp/to_proto.rs | 29 +++++++++++++++---- 3 files changed, 33 insertions(+), 15 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 9773d8dbce0..691ea6f5677 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 @@ -1068,7 +1068,7 @@ pub(crate) fn handle_completion_resolve( else { return Ok(original_completion); }; - let resolved_completions = to_proto::completion_items( + let mut resolved_completions = to_proto::completion_items( &snap.config, &forced_resolve_completions_config.fields_to_resolve, &line_index, @@ -1077,15 +1077,13 @@ pub(crate) fn handle_completion_resolve( resolve_data.trigger_character, resolved_completions, ); - let Some(mut resolved_completion) = resolved_completions.into_iter().find(|completion| { - completion.label == original_completion.label - && completion.kind == original_completion.kind - && completion.deprecated == original_completion.deprecated - && completion.preselect == original_completion.preselect - && completion.sort_text == original_completion.sort_text - }) else { - return Ok(original_completion); - }; + + let mut resolved_completion = + if resolved_completions.get(resolve_data.completion_item_index).is_some() { + resolved_completions.swap_remove(resolve_data.completion_item_index) + } else { + return Ok(original_completion); + }; if !resolve_data.imports.is_empty() { let additional_edits = snap diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs index 8039f0644ee..6ddfe118d5e 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs @@ -826,6 +826,7 @@ pub struct CompletionResolveData { pub imports: Vec, pub version: Option, pub trigger_character: Option, + pub completion_item_index: usize, } #[derive(Debug, Serialize, Deserialize)] 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 375b7428c2d..cdc6fb17fd4 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 @@ -391,18 +391,36 @@ fn completion_item( } else { Vec::new() }; - if something_to_resolve || !imports.is_empty() { - let data = lsp_ext::CompletionResolveData { + let (ref_resolve_data, resolve_data) = if something_to_resolve || !imports.is_empty() { + let mut item_index = acc.len(); + let ref_resolve_data = if ref_match.is_some() { + let ref_resolve_data = lsp_ext::CompletionResolveData { + position: tdpp.clone(), + imports: Vec::new(), + version, + trigger_character: completion_trigger_character, + completion_item_index: item_index, + }; + item_index += 1; + Some(to_value(ref_resolve_data).unwrap()) + } else { + None + }; + let resolve_data = lsp_ext::CompletionResolveData { position: tdpp.clone(), imports, version, trigger_character: completion_trigger_character, + completion_item_index: item_index, }; - lsp_item.data = Some(to_value(data).unwrap()); - } + (ref_resolve_data, Some(to_value(resolve_data).unwrap())) + } else { + (None, None) + }; if let Some((label, indel, relevance)) = ref_match { - let mut lsp_item_with_ref = lsp_types::CompletionItem { label, ..lsp_item.clone() }; + let mut lsp_item_with_ref = + lsp_types::CompletionItem { label, data: ref_resolve_data, ..lsp_item.clone() }; lsp_item_with_ref .additional_text_edits .get_or_insert_with(Default::default) @@ -411,6 +429,7 @@ fn completion_item( acc.push(lsp_item_with_ref); }; + lsp_item.data = resolve_data; acc.push(lsp_item); fn set_score( From f0db79f31ada049bf490c8f27be7443f45460f09 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Mon, 11 Nov 2024 16:06:55 +0100 Subject: [PATCH 2/7] Update the file hash --- src/tools/rust-analyzer/docs/dev/lsp-extensions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md index 7764f7843a0..b7c536e0279 100644 --- a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md +++ b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md @@ -1,5 +1,5 @@ $DIR/immediately-followed-by-lt.rs:11:4 + | +LL | w!('r#long'id); + | ^^^^^^^^ + | +help: if you meant to write a string literal, use double quotes + | +LL | w!("r#long"id); + | ~ ~ + +error: aborting due to 1 previous error + From 80f109a80a8c8aae389442895d896bbd32e68d6d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 5 Nov 2024 02:02:56 +0000 Subject: [PATCH 4/7] Only disable cache if predicate has opaques within it (cherry picked from commit 49153739fd01d82ed999c763fd2771cb837d7dd2) --- .../src/traits/select/mod.rs | 66 +++++++++++++------ 1 file changed, 45 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index fba1d1025ca..ea5b6ff1959 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -12,26 +12,26 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{Diag, EmissionGuarantee}; use rustc_hir as hir; -use rustc_hir::LangItem; use rustc_hir::def_id::DefId; -use rustc_infer::infer::BoundRegionConversionTime::{self, HigherRankedType}; -use rustc_infer::infer::DefineOpaqueTypes; +use rustc_hir::LangItem; use rustc_infer::infer::at::ToTrace; use rustc_infer::infer::relate::TypeRelation; +use rustc_infer::infer::BoundRegionConversionTime::{self, HigherRankedType}; +use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::traits::TraitObligation; use rustc_middle::bug; -use rustc_middle::dep_graph::{DepNodeIndex, dep_kinds}; +use rustc_middle::dep_graph::{dep_kinds, DepNodeIndex}; use rustc_middle::mir::interpret::ErrorHandled; pub use rustc_middle::traits::select::*; use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::TypeErrorToStringExt; -use rustc_middle::ty::print::{PrintTraitRefExt as _, with_no_trimmed_paths}; +use rustc_middle::ty::print::{with_no_trimmed_paths, PrintTraitRefExt as _}; use rustc_middle::ty::{ self, GenericArgsRef, PolyProjectionPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, Upcast, }; -use rustc_span::Symbol; use rustc_span::symbol::sym; +use rustc_span::Symbol; use tracing::{debug, instrument, trace}; use self::EvaluationResult::*; @@ -40,9 +40,9 @@ use super::coherence::{self, Conflict}; use super::project::ProjectionTermObligation; use super::util::closure_trait_ref_and_return_type; use super::{ - ImplDerivedCause, Normalized, Obligation, ObligationCause, ObligationCauseCode, Overflow, - PolyTraitObligation, PredicateObligation, Selection, SelectionError, SelectionResult, - TraitQueryMode, const_evaluatable, project, util, wf, + const_evaluatable, project, util, wf, ImplDerivedCause, Normalized, Obligation, + ObligationCause, ObligationCauseCode, Overflow, PolyTraitObligation, PredicateObligation, + Selection, SelectionError, SelectionResult, TraitQueryMode, }; use crate::error_reporting::InferCtxtErrorExt; use crate::infer::{InferCtxt, InferOk, TypeFreshener}; @@ -1306,7 +1306,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } let tcx = self.tcx(); - if self.can_use_global_caches(param_env) { + if self.can_use_global_caches(param_env, trait_pred) { if let Some(res) = tcx.evaluation_cache.get(&(param_env, trait_pred), tcx) { return Some(res); } @@ -1335,7 +1335,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return; } - if self.can_use_global_caches(param_env) && !trait_pred.has_infer() { + if self.can_use_global_caches(param_env, trait_pred) && !trait_pred.has_infer() { debug!(?trait_pred, ?result, "insert_evaluation_cache global"); // This may overwrite the cache with the same value // FIXME: Due to #50507 this overwrites the different values @@ -1479,7 +1479,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } /// Returns `true` if the global caches can be used. - fn can_use_global_caches(&self, param_env: ty::ParamEnv<'tcx>) -> bool { + fn can_use_global_caches( + &self, + param_env: ty::ParamEnv<'tcx>, + pred: ty::PolyTraitPredicate<'tcx>, + ) -> bool { // If there are any inference variables in the `ParamEnv`, then we // always use a cache local to this particular scope. Otherwise, we // switch to a global cache. @@ -1500,7 +1504,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Avoid using the global cache when we're defining opaque types // as their hidden type may impact the result of candidate selection. - if !self.infcx.defining_opaque_types().is_empty() { + // + // HACK: This is still theoretically unsound. Goals can indirectly rely + // on opaques in the defining scope, and it's easier to do so with TAIT. + // However, if we disqualify *all* goals from being cached, perf suffers. + // This is likely fixed by better caching in general in the new solver. + // See: . + if !self.infcx.defining_opaque_types().is_empty() && pred.has_opaque_types() { return false; } @@ -1523,7 +1533,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let tcx = self.tcx(); let pred = cache_fresh_trait_pred.skip_binder(); - if self.can_use_global_caches(param_env) { + if self.can_use_global_caches(param_env, cache_fresh_trait_pred) { if let Some(res) = tcx.selection_cache.get(&(param_env, pred), tcx) { return Some(res); } @@ -1580,7 +1590,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return; } - if self.can_use_global_caches(param_env) { + if self.can_use_global_caches(param_env, cache_fresh_trait_pred) { if let Err(Overflow(OverflowError::Canonical)) = candidate { // Don't cache overflow globally; we only produce this in certain modes. } else if !pred.has_infer() && !candidate.has_infer() { @@ -1787,7 +1797,11 @@ enum DropVictim { impl DropVictim { fn drop_if(should_drop: bool) -> DropVictim { - if should_drop { DropVictim::Yes } else { DropVictim::No } + if should_drop { + DropVictim::Yes + } else { + DropVictim::No + } } } @@ -1891,7 +1905,11 @@ impl<'tcx> SelectionContext<'_, 'tcx> { (ObjectCandidate(_) | ProjectionCandidate(_), ParamCandidate(victim_cand)) => { // Prefer these to a global where-clause bound // (see issue #50825). - if is_global(*victim_cand) { DropVictim::Yes } else { DropVictim::No } + if is_global(*victim_cand) { + DropVictim::Yes + } else { + DropVictim::No + } } ( ImplCandidate(_) @@ -2450,9 +2468,11 @@ impl<'tcx> SelectionContext<'_, 'tcx> { } else { // If this is an ill-formed auto/built-in trait, then synthesize // new error args for the missing generics. - let err_args = ty::GenericArgs::extend_with_error(tcx, trait_def_id, &[ - normalized_ty.into(), - ]); + let err_args = ty::GenericArgs::extend_with_error( + tcx, + trait_def_id, + &[normalized_ty.into()], + ); ty::TraitRef::new_from_args(tcx, trait_def_id, err_args) }; @@ -3154,7 +3174,11 @@ impl<'o, 'tcx> TraitObligationStackList<'o, 'tcx> { } fn depth(&self) -> usize { - if let Some(head) = self.head { head.depth } else { 0 } + if let Some(head) = self.head { + head.depth + } else { + 0 + } } } From 71ed4559585c66672ff0a28a524881d227380369 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Thu, 14 Nov 2024 11:08:06 -0700 Subject: [PATCH 5/7] rustdoc-search: case-sensitive only when capitals are used This is the "smartcase" behavior, described by vim and dtolnay. (cherry picked from commit 32500aa8e0f23029c0fa69235d19f770106c016f) --- src/librustdoc/html/static/js/search.js | 11 +++++++---- tests/rustdoc-js-std/write.js | 24 ++++++++++++++++++++++++ tests/rustdoc-js/case.js | 17 +++++++++++++++++ tests/rustdoc-js/case.rs | 7 +++++++ 4 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 tests/rustdoc-js-std/write.js create mode 100644 tests/rustdoc-js/case.js create mode 100644 tests/rustdoc-js/case.rs diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index eed64d024c0..526a32e194a 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -2098,6 +2098,7 @@ class DocSearch { const sortResults = async(results, isType, preferredCrate) => { const userQuery = parsedQuery.userQuery; const casedUserQuery = parsedQuery.original; + const isMixedCase = casedUserQuery !== userQuery; const result_list = []; for (const result of results.values()) { result.item = this.searchIndex[result.id]; @@ -2109,10 +2110,12 @@ class DocSearch { let a, b; // sort by exact case-sensitive match - a = (aaa.item.name !== casedUserQuery); - b = (bbb.item.name !== casedUserQuery); - if (a !== b) { - return a - b; + if (isMixedCase) { + a = (aaa.item.name !== casedUserQuery); + b = (bbb.item.name !== casedUserQuery); + if (a !== b) { + return a - b; + } } // sort by exact match with regard to the last word (mismatch goes later) diff --git a/tests/rustdoc-js-std/write.js b/tests/rustdoc-js-std/write.js new file mode 100644 index 00000000000..4a9475102a5 --- /dev/null +++ b/tests/rustdoc-js-std/write.js @@ -0,0 +1,24 @@ +const EXPECTED = [ + { + 'query': 'write', + 'others': [ + { 'path': 'std::fmt', 'name': 'write' }, + { 'path': 'std::fs', 'name': 'write' }, + { 'path': 'std::ptr', 'name': 'write' }, + { 'path': 'std::fmt', 'name': 'Write' }, + { 'path': 'std::io', 'name': 'Write' }, + { 'path': 'std::hash::Hasher', 'name': 'write' }, + ], + }, + { + 'query': 'Write', + 'others': [ + { 'path': 'std::fmt', 'name': 'Write' }, + { 'path': 'std::io', 'name': 'Write' }, + { 'path': 'std::fmt', 'name': 'write' }, + { 'path': 'std::fs', 'name': 'write' }, + { 'path': 'std::ptr', 'name': 'write' }, + { 'path': 'std::hash::Hasher', 'name': 'write' }, + ], + }, +]; diff --git a/tests/rustdoc-js/case.js b/tests/rustdoc-js/case.js new file mode 100644 index 00000000000..22b970eb139 --- /dev/null +++ b/tests/rustdoc-js/case.js @@ -0,0 +1,17 @@ +const EXPECTED = [ + { + 'query': 'Foo', + 'others': [ + { 'path': 'case', 'name': 'Foo', 'desc': 'Docs for Foo' }, + { 'path': 'case', 'name': 'foo', 'desc': 'Docs for foo' }, + ], + }, + { + 'query': 'foo', + 'others': [ + // https://github.com/rust-lang/rust/issues/133017 + { 'path': 'case', 'name': 'Foo', 'desc': 'Docs for Foo' }, + { 'path': 'case', 'name': 'foo', 'desc': 'Docs for foo' }, + ], + }, +]; diff --git a/tests/rustdoc-js/case.rs b/tests/rustdoc-js/case.rs new file mode 100644 index 00000000000..532edd55f1d --- /dev/null +++ b/tests/rustdoc-js/case.rs @@ -0,0 +1,7 @@ +#![allow(nonstandard_style)] + +/// Docs for Foo +pub struct Foo; + +/// Docs for foo +pub struct foo; From 7757d3257191ab6b8fe90c1b3429de9729081025 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Fri, 11 Oct 2024 13:47:08 -0700 Subject: [PATCH 6/7] (ci) Update macOS to Xcode 15 (cherry picked from commit 94579ff9301fcee893cd0c4ad9284ab5ef51e6cd) --- src/ci/github-actions/jobs.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 8f49f623afa..876abb6d915 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -46,7 +46,7 @@ envs: RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 MACOSX_DEPLOYMENT_TARGET: 10.12 MACOSX_STD_DEPLOYMENT_TARGET: 10.12 - SELECT_XCODE: /Applications/Xcode_14.3.1.app + SELECT_XCODE: /Applications/Xcode_15.2.app NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 @@ -282,7 +282,7 @@ auto: RUST_CONFIGURE_ARGS: --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set rust.lto=thin --set rust.codegen-units=1 RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 MACOSX_DEPLOYMENT_TARGET: 10.12 - SELECT_XCODE: /Applications/Xcode_14.3.1.app + SELECT_XCODE: /Applications/Xcode_15.2.app NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 @@ -298,7 +298,7 @@ auto: RUST_CONFIGURE_ARGS: --enable-sanitizers --enable-profiler --set rust.jemalloc --set target.aarch64-apple-ios-macabi.sanitizers=false --set target.x86_64-apple-ios-macabi.sanitizers=false RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 MACOSX_DEPLOYMENT_TARGET: 10.12 - SELECT_XCODE: /Applications/Xcode_14.3.1.app + SELECT_XCODE: /Applications/Xcode_15.2.app NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 @@ -327,7 +327,7 @@ auto: --set llvm.ninja=false --set rust.lto=thin RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - SELECT_XCODE: /Applications/Xcode_14.3.1.app + SELECT_XCODE: /Applications/Xcode_15.4.app USE_XCODE_CLANG: 1 MACOSX_DEPLOYMENT_TARGET: 11.0 MACOSX_STD_DEPLOYMENT_TARGET: 11.0 @@ -347,7 +347,7 @@ auto: --enable-profiler --set rust.jemalloc RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - SELECT_XCODE: /Applications/Xcode_14.3.1.app + SELECT_XCODE: /Applications/Xcode_15.4.app USE_XCODE_CLANG: 1 MACOSX_DEPLOYMENT_TARGET: 11.0 MACOSX_STD_DEPLOYMENT_TARGET: 11.0 From 48c21ba81836684c4089bc2407c11a87b73fe4db Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 21 Oct 2024 11:40:12 -0700 Subject: [PATCH 7/7] Update debuginfo test for newer lldb For reasons I don't understand, lldb in Xcode 15 no longer prints objects as: (long) $0 = 19 instead, it is printing them as: (long) 19 (cherry picked from commit 16b91e887afcdbfe0db2232639f0c9d33b7e2246) --- tests/debuginfo/constant-ordering-prologue.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/debuginfo/constant-ordering-prologue.rs b/tests/debuginfo/constant-ordering-prologue.rs index f2d4fd37ce3..3136aff238a 100644 --- a/tests/debuginfo/constant-ordering-prologue.rs +++ b/tests/debuginfo/constant-ordering-prologue.rs @@ -20,11 +20,11 @@ // lldb-command:run // lldb-command:print a -// lldb-check: = 19 +// lldb-check: 19 // lldb-command:print b -// lldb-check: = 20 +// lldb-check: 20 // lldb-command:print c -// lldb-check: = 21.5 +// lldb-check: 21.5 fn binding(a: i64, b: u64, c: f64) { let x = 0;