Skip to content

Commit 4193abc

Browse files
committed
Fix import search not discarding rawness
1 parent 7ddeaba commit 4193abc

File tree

8 files changed

+65
-29
lines changed

8 files changed

+65
-29
lines changed

src/tools/rust-analyzer/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ exclude = ["crates/proc-macro-srv/proc-macro-test/imp"]
44
resolver = "2"
55

66
[workspace.package]
7-
rust-version = "1.82"
7+
rust-version = "1.83"
88
edition = "2021"
99
license = "MIT OR Apache-2.0"
1010
authors = ["rust-analyzer team"]

src/tools/rust-analyzer/crates/hir-expand/src/name.rs

+33-7
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use syntax::utils::is_raw_identifier;
1111
/// and declarations. In theory, names should also carry hygiene info, but we are
1212
/// not there yet!
1313
///
14-
/// Note that the rawness (`r#`) of names does not depend on whether they are written raw.
14+
/// Note that the rawness (`r#`) of names is not preserved. Names are always stored without a `r#` prefix.
1515
/// This is because we want to show (in completions etc.) names as raw depending on the needs
1616
/// of the current crate, for example if it is edition 2021 complete `gen` even if the defining
1717
/// crate is in edition 2024 and wrote `r#gen`, and the opposite holds as well.
@@ -77,6 +77,7 @@ impl Name {
7777
/// Hopefully, this should allow us to integrate hygiene cleaner in the
7878
/// future, and to switch to interned representation of names.
7979
fn new_text(text: &str) -> Name {
80+
debug_assert!(!text.starts_with("r#"));
8081
Name { symbol: Symbol::intern(text), ctx: () }
8182
}
8283

@@ -91,15 +92,34 @@ impl Name {
9192

9293
pub fn new_root(text: &str) -> Name {
9394
// The edition doesn't matter for hygiene.
94-
Self::new(text, SyntaxContextId::root(Edition::Edition2015))
95+
Self::new(text.trim_start_matches("r#"), SyntaxContextId::root(Edition::Edition2015))
9596
}
9697

9798
pub fn new_tuple_field(idx: usize) -> Name {
98-
Name { symbol: Symbol::intern(&idx.to_string()), ctx: () }
99+
let symbol = match idx {
100+
0 => sym::INTEGER_0.clone(),
101+
1 => sym::INTEGER_1.clone(),
102+
2 => sym::INTEGER_2.clone(),
103+
3 => sym::INTEGER_3.clone(),
104+
4 => sym::INTEGER_4.clone(),
105+
5 => sym::INTEGER_5.clone(),
106+
6 => sym::INTEGER_6.clone(),
107+
7 => sym::INTEGER_7.clone(),
108+
8 => sym::INTEGER_8.clone(),
109+
9 => sym::INTEGER_9.clone(),
110+
10 => sym::INTEGER_10.clone(),
111+
11 => sym::INTEGER_11.clone(),
112+
12 => sym::INTEGER_12.clone(),
113+
13 => sym::INTEGER_13.clone(),
114+
14 => sym::INTEGER_14.clone(),
115+
15 => sym::INTEGER_15.clone(),
116+
_ => Symbol::intern(&idx.to_string()),
117+
};
118+
Name { symbol, ctx: () }
99119
}
100120

101121
pub fn new_lifetime(lt: &ast::Lifetime) -> Name {
102-
Name { symbol: Symbol::intern(lt.text().as_str()), ctx: () }
122+
Self::new_text(lt.text().as_str().trim_start_matches("r#"))
103123
}
104124

105125
/// Resolve a name from the text of token.
@@ -142,15 +162,18 @@ impl Name {
142162
}
143163

144164
/// Returns the text this name represents if it isn't a tuple field.
165+
///
166+
/// Do not use this for user-facing text, use `display` instead to handle editions properly.
145167
pub fn as_str(&self) -> &str {
146168
self.symbol.as_str()
147169
}
148170

171+
// FIXME: Remove this
149172
pub fn unescaped(&self) -> UnescapedName<'_> {
150173
UnescapedName(self)
151174
}
152175

153-
pub fn is_escaped(&self, edition: Edition) -> bool {
176+
pub fn needs_escape(&self, edition: Edition) -> bool {
154177
is_raw_identifier(self.symbol.as_str(), edition)
155178
}
156179

@@ -173,16 +196,19 @@ impl Name {
173196
&self.symbol
174197
}
175198

176-
pub const fn new_symbol(symbol: Symbol, ctx: SyntaxContextId) -> Self {
199+
pub fn new_symbol(symbol: Symbol, ctx: SyntaxContextId) -> Self {
200+
debug_assert!(!symbol.as_str().starts_with("r#"));
177201
_ = ctx;
178202
Self { symbol, ctx: () }
179203
}
180204

181205
// FIXME: This needs to go once we have hygiene
182-
pub const fn new_symbol_root(sym: Symbol) -> Self {
206+
pub fn new_symbol_root(sym: Symbol) -> Self {
207+
debug_assert!(!sym.as_str().starts_with("r#"));
183208
Self { symbol: sym, ctx: () }
184209
}
185210

211+
// FIXME: Remove this
186212
#[inline]
187213
pub fn eq_ident(&self, ident: &str) -> bool {
188214
self.as_str() == ident.trim_start_matches("r#")

src/tools/rust-analyzer/crates/hir/src/semantics.rs

+4-7
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ use stdx::TupleExt;
3939
use syntax::{
4040
algo::skip_trivia_token,
4141
ast::{self, HasAttrs as _, HasGenericParams},
42-
AstNode, AstToken, Direction, SmolStr, SyntaxKind, SyntaxNode, SyntaxNodePtr, SyntaxToken,
43-
TextRange, TextSize,
42+
AstNode, AstToken, Direction, SyntaxKind, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange,
43+
TextSize,
4444
};
4545
use triomphe::Arc;
4646

@@ -1587,14 +1587,11 @@ impl<'db> SemanticsImpl<'db> {
15871587
pub fn resolve_mod_path_relative(
15881588
&self,
15891589
to: Module,
1590-
segments: impl IntoIterator<Item = SmolStr>,
1590+
segments: impl IntoIterator<Item = Name>,
15911591
) -> Option<impl Iterator<Item = ItemInNs>> {
15921592
let items = to.id.resolver(self.db.upcast()).resolve_module_path_in_items(
15931593
self.db.upcast(),
1594-
&ModPath::from_segments(
1595-
hir_def::path::PathKind::Plain,
1596-
segments.into_iter().map(|it| Name::new_root(&it)),
1597-
),
1594+
&ModPath::from_segments(hir_def::path::PathKind::Plain, segments),
15981595
);
15991596
Some(items.iter_items().map(|(item, _)| item.into()))
16001597
}

src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use ide_db::imports::{
55
insert_use::ImportScope,
66
};
77
use itertools::Itertools;
8-
use syntax::{ast, AstNode, SyntaxNode, ToSmolStr, T};
8+
use syntax::{ast, AstNode, SyntaxNode, ToSmolStr};
99

1010
use crate::{
1111
config::AutoImportExclusionType,
@@ -403,10 +403,11 @@ fn import_on_the_fly_method(
403403

404404
fn import_name(ctx: &CompletionContext<'_>) -> String {
405405
let token_kind = ctx.token.kind();
406-
if matches!(token_kind, T![.] | T![::]) {
407-
String::new()
408-
} else {
406+
407+
if token_kind.is_any_identifier() {
409408
ctx.token.to_string()
409+
} else {
410+
String::new()
410411
}
411412
}
412413

src/tools/rust-analyzer/crates/ide-completion/src/render.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ fn render_resolution_path(
423423

424424
let name = local_name.display_no_db(ctx.completion.edition).to_smolstr();
425425
let mut item = render_resolution_simple_(ctx, &local_name, import_to_add, resolution);
426-
if local_name.is_escaped(completion.edition) {
426+
if local_name.needs_escape(completion.edition) {
427427
item.insert_text(local_name.display_no_db(completion.edition).to_smolstr());
428428
}
429429
// Add `<>` for generic types

src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs

+14-6
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ use std::ops::ControlFlow;
44

55
use hir::{
66
db::HirDatabase, AsAssocItem, AssocItem, AssocItemContainer, Crate, HasCrate, ImportPathConfig,
7-
ItemInNs, ModPath, Module, ModuleDef, PathResolution, PrefixKind, ScopeDef, Semantics,
7+
ItemInNs, ModPath, Module, ModuleDef, Name, PathResolution, PrefixKind, ScopeDef, Semantics,
88
SemanticsScope, Trait, TyFingerprint, Type,
99
};
1010
use itertools::Itertools;
1111
use rustc_hash::{FxHashMap, FxHashSet};
1212
use syntax::{
1313
ast::{self, make, HasName},
14-
AstNode, SmolStr, SyntaxNode,
14+
AstNode, SyntaxNode,
1515
};
1616

1717
use crate::{
@@ -53,7 +53,7 @@ pub struct TraitImportCandidate {
5353
#[derive(Debug)]
5454
pub struct PathImportCandidate {
5555
/// Optional qualifier before name.
56-
pub qualifier: Vec<SmolStr>,
56+
pub qualifier: Vec<Name>,
5757
/// The name the item (struct, trait, enum, etc.) should have.
5858
pub name: NameToImport,
5959
}
@@ -72,10 +72,18 @@ pub enum NameToImport {
7272

7373
impl NameToImport {
7474
pub fn exact_case_sensitive(s: String) -> NameToImport {
75+
let s = match s.strip_prefix("r#") {
76+
Some(s) => s.to_owned(),
77+
None => s,
78+
};
7579
NameToImport::Exact(s, true)
7680
}
7781

7882
pub fn fuzzy(s: String) -> NameToImport {
83+
let s = match s.strip_prefix("r#") {
84+
Some(s) => s.to_owned(),
85+
None => s,
86+
};
7987
// unless all chars are lowercase, we do a case sensitive search
8088
let case_sensitive = s.chars().any(|c| c.is_uppercase());
8189
NameToImport::Fuzzy(s, case_sensitive)
@@ -359,7 +367,7 @@ fn path_applicable_imports(
359367
[first_qsegment, qualifier_rest @ ..] => items_locator::items_with_name(
360368
sema,
361369
current_crate,
362-
NameToImport::Exact(first_qsegment.to_string(), true),
370+
NameToImport::Exact(first_qsegment.as_str().to_owned(), true),
363371
AssocSearchMode::Exclude,
364372
)
365373
.filter_map(|item| {
@@ -389,7 +397,7 @@ fn validate_resolvable(
389397
scope_filter: impl Fn(ItemInNs) -> bool,
390398
candidate: &NameToImport,
391399
resolved_qualifier: ItemInNs,
392-
unresolved_qualifier: &[SmolStr],
400+
unresolved_qualifier: &[Name],
393401
) -> Option<LocatedImport> {
394402
let _p = tracing::info_span!("ImportAssets::import_for_item").entered();
395403

@@ -722,7 +730,7 @@ fn path_import_candidate(
722730
if qualifier.first_qualifier().is_none_or(|it| sema.resolve_path(&it).is_none()) {
723731
let qualifier = qualifier
724732
.segments()
725-
.map(|seg| seg.name_ref().map(|name| SmolStr::new(name.text())))
733+
.map(|seg| seg.name_ref().map(|name| Name::new_root(&name.text())))
726734
.collect::<Option<Vec<_>>>()?;
727735
ImportCandidate::Path(PathImportCandidate { qualifier, name })
728736
} else {

src/tools/rust-analyzer/crates/ide-db/src/items_locator.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -141,10 +141,11 @@ fn find_items<'a>(
141141
// Query the local crate using the symbol index.
142142
let mut local_results = Vec::new();
143143
local_query.search(&symbol_index::crate_symbols(db, krate), |local_candidate| {
144-
ControlFlow::<()>::Continue(local_results.push(match local_candidate.def {
144+
local_results.push(match local_candidate.def {
145145
hir::ModuleDef::Macro(macro_def) => ItemInNs::Macros(macro_def),
146146
def => ItemInNs::from(def),
147-
}))
147+
});
148+
ControlFlow::<()>::Continue(())
148149
});
149150
local_results.into_iter().chain(external_importables)
150151
}

src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,10 @@ pub fn world_symbols(db: &RootDatabase, query: Query) -> Vec<FileSymbol> {
220220
};
221221

222222
let mut res = vec![];
223-
query.search::<()>(&indices, |f| ControlFlow::Continue(res.push(f.clone())));
223+
query.search::<()>(&indices, |f| {
224+
res.push(f.clone());
225+
ControlFlow::Continue(())
226+
});
224227
res
225228
}
226229

0 commit comments

Comments
 (0)