Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir-def/src/body.rs14
-rw-r--r--crates/hir-def/src/body/pretty.rs65
-rw-r--r--crates/hir-def/src/body/tests.rs6
-rw-r--r--crates/hir-def/src/find_path.rs7
-rw-r--r--crates/hir-def/src/hir/format_args.rs2
-rw-r--r--crates/hir-def/src/hir/type_ref.rs13
-rw-r--r--crates/hir-def/src/import_map.rs16
-rw-r--r--crates/hir-def/src/item_scope.rs3
-rw-r--r--crates/hir-def/src/item_tree.rs6
-rw-r--r--crates/hir-def/src/item_tree/pretty.rs86
-rw-r--r--crates/hir-def/src/item_tree/tests.rs3
-rw-r--r--crates/hir-def/src/nameres.rs6
-rw-r--r--crates/hir-def/src/nameres/collector.rs10
-rw-r--r--crates/hir-def/src/nameres/tests/macros.rs5
-rw-r--r--crates/hir-def/src/nameres/tests/mod_resolution.rs8
-rw-r--r--crates/hir-def/src/path.rs19
-rw-r--r--crates/hir-def/src/pretty.rs84
-rw-r--r--crates/hir-expand/src/eager.rs3
-rw-r--r--crates/hir-expand/src/mod_path.rs46
-rw-r--r--crates/hir-expand/src/name.rs93
-rw-r--r--crates/hir-ty/src/chalk_db.rs18
-rw-r--r--crates/hir-ty/src/consteval/tests.rs10
-rw-r--r--crates/hir-ty/src/diagnostics/decl_check.rs70
-rw-r--r--crates/hir-ty/src/diagnostics/expr.rs30
-rw-r--r--crates/hir-ty/src/diagnostics/match_check.rs35
-rw-r--r--crates/hir-ty/src/display.rs116
-rw-r--r--crates/hir-ty/src/infer/closure.rs4
-rw-r--r--crates/hir-ty/src/layout/tests.rs13
-rw-r--r--crates/hir-ty/src/lib.rs9
-rw-r--r--crates/hir-ty/src/mir.rs5
-rw-r--r--crates/hir-ty/src/mir/eval.rs17
-rw-r--r--crates/hir-ty/src/mir/eval/shim.rs6
-rw-r--r--crates/hir-ty/src/mir/eval/tests.rs6
-rw-r--r--crates/hir-ty/src/mir/lower.rs62
-rw-r--r--crates/hir-ty/src/mir/lower/pattern_matching.rs3
-rw-r--r--crates/hir-ty/src/mir/pretty.rs48
-rw-r--r--crates/hir-ty/src/tls.rs19
-rw-r--r--crates/hir-ty/src/traits.rs3
-rw-r--r--crates/hir/src/attrs.rs8
-rw-r--r--crates/hir/src/display.rs69
-rw-r--r--crates/hir/src/lib.rs84
-rw-r--r--crates/hir/src/symbols.rs16
-rw-r--r--crates/hir/src/term_search/expr.rs55
-rw-r--r--crates/ide-assists/src/handlers/add_missing_impl_members.rs23
-rw-r--r--crates/ide-assists/src/handlers/add_missing_match_arms.rs3
-rw-r--r--crates/ide-assists/src/handlers/auto_import.rs9
-rw-r--r--crates/ide-assists/src/handlers/bool_to_enum.rs6
-rw-r--r--crates/ide-assists/src/handlers/convert_bool_then.rs2
-rw-r--r--crates/ide-assists/src/handlers/convert_into_to_from.rs5
-rw-r--r--crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs12
-rw-r--r--crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs2
-rw-r--r--crates/ide-assists/src/handlers/destructure_struct_binding.rs8
-rw-r--r--crates/ide-assists/src/handlers/expand_glob_import.rs4
-rw-r--r--crates/ide-assists/src/handlers/extract_function.rs69
-rw-r--r--crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs14
-rw-r--r--crates/ide-assists/src/handlers/fill_record_pattern_fields.rs3
-rw-r--r--crates/ide-assists/src/handlers/fix_visibility.rs14
-rw-r--r--crates/ide-assists/src/handlers/generate_delegate_methods.rs3
-rw-r--r--crates/ide-assists/src/handlers/generate_delegate_trait.rs23
-rw-r--r--crates/ide-assists/src/handlers/generate_deref.rs12
-rw-r--r--crates/ide-assists/src/handlers/generate_documentation_template.rs9
-rw-r--r--crates/ide-assists/src/handlers/generate_function.rs24
-rw-r--r--crates/ide-assists/src/handlers/generate_getter_or_setter.rs2
-rw-r--r--crates/ide-assists/src/handlers/generate_new.rs5
-rw-r--r--crates/ide-assists/src/handlers/inline_const_as_literal.rs11
-rw-r--r--crates/ide-assists/src/handlers/move_const_to_impl.rs10
-rw-r--r--crates/ide-assists/src/handlers/move_from_mod_rs.rs2
-rw-r--r--crates/ide-assists/src/handlers/move_module_to_file.rs2
-rw-r--r--crates/ide-assists/src/handlers/move_to_mod_rs.rs2
-rw-r--r--crates/ide-assists/src/handlers/qualify_method_call.rs2
-rw-r--r--crates/ide-assists/src/handlers/qualify_path.rs22
-rw-r--r--crates/ide-assists/src/handlers/reorder_fields.rs13
-rw-r--r--crates/ide-assists/src/handlers/reorder_impl_items.rs5
-rw-r--r--crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs5
-rw-r--r--crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs38
-rw-r--r--crates/ide-assists/src/handlers/term_search.rs6
-rw-r--r--crates/ide-assists/src/handlers/toggle_async_sugar.rs3
-rw-r--r--crates/ide-assists/src/utils.rs20
-rw-r--r--crates/ide-assists/src/utils/suggest_name.rs19
-rw-r--r--crates/ide-completion/src/completions.rs13
-rw-r--r--crates/ide-completion/src/completions/attribute.rs29
-rw-r--r--crates/ide-completion/src/completions/attribute/cfg.rs13
-rw-r--r--crates/ide-completion/src/completions/attribute/derive.rs10
-rw-r--r--crates/ide-completion/src/completions/attribute/lint.rs3
-rw-r--r--crates/ide-completion/src/completions/attribute/macro_use.rs3
-rw-r--r--crates/ide-completion/src/completions/attribute/repr.rs7
-rw-r--r--crates/ide-completion/src/completions/dot.rs1
-rw-r--r--crates/ide-completion/src/completions/env_vars.rs2
-rw-r--r--crates/ide-completion/src/completions/extern_abi.rs9
-rw-r--r--crates/ide-completion/src/completions/extern_crate.rs3
-rw-r--r--crates/ide-completion/src/completions/flyimport.rs2
-rw-r--r--crates/ide-completion/src/completions/fn_param.rs8
-rw-r--r--crates/ide-completion/src/completions/format_string.rs6
-rw-r--r--crates/ide-completion/src/completions/item_list/trait_impl.rs14
-rw-r--r--crates/ide-completion/src/completions/lifetime.rs2
-rw-r--r--crates/ide-completion/src/completions/mod_.rs9
-rw-r--r--crates/ide-completion/src/completions/postfix.rs13
-rw-r--r--crates/ide-completion/src/completions/record.rs2
-rw-r--r--crates/ide-completion/src/completions/snippet.rs3
-rw-r--r--crates/ide-completion/src/completions/use_.rs6
-rw-r--r--crates/ide-completion/src/context.rs9
-rw-r--r--crates/ide-completion/src/context/analysis.rs2
-rw-r--r--crates/ide-completion/src/item.rs11
-rw-r--r--crates/ide-completion/src/lib.rs9
-rw-r--r--crates/ide-completion/src/render.rs70
-rw-r--r--crates/ide-completion/src/render/const_.rs13
-rw-r--r--crates/ide-completion/src/render/function.rs44
-rw-r--r--crates/ide-completion/src/render/literal.rs12
-rw-r--r--crates/ide-completion/src/render/macro_.rs9
-rw-r--r--crates/ide-completion/src/render/pattern.rs35
-rw-r--r--crates/ide-completion/src/render/type_alias.rs18
-rw-r--r--crates/ide-completion/src/render/union_literal.rs34
-rw-r--r--crates/ide-completion/src/render/variant.rs20
-rw-r--r--crates/ide-completion/src/tests.rs24
-rw-r--r--crates/ide-completion/src/tests/raw_identifiers.rs84
-rw-r--r--crates/ide-db/src/defs.rs81
-rw-r--r--crates/ide-db/src/famous_defs.rs9
-rw-r--r--crates/ide-db/src/helpers.rs12
-rw-r--r--crates/ide-db/src/imports/import_assets.rs6
-rw-r--r--crates/ide-db/src/path_transform.rs18
-rw-r--r--crates/ide-db/src/rename.rs74
-rw-r--r--crates/ide-db/src/syntax_helpers/insert_whitespace_into_node.rs5
-rw-r--r--crates/ide-db/src/syntax_helpers/node_ext.rs8
-rw-r--r--crates/ide-db/src/traits.rs21
-rw-r--r--crates/ide-db/src/ty_filter.rs7
-rw-r--r--crates/ide-db/src/use_trivial_constructor.rs4
-rw-r--r--crates/ide-diagnostics/src/handlers/expected_function.rs2
-rw-r--r--crates/ide-diagnostics/src/handlers/json_is_not_rust.rs15
-rw-r--r--crates/ide-diagnostics/src/handlers/missing_fields.rs24
-rw-r--r--crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs2
-rw-r--r--crates/ide-diagnostics/src/handlers/mutability_errors.rs2
-rw-r--r--crates/ide-diagnostics/src/handlers/private_assoc_item.rs2
-rw-r--r--crates/ide-diagnostics/src/handlers/private_field.rs4
-rw-r--r--crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs2
-rw-r--r--crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs10
-rw-r--r--crates/ide-diagnostics/src/handlers/type_mismatch.rs12
-rw-r--r--crates/ide-diagnostics/src/handlers/typed_hole.rs5
-rw-r--r--crates/ide-diagnostics/src/handlers/undeclared_label.rs2
-rw-r--r--crates/ide-diagnostics/src/handlers/unlinked_file.rs11
-rw-r--r--crates/ide-diagnostics/src/handlers/unreachable_label.rs2
-rw-r--r--crates/ide-diagnostics/src/handlers/unresolved_field.rs4
-rw-r--r--crates/ide-diagnostics/src/handlers/unresolved_macro_call.rs2
-rw-r--r--crates/ide-diagnostics/src/handlers/unresolved_method.rs9
-rw-r--r--crates/ide-diagnostics/src/handlers/unused_variables.rs18
-rw-r--r--crates/ide-diagnostics/src/lib.rs49
-rw-r--r--crates/ide-ssr/src/matching.rs10
-rw-r--r--crates/ide-ssr/src/replacing.rs8
-rw-r--r--crates/ide/src/doc_links.rs63
-rw-r--r--crates/ide/src/expand_macro.rs10
-rw-r--r--crates/ide/src/goto_definition.rs4
-rw-r--r--crates/ide/src/highlight_related.rs4
-rw-r--r--crates/ide/src/hover.rs63
-rw-r--r--crates/ide/src/hover/render.rs153
-rw-r--r--crates/ide/src/hover/tests.rs72
-rw-r--r--crates/ide/src/inlay_hints.rs14
-rw-r--r--crates/ide/src/inlay_hints/adjustment.rs6
-rw-r--r--crates/ide/src/inlay_hints/bind_pat.rs4
-rw-r--r--crates/ide/src/inlay_hints/chaining.rs4
-rw-r--r--crates/ide/src/inlay_hints/closing_brace.rs8
-rw-r--r--crates/ide/src/inlay_hints/closure_ret.rs4
-rw-r--r--crates/ide/src/inlay_hints/implicit_drop.rs4
-rw-r--r--crates/ide/src/inlay_hints/param_name.rs4
-rw-r--r--crates/ide/src/moniker.rs45
-rw-r--r--crates/ide/src/navigation_target.rs100
-rw-r--r--crates/ide/src/references.rs5
-rw-r--r--crates/ide/src/rename.rs261
-rw-r--r--crates/ide/src/runnables.rs44
-rw-r--r--crates/ide/src/signature_help.rs103
-rw-r--r--crates/ide/src/static_index.rs16
-rw-r--r--crates/ide/src/syntax_highlighting.rs4
-rw-r--r--crates/ide/src/syntax_highlighting/highlight.rs8
-rw-r--r--crates/ide/src/syntax_highlighting/macro_.rs3
-rw-r--r--crates/ide/src/view_item_tree.rs2
-rw-r--r--crates/ide/src/view_memory_layout.rs16
-rw-r--r--crates/parser/src/syntax_kind.rs9
-rw-r--r--crates/rust-analyzer/src/cli.rs4
-rw-r--r--crates/rust-analyzer/src/cli/analysis_stats.rs77
-rw-r--r--crates/syntax-bridge/src/lib.rs5
-rw-r--r--crates/syntax/src/utils.rs1
179 files changed, 2480 insertions, 1245 deletions
diff --git a/crates/hir-def/src/body.rs b/crates/hir-def/src/body.rs
index a988317e04..f5fe8f8770 100644
--- a/crates/hir-def/src/body.rs
+++ b/crates/hir-def/src/body.rs
@@ -14,7 +14,7 @@ use hir_expand::{name::Name, ExpandError, InFile};
use la_arena::{Arena, ArenaMap, Idx, RawIdx};
use rustc_hash::FxHashMap;
use smallvec::SmallVec;
-use span::MacroFileId;
+use span::{Edition, MacroFileId};
use syntax::{ast, AstPtr, SyntaxNodePtr};
use triomphe::Arc;
@@ -201,8 +201,13 @@ impl Body {
self.block_scopes.iter().map(move |&block| (block, db.block_def_map(block)))
}
- pub fn pretty_print(&self, db: &dyn DefDatabase, owner: DefWithBodyId) -> String {
- pretty::print_body_hir(db, self, owner)
+ pub fn pretty_print(
+ &self,
+ db: &dyn DefDatabase,
+ owner: DefWithBodyId,
+ edition: Edition,
+ ) -> String {
+ pretty::print_body_hir(db, self, owner, edition)
}
pub fn pretty_print_expr(
@@ -210,8 +215,9 @@ impl Body {
db: &dyn DefDatabase,
owner: DefWithBodyId,
expr: ExprId,
+ edition: Edition,
) -> String {
- pretty::print_expr_hir(db, self, owner, expr)
+ pretty::print_expr_hir(db, self, owner, expr, edition)
}
fn new(
diff --git a/crates/hir-def/src/body/pretty.rs b/crates/hir-def/src/body/pretty.rs
index edaee60937..55740a68ac 100644
--- a/crates/hir-def/src/body/pretty.rs
+++ b/crates/hir-def/src/body/pretty.rs
@@ -3,6 +3,7 @@
use std::fmt::{self, Write};
use itertools::Itertools;
+use span::Edition;
use crate::{
hir::{
@@ -15,20 +16,26 @@ use crate::{
use super::*;
-pub(super) fn print_body_hir(db: &dyn DefDatabase, body: &Body, owner: DefWithBodyId) -> String {
+pub(super) fn print_body_hir(
+ db: &dyn DefDatabase,
+ body: &Body,
+ owner: DefWithBodyId,
+ edition: Edition,
+) -> String {
let header = match owner {
- DefWithBodyId::FunctionId(it) => {
- it.lookup(db).id.resolved(db, |it| format!("fn {}", it.name.display(db.upcast())))
- }
+ DefWithBodyId::FunctionId(it) => it
+ .lookup(db)
+ .id
+ .resolved(db, |it| format!("fn {}", it.name.display(db.upcast(), edition))),
DefWithBodyId::StaticId(it) => it
.lookup(db)
.id
- .resolved(db, |it| format!("static {} = ", it.name.display(db.upcast()))),
+ .resolved(db, |it| format!("static {} = ", it.name.display(db.upcast(), edition))),
DefWithBodyId::ConstId(it) => it.lookup(db).id.resolved(db, |it| {
format!(
"const {} = ",
match &it.name {
- Some(name) => name.display(db.upcast()).to_string(),
+ Some(name) => name.display(db.upcast(), edition).to_string(),
None => "_".to_owned(),
}
)
@@ -39,13 +46,13 @@ pub(super) fn print_body_hir(db: &dyn DefDatabase, body: &Body, owner: DefWithBo
let enum_loc = loc.parent.lookup(db);
format!(
"enum {}::{}",
- enum_loc.id.item_tree(db)[enum_loc.id.value].name.display(db.upcast()),
- loc.id.item_tree(db)[loc.id.value].name.display(db.upcast()),
+ enum_loc.id.item_tree(db)[enum_loc.id.value].name.display(db.upcast(), edition),
+ loc.id.item_tree(db)[loc.id.value].name.display(db.upcast(), edition),
)
}
};
- let mut p = Printer { db, body, buf: header, indent_level: 0, needs_indent: false };
+ let mut p = Printer { db, body, buf: header, indent_level: 0, needs_indent: false, edition };
if let DefWithBodyId::FunctionId(it) = owner {
p.buf.push('(');
let function_data = &db.function_data(it);
@@ -86,8 +93,10 @@ pub(super) fn print_expr_hir(
body: &Body,
_owner: DefWithBodyId,
expr: ExprId,
+ edition: Edition,
) -> String {
- let mut p = Printer { db, body, buf: String::new(), indent_level: 0, needs_indent: false };
+ let mut p =
+ Printer { db, body, buf: String::new(), indent_level: 0, needs_indent: false, edition };
p.print_expr(expr);
p.buf
}
@@ -113,6 +122,7 @@ struct Printer<'a> {
buf: String,
indent_level: usize,
needs_indent: bool,
+ edition: Edition,
}
impl Write for Printer<'_> {
@@ -173,13 +183,14 @@ impl Printer<'_> {
Expr::OffsetOf(offset_of) => {
w!(self, "builtin#offset_of(");
self.print_type_ref(&offset_of.container);
+ let edition = self.edition;
w!(
self,
", {})",
offset_of
.fields
.iter()
- .format_with(".", |field, f| f(&field.display(self.db.upcast())))
+ .format_with(".", |field, f| f(&field.display(self.db.upcast(), edition)))
);
}
Expr::Path(path) => self.print_path(path),
@@ -201,7 +212,7 @@ impl Printer<'_> {
}
Expr::Loop { body, label } => {
if let Some(lbl) = label {
- w!(self, "{}: ", self.body[*lbl].name.display(self.db.upcast()));
+ w!(self, "{}: ", self.body[*lbl].name.display(self.db.upcast(), self.edition));
}
w!(self, "loop ");
self.print_expr(*body);
@@ -221,10 +232,11 @@ impl Printer<'_> {
}
Expr::MethodCall { receiver, method_name, args, generic_args } => {
self.print_expr(*receiver);
- w!(self, ".{}", method_name.display(self.db.upcast()));
+ w!(self, ".{}", method_name.display(self.db.upcast(), self.edition));
if let Some(args) = generic_args {
w!(self, "::<");
- print_generic_args(self.db, args, self).unwrap();
+ let edition = self.edition;
+ print_generic_args(self.db, args, self, edition).unwrap();
w!(self, ">");
}
w!(self, "(");
@@ -259,13 +271,13 @@ impl Printer<'_> {
Expr::Continue { label } => {
w!(self, "continue");
if let Some(lbl) = label {
- w!(self, " {}", self.body[*lbl].name.display(self.db.upcast()));
+ w!(self, " {}", self.body[*lbl].name.display(self.db.upcast(), self.edition));
}
}
Expr::Break { expr, label } => {
w!(self, "break");
if let Some(lbl) = label {
- w!(self, " {}", self.body[*lbl].name.display(self.db.upcast()));
+ w!(self, " {}", self.body[*lbl].name.display(self.db.upcast(), self.edition));
}
if let Some(expr) = expr {
self.whitespace();
@@ -307,9 +319,10 @@ impl Printer<'_> {
}
w!(self, "{{");
+ let edition = self.edition;
self.indented(|p| {
for field in &**fields {
- w!(p, "{}: ", field.name.display(self.db.upcast()));
+ w!(p, "{}: ", field.name.display(self.db.upcast(), edition));
p.print_expr(field.expr);
wln!(p, ",");
}
@@ -326,7 +339,7 @@ impl Printer<'_> {
}
Expr::Field { expr, name } => {
self.print_expr(*expr);
- w!(self, ".{}", name.display(self.db.upcast()));
+ w!(self, ".{}", name.display(self.db.upcast(), self.edition));
}
Expr::Await { expr } => {
self.print_expr(*expr);
@@ -464,8 +477,9 @@ impl Printer<'_> {
}
Expr::Literal(lit) => self.print_literal(lit),
Expr::Block { id: _, statements, tail, label } => {
- let label =
- label.map(|lbl| format!("{}: ", self.body[lbl].name.display(self.db.upcast())));
+ let label = label.map(|lbl| {
+ format!("{}: ", self.body[lbl].name.display(self.db.upcast(), self.edition))
+ });
self.print_block(label.as_deref(), statements, tail);
}
Expr::Unsafe { id: _, statements, tail } => {
@@ -539,9 +553,10 @@ impl Printer<'_> {
}
w!(self, " {{");
+ let edition = self.edition;
self.indented(|p| {
for arg in args.iter() {
- w!(p, "{}: ", arg.name.display(self.db.upcast()));
+ w!(p, "{}: ", arg.name.display(self.db.upcast(), edition));
p.print_pat(arg.pat);
wln!(p, ",");
}
@@ -686,11 +701,13 @@ impl Printer<'_> {
}
fn print_type_ref(&mut self, ty: &TypeRef) {
- print_type_ref(self.db, ty, self).unwrap();
+ let edition = self.edition;
+ print_type_ref(self.db, ty, self, edition).unwrap();
}
fn print_path(&mut self, path: &Path) {
- print_path(self.db, path, self).unwrap();
+ let edition = self.edition;
+ print_path(self.db, path, self, edition).unwrap();
}
fn print_binding(&mut self, id: BindingId) {
@@ -701,6 +718,6 @@ impl Printer<'_> {
BindingAnnotation::Ref => "ref ",
BindingAnnotation::RefMut => "ref mut ",
};
- w!(self, "{}{}", mode, name.display(self.db.upcast()));
+ w!(self, "{}{}", mode, name.display(self.db.upcast(), self.edition));
}
}
diff --git a/crates/hir-def/src/body/tests.rs b/crates/hir-def/src/body/tests.rs
index 0011d3a20c..38fc01d8fc 100644
--- a/crates/hir-def/src/body/tests.rs
+++ b/crates/hir-def/src/body/tests.rs
@@ -219,7 +219,7 @@ fn main() {
},
);
}"#]]
- .assert_eq(&body.pretty_print(&db, def))
+ .assert_eq(&body.pretty_print(&db, def, Edition::CURRENT))
}
#[test]
@@ -285,7 +285,7 @@ impl SsrError {
),
);
}"#]]
- .assert_eq(&body.pretty_print(&db, def))
+ .assert_eq(&body.pretty_print(&db, def, Edition::CURRENT))
}
#[test]
@@ -333,5 +333,5 @@ fn f(a: i32, b: u32) -> String {
);
};
}"#]]
- .assert_eq(&body.pretty_print(&db, def))
+ .assert_eq(&body.pretty_print(&db, def, Edition::CURRENT))
}
diff --git a/crates/hir-def/src/find_path.rs b/crates/hir-def/src/find_path.rs
index 5a3a3e9189..f5e03e5281 100644
--- a/crates/hir-def/src/find_path.rs
+++ b/crates/hir-def/src/find_path.rs
@@ -651,6 +651,7 @@ mod tests {
use expect_test::{expect, Expect};
use hir_expand::db::ExpandDatabase;
use itertools::Itertools;
+ use span::Edition;
use stdx::format_to;
use syntax::ast::AstNode;
use test_fixture::WithFixture;
@@ -717,8 +718,10 @@ mod tests {
"{:7}(imports {}): {}\n",
format!("{:?}", prefix),
if ignore_local_imports { '✖' } else { '✔' },
- found_path
- .map_or_else(|| "<unresolvable>".to_owned(), |it| it.display(&db).to_string()),
+ found_path.map_or_else(
+ || "<unresolvable>".to_owned(),
+ |it| it.display(&db, Edition::CURRENT).to_string()
+ ),
);
}
expect.assert_eq(&res);
diff --git a/crates/hir-def/src/hir/format_args.rs b/crates/hir-def/src/hir/format_args.rs
index 390e7da677..e1c3bd25bc 100644
--- a/crates/hir-def/src/hir/format_args.rs
+++ b/crates/hir-def/src/hir/format_args.rs
@@ -250,7 +250,7 @@ pub(crate) fn parse(
}
}
ArgRef::Name(name, span) => {
- let name = Name::new(name, tt::IdentIsRaw::No, call_ctx);
+ let name = Name::new(name, call_ctx);
if let Some((index, _)) = args.by_name(&name) {
record_usage(name, span);
// Name found in `args`, so we resolve it to its index.
diff --git a/crates/hir-def/src/hir/type_ref.rs b/crates/hir-def/src/hir/type_ref.rs
index 8f618b2d30..b74cd90f69 100644
--- a/crates/hir-def/src/hir/type_ref.rs
+++ b/crates/hir-def/src/hir/type_ref.rs
@@ -10,6 +10,7 @@ use hir_expand::{
AstId,
};
use intern::{sym, Interned, Symbol};
+use span::Edition;
use syntax::ast::{self, HasGenericArgs, HasName, IsString};
use crate::{
@@ -419,18 +420,22 @@ impl ConstRef {
param.default_val().map(|default| Self::from_const_arg(lower_ctx, Some(default)))
}
- pub fn display<'a>(&'a self, db: &'a dyn ExpandDatabase) -> impl fmt::Display + 'a {
- struct Display<'a>(&'a dyn ExpandDatabase, &'a ConstRef);
+ pub fn display<'a>(
+ &'a self,
+ db: &'a dyn ExpandDatabase,
+ edition: Edition,
+ ) -> impl fmt::Display + 'a {
+ struct Display<'a>(&'a dyn ExpandDatabase, &'a ConstRef, Edition);
impl fmt::Display for Display<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.1 {
ConstRef::Scalar(s) => s.fmt(f),
- ConstRef::Path(n) => n.display(self.0).fmt(f),
+ ConstRef::Path(n) => n.display(self.0, self.2).fmt(f),
ConstRef::Complex(_) => f.write_str("{const}"),
}
}
}
- Display(db, self)
+ Display(db, self, edition)
}
// We special case literals and single identifiers, to speed up things.
diff --git a/crates/hir-def/src/import_map.rs b/crates/hir-def/src/import_map.rs
index 8cc022e4c6..9574e5d9cd 100644
--- a/crates/hir-def/src/import_map.rs
+++ b/crates/hir-def/src/import_map.rs
@@ -8,6 +8,7 @@ use hir_expand::name::Name;
use itertools::Itertools;
use rustc_hash::FxHashSet;
use smallvec::SmallVec;
+use span::Edition;
use stdx::{format_to, TupleExt};
use syntax::ToSmolStr;
use triomphe::Arc;
@@ -66,7 +67,12 @@ impl ImportMap {
for (k, v) in self.item_to_info_map.iter() {
format_to!(out, "{:?} ({:?}) -> ", k, v.1);
for v in &v.0 {
- format_to!(out, "{}:{:?}, ", v.name.display(db.upcast()), v.container);
+ format_to!(
+ out,
+ "{}:{:?}, ",
+ v.name.display(db.upcast(), Edition::CURRENT),
+ v.container
+ );
}
format_to!(out, "\n");
}
@@ -83,7 +89,7 @@ impl ImportMap {
// We've only collected items, whose name cannot be tuple field so unwrapping is fine.
.flat_map(|(&item, (info, _))| {
info.iter().enumerate().map(move |(idx, info)| {
- (item, info.name.display(db.upcast()).to_smolstr(), idx as u32)
+ (item, info.name.unescaped().display(db.upcast()).to_smolstr(), idx as u32)
})
})
.collect();
@@ -461,7 +467,7 @@ fn search_maps(
query.search_mode.check(
&query.query,
query.case_sensitive,
- &info.name.display(db.upcast()).to_smolstr(),
+ &info.name.unescaped().display(db.upcast()).to_smolstr(),
)
});
res.extend(iter.map(TupleExt::head));
@@ -577,7 +583,7 @@ mod tests {
Some(format!(
"{}::{}",
render_path(db, &trait_info[0]),
- assoc_item_name.display(db.upcast())
+ assoc_item_name.display(db.upcast(), Edition::CURRENT)
))
}
@@ -616,7 +622,7 @@ mod tests {
module = parent;
}
- segments.iter().rev().map(|it| it.display(db.upcast())).join("::")
+ segments.iter().rev().map(|it| it.display(db.upcast(), Edition::CURRENT)).join("::")
}
#[test]
diff --git a/crates/hir-def/src/item_scope.rs b/crates/hir-def/src/item_scope.rs
index df6b1f55c1..89b011094a 100644
--- a/crates/hir-def/src/item_scope.rs
+++ b/crates/hir-def/src/item_scope.rs
@@ -9,6 +9,7 @@ use la_arena::Idx;
use once_cell::sync::Lazy;
use rustc_hash::{FxHashMap, FxHashSet};
use smallvec::{smallvec, SmallVec};
+use span::Edition;
use stdx::format_to;
use syntax::ast;
@@ -706,7 +707,7 @@ impl ItemScope {
format_to!(
buf,
"{}:",
- name.map_or("_".to_owned(), |name| name.display(db).to_string())
+ name.map_or("_".to_owned(), |name| name.display(db, Edition::LATEST).to_string())
);
if let Some((.., i)) = def.types {
diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs
index 28eebb286e..517f40ebd1 100644
--- a/crates/hir-def/src/item_tree.rs
+++ b/crates/hir-def/src/item_tree.rs
@@ -51,7 +51,7 @@ use la_arena::{Arena, Idx, RawIdx};
use once_cell::sync::OnceCell;
use rustc_hash::FxHashMap;
use smallvec::SmallVec;
-use span::{AstIdNode, FileAstId, SyntaxContextId};
+use span::{AstIdNode, Edition, FileAstId, SyntaxContextId};
use stdx::never;
use syntax::{ast, match_ast, SyntaxKind};
use triomphe::Arc;
@@ -199,8 +199,8 @@ impl ItemTree {
Attrs::filter(db, krate, self.raw_attrs(of).clone())
}
- pub fn pretty_print(&self, db: &dyn DefDatabase) -> String {
- pretty::print_item_tree(db, self)
+ pub fn pretty_print(&self, db: &dyn DefDatabase, edition: Edition) -> String {
+ pretty::print_item_tree(db, self, edition)
}
fn data(&self) -> &ItemTreeData {
diff --git a/crates/hir-def/src/item_tree/pretty.rs b/crates/hir-def/src/item_tree/pretty.rs
index 740759e6e3..b5a65abce8 100644
--- a/crates/hir-def/src/item_tree/pretty.rs
+++ b/crates/hir-def/src/item_tree/pretty.rs
@@ -3,7 +3,7 @@
use std::fmt::{self, Write};
use la_arena::{Idx, RawIdx};
-use span::ErasedFileAstId;
+use span::{Edition, ErasedFileAstId};
use crate::{
generics::{TypeOrConstParamData, WherePredicate, WherePredicateTypeTarget},
@@ -18,8 +18,9 @@ use crate::{
visibility::RawVisibility,
};
-pub(super) fn print_item_tree(db: &dyn DefDatabase, tree: &ItemTree) -> String {
- let mut p = Printer { db, tree, buf: String::new(), indent_level: 0, needs_indent: true };
+pub(super) fn print_item_tree(db: &dyn DefDatabase, tree: &ItemTree, edition: Edition) -> String {
+ let mut p =
+ Printer { db, tree, buf: String::new(), indent_level: 0, needs_indent: true, edition };
if let Some(attrs) = tree.attrs.get(&AttrOwner::TopLevel) {
p.print_attrs(attrs, true, "\n");
@@ -56,6 +57,7 @@ struct Printer<'a> {
buf: String,
indent_level: usize,
needs_indent: bool,
+ edition: Edition,
}
impl Printer<'_> {
@@ -97,7 +99,7 @@ impl Printer<'_> {
self,
"#{}[{}{}]{}",
inner,
- attr.path.display(self.db.upcast()),
+ attr.path.display(self.db.upcast(), self.edition),
attr.input.as_ref().map(|it| it.to_string()).unwrap_or_default(),
separated_by,
);
@@ -113,13 +115,14 @@ impl Printer<'_> {
fn print_visibility(&mut self, vis: RawVisibilityId) {
match &self.tree[vis] {
RawVisibility::Module(path, _expl) => {
- w!(self, "pub({}) ", path.display(self.db.upcast()))
+ w!(self, "pub({}) ", path.display(self.db.upcast(), self.edition))
}
RawVisibility::Public => w!(self, "pub "),
};
}
fn print_fields(&mut self, parent: FieldParent, kind: FieldsShape, fields: &[Field]) {
+ let edition = self.edition;
match kind {
FieldsShape::Record => {
self.whitespace();
@@ -131,7 +134,7 @@ impl Printer<'_> {
"\n",
);
this.print_visibility(*visibility);
- w!(this, "{}: ", name.display(self.db.upcast()));
+ w!(this, "{}: ", name.display(self.db.upcast(), edition));
this.print_type_ref(type_ref);
wln!(this, ",");
}
@@ -147,7 +150,7 @@ impl Printer<'_> {
"\n",
);
this.print_visibility(*visibility);
- w!(this, "{}: ", name.display(self.db.upcast()));
+ w!(this, "{}: ", name.display(self.db.upcast(), edition));
this.print_type_ref(type_ref);
wln!(this, ",");
}
@@ -186,20 +189,20 @@ impl Printer<'_> {
fn print_use_tree(&mut self, use_tree: &UseTree) {
match &use_tree.kind {
UseTreeKind::Single { path, alias } => {
- w!(self, "{}", path.display(self.db.upcast()));
+ w!(self, "{}", path.display(self.db.upcast(), self.edition));
if let Some(alias) = alias {
- w!(self, " as {}", alias);
+ w!(self, " as {}", alias.display(self.edition));
}
}
UseTreeKind::Glob { path } => {
if let Some(path) = path {
- w!(self, "{}::", path.display(self.db.upcast()));
+ w!(self, "{}::", path.display(self.db.upcast(), self.edition));
}
w!(self, "*");
}
UseTreeKind::Prefixed { prefix, list } => {
if let Some(prefix) = prefix {
- w!(self, "{}::", prefix.display(self.db.upcast()));
+ w!(self, "{}::", prefix.display(self.db.upcast(), self.edition));
}
w!(self, "{{");
for (i, tree) in list.iter().enumerate() {
@@ -229,9 +232,9 @@ impl Printer<'_> {
let ExternCrate { name, alias, visibility, ast_id } = &self.tree[it];
self.print_ast_id(ast_id.erase());
self.print_visibility(*visibility);
- w!(self, "extern crate {}", name.display(self.db.upcast()));
+ w!(self, "extern crate {}", name.display(self.db.upcast(), self.edition));
if let Some(alias) = alias {
- w!(self, " as {}", alias);
+ w!(self, " as {}", alias.display(self.edition));
}
wln!(self, ";");
}
@@ -278,7 +281,7 @@ impl Printer<'_> {
if let Some(abi) = abi {
w!(self, "extern \"{}\" ", abi);
}
- w!(self, "fn {}", name.display(self.db.upcast()));
+ w!(self, "fn {}", name.display(self.db.upcast(), self.edition));
self.print_generic_params(explicit_generic_params, it.into());
w!(self, "(");
if !params.is_empty() {
@@ -314,7 +317,7 @@ impl Printer<'_> {
&self.tree[it];
self.print_ast_id(ast_id.erase());
self.print_visibility(*visibility);
- w!(self, "struct {}", name.display(self.db.upcast()));
+ w!(self, "struct {}", name.display(self.db.upcast(), self.edition));
self.print_generic_params(generic_params, it.into());
self.print_fields_and_where_clause(
FieldParent::Struct(it),
@@ -332,7 +335,7 @@ impl Printer<'_> {
let Union { name, visibility, fields, generic_params, ast_id } = &self.tree[it];
self.print_ast_id(ast_id.erase());
self.print_visibility(*visibility);
- w!(self, "union {}", name.display(self.db.upcast()));
+ w!(self, "union {}", name.display(self.db.upcast(), self.edition));
self.print_generic_params(generic_params, it.into());
self.print_fields_and_where_clause(
FieldParent::Union(it),
@@ -346,15 +349,16 @@ impl Printer<'_> {
let Enum { name, visibility, variants, generic_params, ast_id } = &self.tree[it];
self.print_ast_id(ast_id.erase());
self.print_visibility(*visibility);
- w!(self, "enum {}", name.display(self.db.upcast()));
+ w!(self, "enum {}", name.display(self.db.upcast(), self.edition));
self.print_generic_params(generic_params, it.into());
self.print_where_clause_and_opening_brace(generic_params);
+ let edition = self.edition;
self.indented(|this| {
for variant in FileItemTreeId::range_iter(variants.clone()) {
let Variant { name, fields, shape: kind, ast_id } = &this.tree[variant];
this.print_ast_id(ast_id.erase());
this.print_attrs_of(variant, "\n");
- w!(this, "{}", name.display(self.db.upcast()));
+ w!(this, "{}", name.display(self.db.upcast(), edition));
this.print_fields(FieldParent::Variant(variant), *kind, fields);
wln!(this, ",");
}
@@ -367,7 +371,7 @@ impl Printer<'_> {
self.print_visibility(*visibility);
w!(self, "const ");
match name {
- Some(name) => w!(self, "{}", name.display(self.db.upcast())),
+ Some(name) => w!(self, "{}", name.display(self.db.upcast(), self.edition)),
None => w!(self, "_"),
}
w!(self, ": ");
@@ -382,7 +386,7 @@ impl Printer<'_> {
if *mutable {
w!(self, "mut ");
}
- w!(self, "{}: ", name.display(self.db.upcast()));
+ w!(self, "{}: ", name.display(self.db.upcast(), self.edition));
self.print_type_ref(type_ref);
w!(self, " = _;");
wln!(self);
@@ -398,7 +402,7 @@ impl Printer<'_> {
if *is_auto {
w!(self, "auto ");
}
- w!(self, "trait {}", name.display(self.db.upcast()));
+ w!(self, "trait {}", name.display(self.db.upcast(), self.edition));
self.print_generic_params(generic_params, it.into());
self.print_where_clause_and_opening_brace(generic_params);
self.indented(|this| {
@@ -412,7 +416,7 @@ impl Printer<'_> {
let TraitAlias { name, visibility, generic_params, ast_id } = &self.tree[it];
self.print_ast_id(ast_id.erase());
self.print_visibility(*visibility);
- w!(self, "trait {}", name.display(self.db.upcast()));
+ w!(self, "trait {}", name.display(self.db.upcast(), self.edition));
self.print_generic_params(generic_params, it.into());
w!(self, " = ");
self.print_where_clause(generic_params);
@@ -457,7 +461,7 @@ impl Printer<'_> {
&self.tree[it];
self.print_ast_id(ast_id.erase());
self.print_visibility(*visibility);
- w!(self, "type {}", name.display(self.db.upcast()));
+ w!(self, "type {}", name.display(self.db.upcast(), self.edition));
self.print_generic_params(generic_params, it.into());
if !bounds.is_empty() {
w!(self, ": ");
@@ -475,7 +479,7 @@ impl Printer<'_> {
let Mod { name, visibility, kind, ast_id } = &self.tree[it];
self.print_ast_id(ast_id.erase());
self.print_visibility(*visibility);
- w!(self, "mod {}", name.display(self.db.upcast()));
+ w!(self, "mod {}", name.display(self.db.upcast(), self.edition));
match kind {
ModKind::Inline { items } => {
w!(self, " {{");
@@ -500,18 +504,22 @@ impl Printer<'_> {
ctxt,
expand_to
);
- wln!(self, "{}!(...);", path.display(self.db.upcast()));
+ wln!(self, "{}!(...);", path.display(self.db.upcast(), self.edition));
}
ModItem::MacroRules(it) => {
let MacroRules { name, ast_id } = &self.tree[it];
self.print_ast_id(ast_id.erase());
- wln!(self, "macro_rules! {} {{ ... }}", name.display(self.db.upcast()));
+ wln!(
+ self,
+ "macro_rules! {} {{ ... }}",
+ name.display(self.db.upcast(), self.edition)
+ );
}
ModItem::Macro2(it) => {
let Macro2 { name, visibility, ast_id } = &self.tree[it];
self.print_ast_id(ast_id.erase());
self.print_visibility(*visibility);
- wln!(self, "macro {} {{ ... }}", name.display(self.db.upcast()));
+ wln!(self, "macro {} {{ ... }}", name.display(self.db.upcast(), self.edition));
}
}
@@ -519,15 +527,18 @@ impl Printer<'_> {
}
fn print_type_ref(&mut self, type_ref: &TypeRef) {
- print_type_ref(self.db, type_ref, self).unwrap();
+ let edition = self.edition;
+ print_type_ref(self.db, type_ref, self, edition).unwrap();
}
fn print_type_bounds(&mut self, bounds: &[Interned<TypeBound>]) {
- print_type_bounds(self.db, bounds, self).unwrap();
+ let edition = self.edition;
+ print_type_bounds(self.db, bounds, self, edition).unwrap();
}
fn print_path(&mut self, path: &Path) {
- print_path(self.db, path, self).unwrap();
+ let edition = self.edition;
+ print_path(self.db, path, self, edition).unwrap();
}
fn print_generic_params(&mut self, params: &GenericParams, parent: GenericModItem) {
@@ -543,7 +554,7 @@ impl Printer<'_> {
}
first = false;
self.print_attrs_of(AttrOwner::LifetimeParamData(parent, idx), " ");
- w!(self, "{}", lt.name.display(self.db.upcast()));
+ w!(self, "{}", lt.name.display(self.db.upcast(), self.edition));
}
for (idx, x) in params.iter_type_or_consts() {
if !first {
@@ -553,11 +564,11 @@ impl Printer<'_> {
self.print_attrs_of(AttrOwner::TypeOrConstParamData(parent, idx), " ");
match x {
TypeOrConstParamData::TypeParamData(ty) => match &ty.name {
- Some(name) => w!(self, "{}", name.display(self.db.upcast())),
+ Some(name) => w!(self, "{}", name.display(self.db.upcast(), self.edition)),
None => w!(self, "_anon_{}", idx.into_raw()),
},
TypeOrConstParamData::ConstParamData(konst) => {
- w!(self, "const {}: ", konst.name.display(self.db.upcast()));
+ w!(self, "const {}: ", konst.name.display(self.db.upcast(), self.edition));
self.print_type_ref(&konst.ty);
}
}
@@ -580,6 +591,7 @@ impl Printer<'_> {
}
w!(self, "\nwhere");
+ let edition = self.edition;
self.indented(|this| {
for (i, pred) in params.where_predicates().enumerate() {
if i != 0 {
@@ -592,8 +604,8 @@ impl Printer<'_> {
wln!(
this,
"{}: {},",
- target.name.display(self.db.upcast()),
- bound.name.display(self.db.upcast())
+ target.name.display(self.db.upcast(), edition),
+ bound.name.display(self.db.upcast(), edition)
);
continue;
}
@@ -603,7 +615,7 @@ impl Printer<'_> {
if i != 0 {
w!(this, ", ");
}
- w!(this, "{}", lt.display(self.db.upcast()));
+ w!(this, "{}", lt.display(self.db.upcast(), edition));
}
w!(this, "> ");
(target, bound)
@@ -613,7 +625,7 @@ impl Printer<'_> {
match target {
WherePredicateTypeTarget::TypeRef(ty) => this.print_type_ref(ty),
WherePredicateTypeTarget::TypeOrConstParam(id) => match params[*id].name() {
- Some(name) => w!(this, "{}", name.display(self.db.upcast())),
+ Some(name) => w!(this, "{}", name.display(self.db.upcast(), edition)),
None => w!(this, "_anon_{}", id.into_raw()),
},
}
diff --git a/crates/hir-def/src/item_tree/tests.rs b/crates/hir-def/src/item_tree/tests.rs
index c6930401a6..5c07369f4b 100644
--- a/crates/hir-def/src/item_tree/tests.rs
+++ b/crates/hir-def/src/item_tree/tests.rs
@@ -1,4 +1,5 @@
use expect_test::{expect, Expect};
+use span::Edition;
use test_fixture::WithFixture;
use crate::{db::DefDatabase, test_db::TestDB};
@@ -6,7 +7,7 @@ use crate::{db::DefDatabase, test_db::TestDB};
fn check(ra_fixture: &str, expect: Expect) {
let (db, file_id) = TestDB::with_single_file(ra_fixture);
let item_tree = db.file_item_tree(file_id.into());
- let pretty = item_tree.pretty_print(&db);
+ let pretty = item_tree.pretty_print(&db, Edition::CURRENT);
expect.assert_eq(&pretty);
}
diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs
index 8825e46336..11601c683e 100644
--- a/crates/hir-def/src/nameres.rs
+++ b/crates/hir-def/src/nameres.rs
@@ -328,6 +328,10 @@ impl DefMap {
/// The module id of a crate or block root.
pub const ROOT: LocalModuleId = LocalModuleId::from_raw(la_arena::RawIdx::from_u32(0));
+ pub fn edition(&self) -> Edition {
+ self.data.edition
+ }
+
pub(crate) fn crate_def_map_query(db: &dyn DefDatabase, crate_id: CrateId) -> Arc<DefMap> {
let crate_graph = db.crate_graph();
let krate = &crate_graph[crate_id];
@@ -550,7 +554,7 @@ impl DefMap {
for (name, child) in
map.modules[module].children.iter().sorted_by(|a, b| Ord::cmp(&a.0, &b.0))
{
- let path = format!("{path}::{}", name.display(db.upcast()));
+ let path = format!("{path}::{}", name.display(db.upcast(), Edition::LATEST));
buf.push('\n');
go(buf, db, map, &path, *child);
}
diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs
index debc5a4432..22eb5a174d 100644
--- a/crates/hir-def/src/nameres/collector.rs
+++ b/crates/hir-def/src/nameres/collector.rs
@@ -548,7 +548,7 @@ impl DefCollector<'_> {
types => {
tracing::debug!(
"could not resolve prelude path `{}` to module (resolved to {:?})",
- path.display(self.db.upcast()),
+ path.display(self.db.upcast(), Edition::LATEST),
types
);
}
@@ -768,7 +768,7 @@ impl DefCollector<'_> {
}
fn resolve_import(&self, module_id: LocalModuleId, import: &Import) -> PartialResolvedImport {
- let _p = tracing::info_span!("resolve_import", import_path = %import.path.display(self.db.upcast()))
+ let _p = tracing::info_span!("resolve_import", import_path = %import.path.display(self.db.upcast(), Edition::LATEST))
.entered();
tracing::debug!("resolving import: {:?} ({:?})", import, self.def_map.data.edition);
match import.source {
@@ -2151,7 +2151,7 @@ impl ModCollector<'_, '_> {
}
tracing::debug!(
"non-builtin attribute {}",
- attr.path.display(self.def_collector.db.upcast())
+ attr.path.display(self.def_collector.db.upcast(), Edition::LATEST)
);
let ast_id = AstIdWithPath::new(
@@ -2286,8 +2286,8 @@ impl ModCollector<'_, '_> {
stdx::always!(
name == mac.name,
"built-in macro {} has #[rustc_builtin_macro] which declares different name {}",
- mac.name.display(self.def_collector.db.upcast()),
- name.display(self.def_collector.db.upcast())
+ mac.name.display(self.def_collector.db.upcast(), Edition::LATEST),
+ name.display(self.def_collector.db.upcast(), Edition::LATEST),
);
helpers_opt = Some(helpers);
}
diff --git a/crates/hir-def/src/nameres/tests/macros.rs b/crates/hir-def/src/nameres/tests/macros.rs
index 390c934f6d..a05c4dcf9b 100644
--- a/crates/hir-def/src/nameres/tests/macros.rs
+++ b/crates/hir-def/src/nameres/tests/macros.rs
@@ -1,6 +1,7 @@
use expect_test::expect;
use itertools::Itertools;
+use span::Edition;
use super::*;
@@ -1100,7 +1101,7 @@ pub fn derive_macro_2(_item: TokenStream) -> TokenStream {
assert_eq!(def_map.data.exported_derives.len(), 1);
match def_map.data.exported_derives.values().next() {
Some(helpers) => match &**helpers {
- [attr] => assert_eq!(attr.display(&db).to_string(), "helper_attr"),
+ [attr] => assert_eq!(attr.display(&db, Edition::CURRENT).to_string(), "helper_attr"),
_ => unreachable!(),
},
_ => unreachable!(),
@@ -1456,7 +1457,7 @@ fn proc_attr(a: TokenStream, b: TokenStream) -> TokenStream { a }
let actual = def_map
.macro_use_prelude
.keys()
- .map(|name| name.display(&db).to_string())
+ .map(|name| name.display(&db, Edition::CURRENT).to_string())
.sorted()
.join("\n");
diff --git a/crates/hir-def/src/nameres/tests/mod_resolution.rs b/crates/hir-def/src/nameres/tests/mod_resolution.rs
index 1327d9aa62..071b55c83d 100644
--- a/crates/hir-def/src/nameres/tests/mod_resolution.rs
+++ b/crates/hir-def/src/nameres/tests/mod_resolution.rs
@@ -144,14 +144,14 @@ pub struct Baz;
crate::r#async
Bar: t v
- foo: t
r#async: t
-
- crate::r#async::foo
- Foo: t v
+ foo: t
crate::r#async::r#async
Baz: t v
+
+ crate::r#async::foo
+ Foo: t v
"#]],
);
}
diff --git a/crates/hir-def/src/path.rs b/crates/hir-def/src/path.rs
index f90bc954a9..077863c0c9 100644
--- a/crates/hir-def/src/path.rs
+++ b/crates/hir-def/src/path.rs
@@ -13,7 +13,8 @@ use crate::{
};
use hir_expand::name::Name;
use intern::Interned;
-use syntax::{ast, ToSmolStr};
+use span::Edition;
+use syntax::ast;
pub use hir_expand::mod_path::{path, ModPath, PathKind};
@@ -25,11 +26,21 @@ pub enum ImportAlias {
Alias(Name),
}
-impl Display for ImportAlias {
+impl ImportAlias {
+ pub fn display(&self, edition: Edition) -> impl Display + '_ {
+ ImportAliasDisplay { value: self, edition }
+ }
+}
+
+struct ImportAliasDisplay<'a> {
+ value: &'a ImportAlias,
+ edition: Edition,
+}
+impl Display for ImportAliasDisplay<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
+ match self.value {
ImportAlias::Underscore => f.write_str("_"),
- ImportAlias::Alias(name) => f.write_str(&name.display_no_db().to_smolstr()),
+ ImportAlias::Alias(name) => Display::fmt(&name.display_no_db(self.edition), f),
}
}
}
diff --git a/crates/hir-def/src/pretty.rs b/crates/hir-def/src/pretty.rs
index 3ee88b536f..d5ef17a91f 100644
--- a/crates/hir-def/src/pretty.rs
+++ b/crates/hir-def/src/pretty.rs
@@ -5,6 +5,7 @@ use std::fmt::{self, Write};
use hir_expand::mod_path::PathKind;
use intern::Interned;
use itertools::Itertools;
+use span::Edition;
use crate::{
db::DefDatabase,
@@ -13,46 +14,51 @@ use crate::{
type_ref::{Mutability, TraitBoundModifier, TypeBound, TypeRef},
};
-pub(crate) fn print_path(db: &dyn DefDatabase, path: &Path, buf: &mut dyn Write) -> fmt::Result {
+pub(crate) fn print_path(
+ db: &dyn DefDatabase,
+ path: &Path,
+ buf: &mut dyn Write,
+ edition: Edition,
+) -> fmt::Result {
if let Path::LangItem(it, s) = path {
write!(buf, "builtin#lang(")?;
match *it {
LangItemTarget::ImplDef(it) => write!(buf, "{it:?}")?,
LangItemTarget::EnumId(it) => {
- write!(buf, "{}", db.enum_data(it).name.display(db.upcast()))?
+ write!(buf, "{}", db.enum_data(it).name.display(db.upcast(), edition))?
}
LangItemTarget::Function(it) => {
- write!(buf, "{}", db.function_data(it).name.display(db.upcast()))?
+ write!(buf, "{}", db.function_data(it).name.display(db.upcast(), edition))?
}
LangItemTarget::Static(it) => {
- write!(buf, "{}", db.static_data(it).name.display(db.upcast()))?
+ write!(buf, "{}", db.static_data(it).name.display(db.upcast(), edition))?
}
LangItemTarget::Struct(it) => {
- write!(buf, "{}", db.struct_data(it).name.display(db.upcast()))?
+ write!(buf, "{}", db.struct_data(it).name.display(db.upcast(), edition))?
}
LangItemTarget::Union(it) => {
- write!(buf, "{}", db.union_data(it).name.display(db.upcast()))?
+ write!(buf, "{}", db.union_data(it).name.display(db.upcast(), edition))?
}
LangItemTarget::TypeAlias(it) => {
- write!(buf, "{}", db.type_alias_data(it).name.display(db.upcast()))?
+ write!(buf, "{}", db.type_alias_data(it).name.display(db.upcast(), edition))?
}
LangItemTarget::Trait(it) => {
- write!(buf, "{}", db.trait_data(it).name.display(db.upcast()))?
+ write!(buf, "{}", db.trait_data(it).name.display(db.upcast(), edition))?
}
LangItemTarget::EnumVariant(it) => {
- write!(buf, "{}", db.enum_variant_data(it).name.display(db.upcast()))?
+ write!(buf, "{}", db.enum_variant_data(it).name.display(db.upcast(), edition))?
}
}
if let Some(s) = s {
- write!(buf, "::{}", s.display(db.upcast()))?;
+ write!(buf, "::{}", s.display(db.upcast(), edition))?;
}
return write!(buf, ")");
}
match path.type_anchor() {
Some(anchor) => {
write!(buf, "<")?;
- print_type_ref(db, anchor, buf)?;
+ print_type_ref(db, anchor, buf, edition)?;
write!(buf, ">::")?;
}
None => match path.kind() {
@@ -78,10 +84,10 @@ pub(crate) fn print_path(db: &dyn DefDatabase, path: &Path, buf: &mut dyn Write)
write!(buf, "::")?;
}
- write!(buf, "{}", segment.name.display(db.upcast()))?;
+ write!(buf, "{}", segment.name.display(db.upcast(), edition))?;
if let Some(generics) = segment.args_and_bindings {
write!(buf, "::<")?;
- print_generic_args(db, generics, buf)?;
+ print_generic_args(db, generics, buf, edition)?;
write!(buf, ">")?;
}
@@ -94,12 +100,13 @@ pub(crate) fn print_generic_args(
db: &dyn DefDatabase,
generics: &GenericArgs,
buf: &mut dyn Write,
+ edition: Edition,
) -> fmt::Result {
let mut first = true;
let args = if generics.has_self_type {
let (self_ty, args) = generics.args.split_first().unwrap();
write!(buf, "Self=")?;
- print_generic_arg(db, self_ty, buf)?;
+ print_generic_arg(db, self_ty, buf, edition)?;
first = false;
args
} else {
@@ -110,21 +117,21 @@ pub(crate) fn print_generic_args(
write!(buf, ", ")?;
}
first = false;
- print_generic_arg(db, arg, buf)?;
+ print_generic_arg(db, arg, buf, edition)?;
}
for binding in generics.bindings.iter() {
if !first {
write!(buf, ", ")?;
}
first = false;
- write!(buf, "{}", binding.name.display(db.upcast()))?;
+ write!(buf, "{}", binding.name.display(db.upcast(), edition))?;
if !binding.bounds.is_empty() {
write!(buf, ": ")?;
- print_type_bounds(db, &binding.bounds, buf)?;
+ print_type_bounds(db, &binding.bounds, buf, edition)?;
}
if let Some(ty) = &binding.type_ref {
write!(buf, " = ")?;
- print_type_ref(db, ty, buf)?;
+ print_type_ref(db, ty, buf, edition)?;
}
}
Ok(())
@@ -134,11 +141,12 @@ pub(crate) fn print_generic_arg(
db: &dyn DefDatabase,
arg: &GenericArg,
buf: &mut dyn Write,
+ edition: Edition,
) -> fmt::Result {
match arg {
- GenericArg::Type(ty) => print_type_ref(db, ty, buf),
- GenericArg::Const(c) => write!(buf, "{}", c.display(db.upcast())),
- GenericArg::Lifetime(lt) => write!(buf, "{}", lt.name.display(db.upcast())),
+ GenericArg::Type(ty) => print_type_ref(db, ty, buf, edition),
+ GenericArg::Const(c) => write!(buf, "{}", c.display(db.upcast(), edition)),
+ GenericArg::Lifetime(lt) => write!(buf, "{}", lt.name.display(db.upcast(), edition)),
}
}
@@ -146,6 +154,7 @@ pub(crate) fn print_type_ref(
db: &dyn DefDatabase,
type_ref: &TypeRef,
buf: &mut dyn Write,
+ edition: Edition,
) -> fmt::Result {
// FIXME: deduplicate with `HirDisplay` impl
match type_ref {
@@ -157,18 +166,18 @@ pub(crate) fn print_type_ref(
if i != 0 {
write!(buf, ", ")?;
}
- print_type_ref(db, field, buf)?;
+ print_type_ref(db, field, buf, edition)?;
}
write!(buf, ")")?;
}
- TypeRef::Path(path) => print_path(db, path, buf)?,
+ TypeRef::Path(path) => print_path(db, path, buf, edition)?,
TypeRef::RawPtr(pointee, mtbl) => {
let mtbl = match mtbl {
Mutability::Shared => "*const",
Mutability::Mut => "*mut",
};
write!(buf, "{mtbl} ")?;
- print_type_ref(db, pointee, buf)?;
+ print_type_ref(db, pointee, buf, edition)?;
}
TypeRef::Reference(pointee, lt, mtbl) => {
let mtbl = match mtbl {
@@ -177,19 +186,19 @@ pub(crate) fn print_type_ref(
};
write!(buf, "&")?;
if let Some(lt) = lt {
- write!(buf, "{} ", lt.name.display(db.upcast()))?;
+ write!(buf, "{} ", lt.name.display(db.upcast(), edition))?;
}
write!(buf, "{mtbl}")?;
- print_type_ref(db, pointee, buf)?;
+ print_type_ref(db, pointee, buf, edition)?;
}
TypeRef::Array(elem, len) => {
write!(buf, "[")?;
- print_type_ref(db, elem, buf)?;
- write!(buf, "; {}]", len.display(db.upcast()))?;
+ print_type_ref(db, elem, buf, edition)?;
+ write!(buf, "; {}]", len.display(db.upcast(), edition))?;
}
TypeRef::Slice(elem) => {
write!(buf, "[")?;
- print_type_ref(db, elem, buf)?;
+ print_type_ref(db, elem, buf, edition)?;
write!(buf, "]")?;
}
TypeRef::Fn(args_and_ret, varargs, is_unsafe, abi) => {
@@ -208,7 +217,7 @@ pub(crate) fn print_type_ref(
if i != 0 {
write!(buf, ", ")?;
}
- print_type_ref(db, typeref, buf)?;
+ print_type_ref(db, typeref, buf, edition)?;
}
if *varargs {
if !args.is_empty() {
@@ -217,7 +226,7 @@ pub(crate) fn print_type_ref(
write!(buf, "...")?;
}
write!(buf, ") -> ")?;
- print_type_ref(db, return_type, buf)?;
+ print_type_ref(db, return_type, buf, edition)?;
}
TypeRef::Macro(_ast_id) => {
write!(buf, "<macro>")?;
@@ -225,11 +234,11 @@ pub(crate) fn print_type_ref(
TypeRef::Error => write!(buf, "{{unknown}}")?,
TypeRef::ImplTrait(bounds) => {
write!(buf, "impl ")?;
- print_type_bounds(db, bounds, buf)?;
+ print_type_bounds(db, bounds, buf, edition)?;
}
TypeRef::DynTrait(bounds) => {
write!(buf, "dyn ")?;
- print_type_bounds(db, bounds, buf)?;
+ print_type_bounds(db, bounds, buf, edition)?;
}
}
@@ -240,6 +249,7 @@ pub(crate) fn print_type_bounds(
db: &dyn DefDatabase,
bounds: &[Interned<TypeBound>],
buf: &mut dyn Write,
+ edition: Edition,
) -> fmt::Result {
for (i, bound) in bounds.iter().enumerate() {
if i != 0 {
@@ -252,17 +262,17 @@ pub(crate) fn print_type_bounds(
TraitBoundModifier::None => (),
TraitBoundModifier::Maybe => write!(buf, "?")?,
}
- print_path(db, path, buf)?;
+ print_path(db, path, buf, edition)?;
}
TypeBound::ForLifetime(lifetimes, path) => {
write!(
buf,
"for<{}> ",
- lifetimes.iter().map(|it| it.display(db.upcast())).format(", ")
+ lifetimes.iter().map(|it| it.display(db.upcast(), edition)).format(", ")
)?;
- print_path(db, path, buf)?;
+ print_path(db, path, buf, edition)?;
}
- TypeBound::Lifetime(lt) => write!(buf, "{}", lt.name.display(db.upcast()))?,
+ TypeBound::Lifetime(lt) => write!(buf, "{}", lt.name.display(db.upcast(), edition))?,
TypeBound::Error => write!(buf, "{{unknown}}")?,
}
}
diff --git a/crates/hir-expand/src/eager.rs b/crates/hir-expand/src/eager.rs
index 3528b2dde7..1dadfe2ba9 100644
--- a/crates/hir-expand/src/eager.rs
+++ b/crates/hir-expand/src/eager.rs
@@ -176,9 +176,10 @@ fn eager_macro_recur(
Some(path) => match macro_resolver(&path) {
Some(def) => def,
None => {
+ let edition = db.crate_graph()[krate].edition;
error = Some(ExpandError::other(
span_map.span_at(call.syntax().text_range().start()),
- format!("unresolved macro {}", path.display(db)),
+ format!("unresolved macro {}", path.display(db, edition)),
));
offset += call.syntax().text_range().len();
continue;
diff --git a/crates/hir-expand/src/mod_path.rs b/crates/hir-expand/src/mod_path.rs
index 2c26fe414d..dcf2af3997 100644
--- a/crates/hir-expand/src/mod_path.rs
+++ b/crates/hir-expand/src/mod_path.rs
@@ -14,7 +14,7 @@ use crate::{
use base_db::CrateId;
use intern::sym;
use smallvec::SmallVec;
-use span::SyntaxContextId;
+use span::{Edition, SyntaxContextId};
use syntax::{ast, AstNode};
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
@@ -140,8 +140,12 @@ impl ModPath {
UnescapedModPath(self)
}
- pub fn display<'a>(&'a self, db: &'a dyn crate::db::ExpandDatabase) -> impl fmt::Display + 'a {
- Display { db, path: self }
+ pub fn display<'a>(
+ &'a self,
+ db: &'a dyn crate::db::ExpandDatabase,
+ edition: Edition,
+ ) -> impl fmt::Display + 'a {
+ Display { db, path: self, edition }
}
}
@@ -154,11 +158,12 @@ impl Extend<Name> for ModPath {
struct Display<'a> {
db: &'a dyn ExpandDatabase,
path: &'a ModPath,
+ edition: Edition,
}
impl fmt::Display for Display<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- display_fmt_path(self.db, self.path, f, true)
+ display_fmt_path(self.db, self.path, f, Escape::IfNeeded(self.edition))
}
}
@@ -169,7 +174,7 @@ struct UnescapedDisplay<'a> {
impl fmt::Display for UnescapedDisplay<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- display_fmt_path(self.db, self.path.0, f, false)
+ display_fmt_path(self.db, self.path.0, f, Escape::No)
}
}
@@ -178,11 +183,17 @@ impl From<Name> for ModPath {
ModPath::from_segments(PathKind::Plain, iter::once(name))
}
}
+
+enum Escape {
+ No,
+ IfNeeded(Edition),
+}
+
fn display_fmt_path(
db: &dyn ExpandDatabase,
path: &ModPath,
f: &mut fmt::Formatter<'_>,
- escaped: bool,
+ escaped: Escape,
) -> fmt::Result {
let mut first_segment = true;
let mut add_segment = |s| -> fmt::Result {
@@ -210,10 +221,9 @@ fn display_fmt_path(
f.write_str("::")?;
}
first_segment = false;
- if escaped {
- segment.display(db).fmt(f)?;
- } else {
- segment.unescaped().display(db).fmt(f)?;
+ match escaped {
+ Escape::IfNeeded(edition) => segment.display(db, edition).fmt(f)?,
+ Escape::No => segment.unescaped().display(db).fmt(f)?,
}
}
Ok(())
@@ -322,9 +332,11 @@ fn convert_path_tt(db: &dyn ExpandDatabase, tt: &[tt::TokenTree]) -> Option<ModP
tt::Leaf::Ident(tt::Ident { sym: text, .. }) if *text == sym::self_ => PathKind::SELF,
tt::Leaf::Ident(tt::Ident { sym: text, .. }) if *text == sym::super_ => {
let mut deg = 1;
- while let Some(tt::Leaf::Ident(tt::Ident { sym: text, span, is_raw })) = leaves.next() {
+ while let Some(tt::Leaf::Ident(tt::Ident { sym: text, span, is_raw: _ })) =
+ leaves.next()
+ {
if *text != sym::super_ {
- segments.push(Name::new_symbol_maybe_raw(text.clone(), *is_raw, span.ctx));
+ segments.push(Name::new_symbol(text.clone(), span.ctx));
break;
}
deg += 1;
@@ -333,19 +345,13 @@ fn convert_path_tt(db: &dyn ExpandDatabase, tt: &[tt::TokenTree]) -> Option<ModP
}
tt::Leaf::Ident(tt::Ident { sym: text, .. }) if *text == sym::crate_ => PathKind::Crate,
tt::Leaf::Ident(ident) => {
- segments.push(Name::new_symbol_maybe_raw(
- ident.sym.clone(),
- ident.is_raw,
- ident.span.ctx,
- ));
+ segments.push(Name::new_symbol(ident.sym.clone(), ident.span.ctx));
PathKind::Plain
}
_ => return None,
};
segments.extend(leaves.filter_map(|leaf| match leaf {
- ::tt::Leaf::Ident(ident) => {
- Some(Name::new_symbol_maybe_raw(ident.sym.clone(), ident.is_raw, ident.span.ctx))
- }
+ ::tt::Leaf::Ident(ident) => Some(Name::new_symbol(ident.sym.clone(), ident.span.ctx)),
_ => None,
}));
Some(ModPath { kind, segments })
diff --git a/crates/hir-expand/src/name.rs b/crates/hir-expand/src/name.rs
index 2a52aaba6a..54313904a7 100644
--- a/crates/hir-expand/src/name.rs
+++ b/crates/hir-expand/src/name.rs
@@ -3,22 +3,22 @@
use std::fmt;
use intern::{sym, Symbol};
-use span::SyntaxContextId;
-use syntax::{ast, utils::is_raw_identifier};
+use span::{Edition, SyntaxContextId};
+use syntax::ast;
+use syntax::utils::is_raw_identifier;
/// `Name` is a wrapper around string, which is used in hir for both references
/// and declarations. In theory, names should also carry hygiene info, but we are
/// not there yet!
///
-/// Note that `Name` holds and prints escaped name i.e. prefixed with "r#" when it
-/// is a raw identifier. Use [`unescaped()`][Name::unescaped] when you need the
-/// name without "r#".
+/// Note that the rawness (`r#`) of names does not depend on whether they are written raw.
+/// This is because we want to show (in completions etc.) names as raw depending on the needs
+/// of the current crate, for example if it is edition 2021 complete `gen` even if the defining
+/// crate is in edition 2024 and wrote `r#gen`, and the opposite holds as well.
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct Name {
symbol: Symbol,
ctx: (),
- // FIXME: We should probably encode rawness as a property here instead, once we have hygiene
- // in here we've got 4 bytes of padding to fill anyways
}
impl fmt::Debug for Name {
@@ -42,6 +42,7 @@ impl PartialOrd for Name {
}
}
+// No need to strip `r#`, all comparisons are done against well-known symbols.
impl PartialEq<Symbol> for Name {
fn eq(&self, sym: &Symbol) -> bool {
self.symbol == *sym
@@ -55,16 +56,16 @@ impl PartialEq<Name> for Symbol {
}
/// Wrapper of `Name` to print the name without "r#" even when it is a raw identifier.
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct UnescapedName<'a>(&'a Name);
-impl UnescapedName<'_> {
- pub fn display(&self, db: &dyn crate::db::ExpandDatabase) -> impl fmt::Display + '_ {
+impl<'a> UnescapedName<'a> {
+ pub fn display(self, db: &dyn crate::db::ExpandDatabase) -> impl fmt::Display + 'a {
_ = db;
UnescapedDisplay { name: self }
}
#[doc(hidden)]
- pub fn display_no_db(&self) -> impl fmt::Display + '_ {
+ pub fn display_no_db(self) -> impl fmt::Display + 'a {
UnescapedDisplay { name: self }
}
}
@@ -77,16 +78,9 @@ impl Name {
Name { symbol: Symbol::intern(text), ctx: () }
}
- pub fn new(text: &str, raw: tt::IdentIsRaw, ctx: SyntaxContextId) -> Name {
+ pub fn new(text: &str, ctx: SyntaxContextId) -> Name {
_ = ctx;
- Name {
- symbol: if raw.yes() {
- Symbol::intern(&format!("{}{text}", raw.as_str()))
- } else {
- Symbol::intern(text)
- },
- ctx: (),
- }
+ Self::new_text(text)
}
pub fn new_tuple_field(idx: usize) -> Name {
@@ -97,26 +91,9 @@ impl Name {
Name { symbol: Symbol::intern(lt.text().as_str()), ctx: () }
}
- /// Shortcut to create a name from a string literal.
- fn new_ref(text: &str) -> Name {
- Name { symbol: Symbol::intern(text), ctx: () }
- }
-
/// Resolve a name from the text of token.
fn resolve(raw_text: &str) -> Name {
- // FIXME: Edition
- match raw_text.strip_prefix("r#") {
- // When `raw_text` starts with "r#" but the name does not coincide with any
- // keyword, we never need the prefix so we strip it.
- Some(text) if !is_raw_identifier(text, span::Edition::CURRENT) => Name::new_ref(text),
- // Keywords (in the current edition) *can* be used as a name in earlier editions of
- // Rust, e.g. "try" in Rust 2015. Even in such cases, we keep track of them in their
- // escaped form.
- None if is_raw_identifier(raw_text, span::Edition::CURRENT) => {
- Name::new_text(&format!("r#{}", raw_text))
- }
- _ => Name::new_text(raw_text),
- }
+ Name::new_text(raw_text.trim_start_matches("r#"))
}
/// A fake name for things missing in the source code.
@@ -162,19 +139,23 @@ impl Name {
UnescapedName(self)
}
- pub fn is_escaped(&self) -> bool {
- self.symbol.as_str().starts_with("r#")
+ pub fn is_escaped(&self, edition: Edition) -> bool {
+ is_raw_identifier(self.symbol.as_str(), edition)
}
- pub fn display<'a>(&'a self, db: &dyn crate::db::ExpandDatabase) -> impl fmt::Display + 'a {
+ pub fn display<'a>(
+ &'a self,
+ db: &dyn crate::db::ExpandDatabase,
+ edition: Edition,
+ ) -> impl fmt::Display + 'a {
_ = db;
- Display { name: self }
+ self.display_no_db(edition)
}
// FIXME: Remove this
#[doc(hidden)]
- pub fn display_no_db(&self) -> impl fmt::Display + '_ {
- Display { name: self }
+ pub fn display_no_db(&self, edition: Edition) -> impl fmt::Display + '_ {
+ Display { name: self, needs_escaping: is_raw_identifier(self.symbol.as_str(), edition) }
}
pub fn symbol(&self) -> &Symbol {
@@ -186,39 +167,39 @@ impl Name {
Self { symbol, ctx: () }
}
- pub fn new_symbol_maybe_raw(sym: Symbol, raw: tt::IdentIsRaw, ctx: SyntaxContextId) -> Self {
- if raw.no() {
- Self { symbol: sym, ctx: () }
- } else {
- Name::new(sym.as_str(), raw, ctx)
- }
- }
-
// FIXME: This needs to go once we have hygiene
pub const fn new_symbol_root(sym: Symbol) -> Self {
Self { symbol: sym, ctx: () }
}
+
+ #[inline]
+ pub fn eq_ident(&self, ident: &str) -> bool {
+ self.as_str() == ident.trim_start_matches("r#")
+ }
}
struct Display<'a> {
name: &'a Name,
+ needs_escaping: bool,
}
impl fmt::Display for Display<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ if self.needs_escaping {
+ write!(f, "r#")?;
+ }
fmt::Display::fmt(self.name.symbol.as_str(), f)
}
}
struct UnescapedDisplay<'a> {
- name: &'a UnescapedName<'a>,
+ name: UnescapedName<'a>,
}
impl fmt::Display for UnescapedDisplay<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- let symbol = &self.name.0.symbol.as_str();
- let text = symbol.strip_prefix("r#").unwrap_or(symbol);
- fmt::Display::fmt(&text, f)
+ let symbol = self.name.0.symbol.as_str();
+ fmt::Display::fmt(symbol, f)
}
}
diff --git a/crates/hir-ty/src/chalk_db.rs b/crates/hir-ty/src/chalk_db.rs
index a151ee01e6..a3e4da5d1a 100644
--- a/crates/hir-ty/src/chalk_db.rs
+++ b/crates/hir-ty/src/chalk_db.rs
@@ -5,6 +5,7 @@ use std::{iter, ops::ControlFlow, sync::Arc};
use hir_expand::name::Name;
use intern::sym;
+use span::Edition;
use tracing::debug;
use chalk_ir::{cast::Caster, fold::shift::Shift, CanonicalVarKinds};
@@ -424,18 +425,19 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
fn trait_name(&self, trait_id: chalk_ir::TraitId<Interner>) -> String {
let id = from_chalk_trait_id(trait_id);
- self.db.trait_data(id).name.display(self.db.upcast()).to_string()
+ self.db.trait_data(id).name.display(self.db.upcast(), self.edition()).to_string()
}
fn adt_name(&self, chalk_ir::AdtId(adt_id): AdtId) -> String {
+ let edition = self.edition();
match adt_id {
hir_def::AdtId::StructId(id) => {
- self.db.struct_data(id).name.display(self.db.upcast()).to_string()
+ self.db.struct_data(id).name.display(self.db.upcast(), edition).to_string()
}
hir_def::AdtId::EnumId(id) => {
- self.db.enum_data(id).name.display(self.db.upcast()).to_string()
+ self.db.enum_data(id).name.display(self.db.upcast(), edition).to_string()
}
hir_def::AdtId::UnionId(id) => {
- self.db.union_data(id).name.display(self.db.upcast()).to_string()
+ self.db.union_data(id).name.display(self.db.upcast(), edition).to_string()
}
}
}
@@ -445,7 +447,7 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
}
fn assoc_type_name(&self, assoc_ty_id: chalk_ir::AssocTypeId<Interner>) -> String {
let id = self.db.associated_ty_data(assoc_ty_id).name;
- self.db.type_alias_data(id).name.display(self.db.upcast()).to_string()
+ self.db.type_alias_data(id).name.display(self.db.upcast(), self.edition()).to_string()
}
fn opaque_type_name(&self, opaque_ty_id: chalk_ir::OpaqueTyId<Interner>) -> String {
format!("Opaque_{}", opaque_ty_id.0)
@@ -519,6 +521,10 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
}
impl<'a> ChalkContext<'a> {
+ fn edition(&self) -> Edition {
+ self.db.crate_graph()[self.krate].edition
+ }
+
fn for_trait_impls(
&self,
trait_id: hir_def::TraitId,
@@ -843,7 +849,7 @@ fn impl_def_datum(
"impl {:?}: {}{} where {:?}",
chalk_id,
if negative { "!" } else { "" },
- trait_ref.display(db),
+ trait_ref.display(db, db.crate_graph()[krate].edition),
where_clauses
);
diff --git a/crates/hir-ty/src/consteval/tests.rs b/crates/hir-ty/src/consteval/tests.rs
index dc3817ce3f..a0399a06f2 100644
--- a/crates/hir-ty/src/consteval/tests.rs
+++ b/crates/hir-ty/src/consteval/tests.rs
@@ -1,3 +1,4 @@
+use base_db::SourceDatabase;
use chalk_ir::Substitution;
use hir_def::db::DefDatabase;
use rustc_apfloat::{
@@ -94,9 +95,10 @@ fn check_answer(ra_fixture: &str, check: impl FnOnce(&[u8], &MemoryMap)) {
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.test_crate()].edition;
match e {
- ConstEvalError::MirLowerError(e) => e.pretty_print(&mut err, &db, span_formatter),
- ConstEvalError::MirEvalError(e) => e.pretty_print(&mut err, &db, span_formatter),
+ ConstEvalError::MirLowerError(e) => e.pretty_print(&mut err, &db, span_formatter, edition),
+ ConstEvalError::MirEvalError(e) => e.pretty_print(&mut err, &db, span_formatter, edition),
}
.unwrap();
err
@@ -110,7 +112,9 @@ fn eval_goal(db: &TestDB, file_id: EditionedFileId) -> Result<Const, ConstEvalEr
.declarations()
.find_map(|x| match x {
hir_def::ModuleDefId::ConstId(x) => {
- if db.const_data(x).name.as_ref()?.display(db).to_string() == "GOAL" {
+ if db.const_data(x).name.as_ref()?.display(db, file_id.edition()).to_string()
+ == "GOAL"
+ {
Some(x)
} else {
None
diff --git a/crates/hir-ty/src/diagnostics/decl_check.rs b/crates/hir-ty/src/diagnostics/decl_check.rs
index b093440060..024fc32f86 100644
--- a/crates/hir-ty/src/diagnostics/decl_check.rs
+++ b/crates/hir-ty/src/diagnostics/decl_check.rs
@@ -17,17 +17,18 @@ use std::fmt;
use hir_def::{
data::adt::VariantData, db::DefDatabase, hir::Pat, src::HasSource, AdtId, AttrDefId, ConstId,
- EnumId, EnumVariantId, FunctionId, ItemContainerId, Lookup, ModuleDefId, ModuleId, StaticId,
- StructId, TraitId, TypeAliasId,
+ EnumId, EnumVariantId, FunctionId, HasModule, ItemContainerId, Lookup, ModuleDefId, ModuleId,
+ StaticId, StructId, TraitId, TypeAliasId,
};
use hir_expand::{
name::{AsName, Name},
- HirFileId, MacroFileIdExt,
+ HirFileId, HirFileIdExt, MacroFileIdExt,
};
use intern::sym;
use stdx::{always, never};
use syntax::{
ast::{self, HasName},
+ utils::is_raw_identifier,
AstNode, AstPtr, ToSmolStr,
};
@@ -318,17 +319,21 @@ impl<'a> DeclValidator<'a> {
/// This includes function parameters except for trait implementation associated functions.
fn validate_func_body(&mut self, func: FunctionId) {
let body = self.db.body(func.into());
+ let edition = self.edition(func);
let mut pats_replacements = body
.pats
.iter()
.filter_map(|(pat_id, pat)| match pat {
Pat::Bind { id, .. } => {
let bind_name = &body.bindings[*id].name;
+ let mut suggested_text =
+ to_lower_snake_case(&bind_name.unescaped().display_no_db().to_smolstr())?;
+ if is_raw_identifier(&suggested_text, edition) {
+ suggested_text.insert_str(0, "r#");
+ }
let replacement = Replacement {
current_name: bind_name.clone(),
- suggested_text: to_lower_snake_case(
- &bind_name.display_no_db().to_smolstr(),
- )?,
+ suggested_text,
expected_case: CaseType::LowerSnakeCase,
};
Some((pat_id, replacement))
@@ -377,6 +382,11 @@ impl<'a> DeclValidator<'a> {
}
}
+ fn edition(&self, id: impl HasModule) -> span::Edition {
+ let krate = id.krate(self.db.upcast());
+ self.db.crate_graph()[krate].edition
+ }
+
fn validate_struct(&mut self, struct_id: StructId) {
// Check the structure name.
let non_camel_case_allowed =
@@ -405,16 +415,17 @@ impl<'a> DeclValidator<'a> {
let VariantData::Record(fields) = data.variant_data.as_ref() else {
return;
};
+ let edition = self.edition(struct_id);
let mut struct_fields_replacements = fields
.iter()
.filter_map(|(_, field)| {
- to_lower_snake_case(&field.name.display_no_db().to_smolstr()).map(|new_name| {
- Replacement {
+ to_lower_snake_case(&field.name.display_no_db(edition).to_smolstr()).map(
+ |new_name| Replacement {
current_name: field.name.clone(),
suggested_text: new_name,
expected_case: CaseType::LowerSnakeCase,
- }
- })
+ },
+ )
})
.peekable();
@@ -498,14 +509,17 @@ impl<'a> DeclValidator<'a> {
self.validate_enum_variant_fields(*variant_id);
}
+ let edition = self.edition(enum_id);
let mut enum_variants_replacements = data
.variants
.iter()
.filter_map(|(_, name)| {
- to_camel_case(&name.display_no_db().to_smolstr()).map(|new_name| Replacement {
- current_name: name.clone(),
- suggested_text: new_name,
- expected_case: CaseType::UpperCamelCase,
+ to_camel_case(&name.display_no_db(edition).to_smolstr()).map(|new_name| {
+ Replacement {
+ current_name: name.clone(),
+ suggested_text: new_name,
+ expected_case: CaseType::UpperCamelCase,
+ }
})
})
.peekable();
@@ -566,16 +580,17 @@ impl<'a> DeclValidator<'a> {
let VariantData::Record(fields) = variant_data.variant_data.as_ref() else {
return;
};
+ let edition = self.edition(variant_id);
let mut variant_field_replacements = fields
.iter()
.filter_map(|(_, field)| {
- to_lower_snake_case(&field.name.display_no_db().to_smolstr()).map(|new_name| {
- Replacement {
+ to_lower_snake_case(&field.name.display_no_db(edition).to_smolstr()).map(
+ |new_name| Replacement {
current_name: field.name.clone(),
suggested_text: new_name,
expected_case: CaseType::LowerSnakeCase,
- }
- })
+ },
+ )
})
.peekable();
@@ -704,18 +719,22 @@ impl<'a> DeclValidator<'a> {
) where
N: AstNode + HasName + fmt::Debug,
S: HasSource<Value = N>,
- L: Lookup<Data = S, Database<'a> = dyn DefDatabase + 'a>,
+ L: Lookup<Data = S, Database<'a> = dyn DefDatabase + 'a> + HasModule + Copy,
{
let to_expected_case_type = match expected_case {
CaseType::LowerSnakeCase => to_lower_snake_case,
CaseType::UpperSnakeCase => to_upper_snake_case,
CaseType::UpperCamelCase => to_camel_case,
};
- let Some(replacement) =
- to_expected_case_type(&name.display(self.db.upcast()).to_smolstr()).map(|new_name| {
- Replacement { current_name: name.clone(), suggested_text: new_name, expected_case }
- })
- else {
+ let edition = self.edition(item_id);
+ let Some(replacement) = to_expected_case_type(
+ &name.display(self.db.upcast(), edition).to_smolstr(),
+ )
+ .map(|new_name| Replacement {
+ current_name: name.clone(),
+ suggested_text: new_name,
+ expected_case,
+ }) else {
return;
};
@@ -748,12 +767,13 @@ impl<'a> DeclValidator<'a> {
return;
};
+ let edition = file_id.original_file(self.db.upcast()).edition();
let diagnostic = IncorrectCase {
file: file_id,
ident_type,
ident: AstPtr::new(&name_ast),
expected_case: replacement.expected_case,
- ident_text: replacement.current_name.display(self.db.upcast()).to_string(),
+ ident_text: replacement.current_name.display(self.db.upcast(), edition).to_string(),
suggested_text: replacement.suggested_text,
};
diff --git a/crates/hir-ty/src/diagnostics/expr.rs b/crates/hir-ty/src/diagnostics/expr.rs
index 6e5a7cce9c..f8b5c7d0ce 100644
--- a/crates/hir-ty/src/diagnostics/expr.rs
+++ b/crates/hir-ty/src/diagnostics/expr.rs
@@ -4,6 +4,7 @@
use std::fmt;
+use base_db::CrateId;
use chalk_solve::rust_ir::AdtKind;
use either::Either;
use hir_def::{
@@ -15,6 +16,7 @@ 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,
@@ -258,7 +260,13 @@ impl ExprValidator {
if !witnesses.is_empty() {
self.diagnostics.push(BodyValidationDiagnostic::MissingMatchArms {
match_expr,
- uncovered_patterns: missing_match_arms(&cx, scrut_ty, witnesses, m_arms.is_empty()),
+ uncovered_patterns: missing_match_arms(
+ &cx,
+ scrut_ty,
+ witnesses,
+ m_arms.is_empty(),
+ self.owner.krate(db.upcast()),
+ ),
});
}
}
@@ -345,7 +353,13 @@ impl ExprValidator {
if !witnesses.is_empty() {
self.diagnostics.push(BodyValidationDiagnostic::NonExhaustiveLet {
pat,
- uncovered_patterns: missing_match_arms(&cx, ty, witnesses, false),
+ uncovered_patterns: missing_match_arms(
+ &cx,
+ ty,
+ witnesses,
+ false,
+ self.owner.krate(db.upcast()),
+ ),
});
}
}
@@ -616,24 +630,26 @@ fn missing_match_arms<'p>(
scrut_ty: &Ty,
witnesses: Vec<WitnessPat<'p>>,
arms_is_empty: bool,
+ krate: CrateId,
) -> String {
- struct DisplayWitness<'a, 'p>(&'a WitnessPat<'p>, &'a MatchCheckCtx<'p>);
+ struct DisplayWitness<'a, 'p>(&'a WitnessPat<'p>, &'a MatchCheckCtx<'p>, Edition);
impl fmt::Display for DisplayWitness<'_, '_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- let DisplayWitness(witness, cx) = *self;
+ let DisplayWitness(witness, cx, edition) = *self;
let pat = cx.hoist_witness_pat(witness);
- write!(f, "{}", pat.display(cx.db))
+ write!(f, "{}", pat.display(cx.db, edition))
}
}
+ 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,
};
if arms_is_empty && !non_empty_enum {
- format!("type `{}` is non-empty", scrut_ty.display(cx.db))
+ format!("type `{}` is non-empty", scrut_ty.display(cx.db, edition))
} else {
- let pat_display = |witness| DisplayWitness(witness, cx);
+ let pat_display = |witness| DisplayWitness(witness, cx, edition);
const LIMIT: usize = 3;
match &*witnesses {
[witness] => format!("`{}` not covered", pat_display(witness)),
diff --git a/crates/hir-ty/src/diagnostics/match_check.rs b/crates/hir-ty/src/diagnostics/match_check.rs
index a0ee7c0748..4bc07bc9ec 100644
--- a/crates/hir-ty/src/diagnostics/match_check.rs
+++ b/crates/hir-ty/src/diagnostics/match_check.rs
@@ -14,6 +14,7 @@ use hir_def::{
body::Body, data::adt::VariantData, hir::PatId, AdtId, EnumVariantId, LocalFieldId, VariantId,
};
use hir_expand::name::Name;
+use span::Edition;
use stdx::{always, never};
use crate::{
@@ -151,7 +152,11 @@ impl<'a> PatCtxt<'a> {
match (bm, ty.kind(Interner)) {
(BindingMode::Ref(_), TyKind::Ref(.., rty)) => ty = rty,
(BindingMode::Ref(_), _) => {
- never!("`ref {}` has wrong type {:?}", name.display(self.db.upcast()), ty);
+ never!(
+ "`ref {}` has wrong type {:?}",
+ name.display(self.db.upcast(), Edition::LATEST),
+ ty
+ );
self.errors.push(PatternError::UnexpectedType);
return Pat { ty: ty.clone(), kind: PatKind::Wild.into() };
}
@@ -297,7 +302,7 @@ impl HirDisplay for Pat {
PatKind::Wild => write!(f, "_"),
PatKind::Never => write!(f, "!"),
PatKind::Binding { name, subpattern } => {
- write!(f, "{}", name.display(f.db.upcast()))?;
+ write!(f, "{}", name.display(f.db.upcast(), f.edition()))?;
if let Some(subpattern) = subpattern {
write!(f, " @ ")?;
subpattern.hir_fmt(f)?;
@@ -317,14 +322,22 @@ impl HirDisplay for Pat {
if let Some(variant) = variant {
match variant {
VariantId::EnumVariantId(v) => {
- write!(f, "{}", f.db.enum_variant_data(v).name.display(f.db.upcast()))?;
- }
- VariantId::StructId(s) => {
- write!(f, "{}", f.db.struct_data(s).name.display(f.db.upcast()))?
- }
- VariantId::UnionId(u) => {
- write!(f, "{}", f.db.union_data(u).name.display(f.db.upcast()))?
+ write!(
+ f,
+ "{}",
+ f.db.enum_variant_data(v).name.display(f.db.upcast(), f.edition())
+ )?;
}
+ VariantId::StructId(s) => write!(
+ f,
+ "{}",
+ f.db.struct_data(s).name.display(f.db.upcast(), f.edition())
+ )?,
+ VariantId::UnionId(u) => write!(
+ f,
+ "{}",
+ f.db.union_data(u).name.display(f.db.upcast(), f.edition())
+ )?,
};
let variant_data = variant.variant_data(f.db.upcast());
@@ -341,7 +354,9 @@ impl HirDisplay for Pat {
write!(
f,
"{}: ",
- rec_fields[p.field].name.display(f.db.upcast())
+ rec_fields[p.field]
+ .name
+ .display(f.db.upcast(), f.edition())
)?;
p.pattern.hir_fmt(f)
})
diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs
index 5a96d396ab..4ef053130a 100644
--- a/crates/hir-ty/src/display.rs
+++ b/crates/hir-ty/src/display.rs
@@ -33,6 +33,7 @@ use rustc_apfloat::{
Float,
};
use smallvec::SmallVec;
+use span::Edition;
use stdx::{never, IsNoneOr};
use triomphe::Arc;
@@ -131,7 +132,11 @@ pub trait HirDisplay {
/// Returns a `Display`able type that is human-readable.
/// Use this for showing types to the user (e.g. diagnostics)
- fn display<'a>(&'a self, db: &'a dyn HirDatabase) -> HirDisplayWrapper<'a, Self>
+ fn display<'a>(
+ &'a self,
+ db: &'a dyn HirDatabase,
+ edition: Edition,
+ ) -> HirDisplayWrapper<'a, Self>
where
Self: Sized,
{
@@ -142,7 +147,7 @@ pub trait HirDisplay {
limited_size: None,
omit_verbose_types: false,
closure_style: ClosureStyle::ImplFn,
- display_target: DisplayTarget::Diagnostics,
+ display_target: DisplayTarget::Diagnostics { edition },
show_container_bounds: false,
}
}
@@ -153,6 +158,7 @@ pub trait HirDisplay {
&'a self,
db: &'a dyn HirDatabase,
max_size: Option<usize>,
+ edition: Edition,
) -> HirDisplayWrapper<'a, Self>
where
Self: Sized,
@@ -164,7 +170,7 @@ pub trait HirDisplay {
limited_size: None,
omit_verbose_types: true,
closure_style: ClosureStyle::ImplFn,
- display_target: DisplayTarget::Diagnostics,
+ display_target: DisplayTarget::Diagnostics { edition },
show_container_bounds: false,
}
}
@@ -175,6 +181,7 @@ pub trait HirDisplay {
&'a self,
db: &'a dyn HirDatabase,
limited_size: Option<usize>,
+ edition: Edition,
) -> HirDisplayWrapper<'a, Self>
where
Self: Sized,
@@ -186,7 +193,7 @@ pub trait HirDisplay {
limited_size,
omit_verbose_types: true,
closure_style: ClosureStyle::ImplFn,
- display_target: DisplayTarget::Diagnostics,
+ display_target: DisplayTarget::Diagnostics { edition },
show_container_bounds: false,
}
}
@@ -242,6 +249,7 @@ pub trait HirDisplay {
&'a self,
db: &'a dyn HirDatabase,
show_container_bounds: bool,
+ edition: Edition,
) -> HirDisplayWrapper<'a, Self>
where
Self: Sized,
@@ -253,13 +261,23 @@ pub trait HirDisplay {
limited_size: None,
omit_verbose_types: false,
closure_style: ClosureStyle::ImplFn,
- display_target: DisplayTarget::Diagnostics,
+ display_target: DisplayTarget::Diagnostics { edition },
show_container_bounds,
}
}
}
impl HirFormatter<'_> {
+ 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,
+ }
+ }
+
pub fn write_joined<T: HirDisplay>(
&mut self,
iter: impl IntoIterator<Item = T>,
@@ -324,7 +342,7 @@ pub enum DisplayTarget {
/// 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,
+ Diagnostics { edition: Edition },
/// 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 },
@@ -460,7 +478,7 @@ impl HirDisplay for ProjectionTy {
">::{}",
f.db.type_alias_data(from_assoc_type_id(self.associated_ty_id))
.name
- .display(f.db.upcast())
+ .display(f.db.upcast(), f.edition())
)?;
let proj_params_count =
self.substitution.len(Interner) - trait_ref.substitution.len(Interner);
@@ -499,7 +517,7 @@ impl HirDisplay for Const {
let id = from_placeholder_idx(f.db, *idx);
let generics = generics(f.db.upcast(), id.parent);
let param_data = &generics[id.local_id];
- write!(f, "{}", param_data.name().unwrap().display(f.db.upcast()))?;
+ write!(f, "{}", param_data.name().unwrap().display(f.db.upcast(), f.edition()))?;
Ok(())
}
ConstValue::Concrete(c) => match &c.interned {
@@ -633,7 +651,7 @@ fn render_const_scalar(
TyKind::Adt(adt, _) if b.len() == 2 * size_of::<usize>() => match adt.0 {
hir_def::AdtId::StructId(s) => {
let data = f.db.struct_data(s);
- write!(f, "&{}", data.name.display(f.db.upcast()))?;
+ write!(f, "&{}", data.name.display(f.db.upcast(), f.edition()))?;
Ok(())
}
_ => f.write_str("<unsized-enum-or-union>"),
@@ -691,7 +709,7 @@ fn render_const_scalar(
match adt.0 {
hir_def::AdtId::StructId(s) => {
let data = f.db.struct_data(s);
- write!(f, "{}", data.name.display(f.db.upcast()))?;
+ write!(f, "{}", data.name.display(f.db.upcast(), f.edition()))?;
let field_types = f.db.field_types(s.into());
render_variant_after_name(
&data.variant_data,
@@ -705,7 +723,7 @@ fn render_const_scalar(
)
}
hir_def::AdtId::UnionId(u) => {
- write!(f, "{}", f.db.union_data(u).name.display(f.db.upcast()))
+ write!(f, "{}", f.db.union_data(u).name.display(f.db.upcast(), f.edition()))
}
hir_def::AdtId::EnumId(e) => {
let Ok(target_data_layout) = f.db.target_data_layout(trait_env.krate) else {
@@ -717,7 +735,7 @@ fn render_const_scalar(
return f.write_str("<failed-to-detect-variant>");
};
let data = f.db.enum_variant_data(var_id);
- write!(f, "{}", data.name.display(f.db.upcast()))?;
+ write!(f, "{}", data.name.display(f.db.upcast(), f.edition()))?;
let field_types = f.db.field_types(var_id.into());
render_variant_after_name(
&data.variant_data,
@@ -802,11 +820,11 @@ fn render_variant_after_name(
if matches!(data, VariantData::Record(_)) {
write!(f, " {{")?;
if let Some((id, data)) = it.next() {
- write!(f, " {}: ", data.name.display(f.db.upcast()))?;
+ write!(f, " {}: ", data.name.display(f.db.upcast(), f.edition()))?;
render_field(f, id)?;
}
for (id, data) in it {
- write!(f, ", {}: ", data.name.display(f.db.upcast()))?;
+ write!(f, ", {}: ", data.name.display(f.db.upcast(), f.edition()))?;
render_field(f, id)?;
}
write!(f, " }}")?;
@@ -1000,15 +1018,23 @@ impl HirDisplay for Ty {
CallableDefId::FunctionId(ff) => {
write!(f, "fn ")?;
f.start_location_link(def.into());
- write!(f, "{}", db.function_data(ff).name.display(f.db.upcast()))?
+ write!(
+ f,
+ "{}",
+ db.function_data(ff).name.display(f.db.upcast(), f.edition())
+ )?
}
CallableDefId::StructId(s) => {
f.start_location_link(def.into());
- write!(f, "{}", db.struct_data(s).name.display(f.db.upcast()))?
+ write!(f, "{}", db.struct_data(s).name.display(f.db.upcast(), f.edition()))?
}
CallableDefId::EnumVariantId(e) => {
f.start_location_link(def.into());
- write!(f, "{}", db.enum_variant_data(e).name.display(f.db.upcast()))?
+ write!(
+ f,
+ "{}",
+ db.enum_variant_data(e).name.display(f.db.upcast(), f.edition())
+ )?
}
};
f.end_location_link();
@@ -1053,13 +1079,13 @@ 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 => {
+ DisplayTarget::Diagnostics { .. } | DisplayTarget::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(),
hir_def::AdtId::EnumId(it) => db.enum_data(it).name.clone(),
};
- write!(f, "{}", name.display(f.db.upcast()))?;
+ write!(f, "{}", name.display(f.db.upcast(), f.edition()))?;
}
DisplayTarget::SourceCode { module_id, allow_opaque: _ } => {
if let Some(path) = find_path::find_path(
@@ -1075,7 +1101,7 @@ impl HirDisplay for Ty {
prefer_absolute: false,
},
) {
- write!(f, "{}", path.display(f.db.upcast()))?;
+ write!(f, "{}", path.display(f.db.upcast(), f.edition()))?;
} else {
return Err(HirDisplayError::DisplaySourceCodeError(
DisplaySourceCodeError::PathNotFound,
@@ -1101,12 +1127,12 @@ impl HirDisplay for Ty {
// 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() {
f.start_location_link(trait_.into());
- write!(f, "{}", trait_data.name.display(f.db.upcast()))?;
+ write!(f, "{}", trait_data.name.display(f.db.upcast(), f.edition()))?;
f.end_location_link();
write!(f, "::")?;
f.start_location_link(type_alias.into());
- write!(f, "{}", type_alias_data.name.display(f.db.upcast()))?;
+ write!(f, "{}", type_alias_data.name.display(f.db.upcast(), f.edition()))?;
f.end_location_link();
// Note that the generic args for the associated type come before those for the
// trait (including the self type).
@@ -1124,7 +1150,7 @@ impl HirDisplay for Ty {
let alias = from_foreign_def_id(*type_alias);
let type_alias = db.type_alias_data(alias);
f.start_location_link(alias.into());
- write!(f, "{}", type_alias.name.display(f.db.upcast()))?;
+ write!(f, "{}", type_alias.name.display(f.db.upcast(), f.edition()))?;
f.end_location_link();
}
TyKind::OpaqueType(opaque_ty_id, parameters) => {
@@ -1256,7 +1282,10 @@ impl HirDisplay for Ty {
write!(
f,
"{}",
- p.name.clone().unwrap_or_else(Name::missing).display(f.db.upcast())
+ p.name
+ .clone()
+ .unwrap_or_else(Name::missing)
+ .display(f.db.upcast(), f.edition())
)?
}
TypeParamProvenance::ArgumentImplTrait => {
@@ -1289,7 +1318,7 @@ impl HirDisplay for Ty {
}
},
TypeOrConstParamData::ConstParamData(p) => {
- write!(f, "{}", p.name.display(f.db.upcast()))?;
+ write!(f, "{}", p.name.display(f.db.upcast(), f.edition()))?;
}
}
}
@@ -1632,7 +1661,7 @@ fn write_bounds_like_dyn_trait(
// existential) here, which is the only thing that's
// possible in actual Rust, and hence don't print it
f.start_location_link(trait_.into());
- write!(f, "{}", f.db.trait_data(trait_).name.display(f.db.upcast()))?;
+ write!(f, "{}", f.db.trait_data(trait_).name.display(f.db.upcast(), f.edition()))?;
f.end_location_link();
if is_fn_trait {
if let [self_, params @ ..] = trait_ref.substitution.as_slice(Interner) {
@@ -1706,7 +1735,7 @@ fn write_bounds_like_dyn_trait(
let assoc_ty_id = from_assoc_type_id(proj.associated_ty_id);
let type_alias = f.db.type_alias_data(assoc_ty_id);
f.start_location_link(assoc_ty_id.into());
- write!(f, "{}", type_alias.name.display(f.db.upcast()))?;
+ write!(f, "{}", type_alias.name.display(f.db.upcast(), f.edition()))?;
f.end_location_link();
let proj_arg_count = generics(f.db.upcast(), assoc_ty_id.into()).len_self();
@@ -1770,7 +1799,7 @@ fn fmt_trait_ref(
}
let trait_ = tr.hir_trait_id();
f.start_location_link(trait_.into());
- write!(f, "{}", f.db.trait_data(trait_).name.display(f.db.upcast()))?;
+ write!(f, "{}", f.db.trait_data(trait_).name.display(f.db.upcast(), f.edition()))?;
f.end_location_link();
let substs = tr.substitution.as_slice(Interner);
hir_fmt_generics(f, &substs[1..], None, substs[0].ty(Interner))
@@ -1796,7 +1825,11 @@ impl HirDisplay for WhereClause {
write!(f, ">::",)?;
let type_alias = from_assoc_type_id(projection_ty.associated_ty_id);
f.start_location_link(type_alias.into());
- write!(f, "{}", f.db.type_alias_data(type_alias).name.display(f.db.upcast()),)?;
+ write!(
+ f,
+ "{}",
+ f.db.type_alias_data(type_alias).name.display(f.db.upcast(), f.edition()),
+ )?;
f.end_location_link();
write!(f, " = ")?;
ty.hir_fmt(f)?;
@@ -1832,7 +1865,7 @@ impl HirDisplay for LifetimeData {
let id = lt_from_placeholder_idx(f.db, *idx);
let generics = generics(f.db.upcast(), id.parent);
let param_data = &generics[id.local_id];
- write!(f, "{}", param_data.name.display(f.db.upcast()))?;
+ write!(f, "{}", param_data.name.display(f.db.upcast(), f.edition()))?;
Ok(())
}
_ if f.display_target.is_source_code() => write!(f, "'_"),
@@ -1913,7 +1946,7 @@ impl HirDisplay for TypeRef {
};
write!(f, "&")?;
if let Some(lifetime) = lifetime {
- write!(f, "{} ", lifetime.name.display(f.db.upcast()))?;
+ write!(f, "{} ", lifetime.name.display(f.db.upcast(), f.edition()))?;
}
write!(f, "{mutability}")?;
inner.hir_fmt(f)?;
@@ -1921,7 +1954,7 @@ impl HirDisplay for TypeRef {
TypeRef::Array(inner, len) => {
write!(f, "[")?;
inner.hir_fmt(f)?;
- write!(f, "; {}]", len.display(f.db.upcast()))?;
+ write!(f, "; {}]", len.display(f.db.upcast(), f.edition()))?;
}
TypeRef::Slice(inner) => {
write!(f, "[")?;
@@ -1942,7 +1975,7 @@ impl HirDisplay for TypeRef {
for index in 0..function_parameters.len() {
let (param_name, param_type) = &function_parameters[index];
if let Some(name) = param_name {
- write!(f, "{}: ", name.display(f.db.upcast()))?;
+ write!(f, "{}: ", name.display(f.db.upcast(), f.edition()))?;
}
param_type.hir_fmt(f)?;
@@ -2000,12 +2033,15 @@ impl HirDisplay for TypeBound {
}
path.hir_fmt(f)
}
- TypeBound::Lifetime(lifetime) => write!(f, "{}", lifetime.name.display(f.db.upcast())),
+ TypeBound::Lifetime(lifetime) => {
+ write!(f, "{}", lifetime.name.display(f.db.upcast(), f.edition()))
+ }
TypeBound::ForLifetime(lifetimes, path) => {
+ let edition = f.edition();
write!(
f,
"for<{}> ",
- lifetimes.iter().map(|it| it.display(f.db.upcast())).format(", ")
+ lifetimes.iter().map(|it| it.display(f.db.upcast(), edition)).format(", ")
)?;
path.hir_fmt(f)
}
@@ -2071,7 +2107,7 @@ impl HirDisplay for Path {
if !matches!(self.kind(), PathKind::Plain) || seg_idx > 0 {
write!(f, "::")?;
}
- write!(f, "{}", segment.name.display(f.db.upcast()))?;
+ write!(f, "{}", segment.name.display(f.db.upcast(), f.edition()))?;
if let Some(generic_args) = segment.args_and_bindings {
// We should be in type context, so format as `Foo<Bar>` instead of `Foo::<Bar>`.
// Do we actually format expressions?
@@ -2116,7 +2152,7 @@ impl HirDisplay for Path {
} else {
write!(f, ", ")?;
}
- write!(f, "{}", binding.name.display(f.db.upcast()))?;
+ write!(f, "{}", binding.name.display(f.db.upcast(), f.edition()))?;
match &binding.type_ref {
Some(ty) => {
write!(f, " = ")?;
@@ -2150,9 +2186,11 @@ impl HirDisplay for hir_def::path::GenericArg {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
match self {
hir_def::path::GenericArg::Type(ty) => ty.hir_fmt(f),
- hir_def::path::GenericArg::Const(c) => write!(f, "{}", c.display(f.db.upcast())),
+ hir_def::path::GenericArg::Const(c) => {
+ write!(f, "{}", c.display(f.db.upcast(), f.edition()))
+ }
hir_def::path::GenericArg::Lifetime(lifetime) => {
- write!(f, "{}", lifetime.name.display(f.db.upcast()))
+ write!(f, "{}", lifetime.name.display(f.db.upcast(), f.edition()))
}
}
}
diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs
index 034ed2d691..03072790d0 100644
--- a/crates/hir-ty/src/infer/closure.rs
+++ b/crates/hir-ty/src/infer/closure.rs
@@ -255,7 +255,9 @@ impl CapturedItem {
pub fn display_place(&self, owner: DefWithBodyId, db: &dyn HirDatabase) -> String {
let body = db.body(owner);
- let mut result = body[self.place.local].name.display(db.upcast()).to_string();
+ let krate = owner.krate(db.upcast());
+ let edition = db.crate_graph()[krate].edition;
+ let mut result = body[self.place.local].name.display(db.upcast(), edition).to_string();
let mut field_need_paren = false;
for proj in &self.place.projections {
match proj {
diff --git a/crates/hir-ty/src/layout/tests.rs b/crates/hir-ty/src/layout/tests.rs
index 8cb428a610..f40d508f75 100644
--- a/crates/hir-ty/src/layout/tests.rs
+++ b/crates/hir-ty/src/layout/tests.rs
@@ -42,19 +42,20 @@ fn eval_goal(ra_fixture: &str, minicore: &str) -> Result<Arc<Layout>, LayoutErro
hir_def::ModuleDefId::AdtId(x) => {
let name = match x {
hir_def::AdtId::StructId(x) => {
- db.struct_data(x).name.display_no_db().to_smolstr()
+ db.struct_data(x).name.display_no_db(file_id.edition()).to_smolstr()
}
hir_def::AdtId::UnionId(x) => {
- db.union_data(x).name.display_no_db().to_smolstr()
+ db.union_data(x).name.display_no_db(file_id.edition()).to_smolstr()
}
hir_def::AdtId::EnumId(x) => {
- db.enum_data(x).name.display_no_db().to_smolstr()
+ db.enum_data(x).name.display_no_db(file_id.edition()).to_smolstr()
}
};
(name == "Goal").then_some(Either::Left(x))
}
hir_def::ModuleDefId::TypeAliasId(x) => {
- let name = db.type_alias_data(x).name.display_no_db().to_smolstr();
+ let name =
+ db.type_alias_data(x).name.display_no_db(file_id.edition()).to_smolstr();
(name == "Goal").then_some(Either::Right(x))
}
_ => None,
@@ -94,7 +95,7 @@ fn eval_expr(ra_fixture: &str, minicore: &str) -> Result<Arc<Layout>, LayoutErro
.declarations()
.find_map(|x| match x {
hir_def::ModuleDefId::FunctionId(x) => {
- let name = db.function_data(x).name.display_no_db().to_smolstr();
+ let name = db.function_data(x).name.display_no_db(file_id.edition()).to_smolstr();
(name == "main").then_some(x)
}
_ => None,
@@ -104,7 +105,7 @@ fn eval_expr(ra_fixture: &str, minicore: &str) -> Result<Arc<Layout>, LayoutErro
let b = hir_body
.bindings
.iter()
- .find(|x| x.1.name.display_no_db().to_smolstr() == "goal")
+ .find(|x| x.1.name.display_no_db(file_id.edition()).to_smolstr() == "goal")
.unwrap()
.0;
let infer = db.infer(function_id.into());
diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs
index 4c9e0a1e11..46611ae0de 100644
--- a/crates/hir-ty/src/lib.rs
+++ b/crates/hir-ty/src/lib.rs
@@ -66,6 +66,7 @@ use intern::{sym, Symbol};
use la_arena::{Arena, Idx};
use mir::{MirEvalError, VTableMap};
use rustc_hash::{FxHashMap, FxHashSet};
+use span::Edition;
use syntax::ast::{make, ConstArg};
use traits::FnTrait;
use triomphe::Arc;
@@ -1025,7 +1026,11 @@ where
collector.placeholders.into_iter().collect()
}
-pub fn known_const_to_ast(konst: &Const, db: &dyn HirDatabase) -> Option<ConstArg> {
+pub fn known_const_to_ast(
+ konst: &Const,
+ db: &dyn HirDatabase,
+ edition: Edition,
+) -> Option<ConstArg> {
if let ConstValue::Concrete(c) = &konst.interned().value {
match c.interned {
ConstScalar::UnevaluatedConst(GeneralConstId::InTypeConstId(cid), _) => {
@@ -1035,5 +1040,5 @@ pub fn known_const_to_ast(konst: &Const, db: &dyn HirDatabase) -> Option<ConstAr
_ => (),
}
}
- Some(make::expr_const_value(konst.display(db).to_string().as_str()))
+ Some(make::expr_const_value(konst.display(db, edition).to_string().as_str()))
}
diff --git a/crates/hir-ty/src/mir.rs b/crates/hir-ty/src/mir.rs
index 06a4236e0a..9c727cb4ed 100644
--- a/crates/hir-ty/src/mir.rs
+++ b/crates/hir-ty/src/mir.rs
@@ -158,7 +158,10 @@ impl<V, T> ProjectionElem<V, T> {
subst.at(Interner, 0).assert_ty_ref(Interner).clone()
}
_ => {
- never!("Overloaded deref on type {} is not a projection", base.display(db));
+ never!(
+ "Overloaded deref on type {} is not a projection",
+ base.display(db, db.crate_graph()[krate].edition)
+ );
TyKind::Error.intern(Interner)
}
},
diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs
index f8083e8985..590cb3952e 100644
--- a/crates/hir-ty/src/mir/eval.rs
+++ b/crates/hir-ty/src/mir/eval.rs
@@ -23,7 +23,7 @@ use rustc_apfloat::{
Float,
};
use rustc_hash::{FxHashMap, FxHashSet};
-use span::FileId;
+use span::{Edition, FileId};
use stdx::never;
use syntax::{SyntaxNodePtr, TextRange};
use triomphe::Arc;
@@ -358,6 +358,7 @@ impl MirEvalError {
f: &mut String,
db: &dyn HirDatabase,
span_formatter: impl Fn(FileId, TextRange) -> String,
+ edition: Edition,
) -> std::result::Result<(), std::fmt::Error> {
writeln!(f, "Mir eval error:")?;
let mut err = self;
@@ -370,7 +371,7 @@ impl MirEvalError {
writeln!(
f,
"In function {} ({:?})",
- function_name.name.display(db.upcast()),
+ function_name.name.display(db.upcast(), edition),
func
)?;
}
@@ -415,7 +416,7 @@ impl MirEvalError {
write!(
f,
"Layout for type `{}` is not available due {err:?}",
- ty.display(db).with_closure_style(ClosureStyle::ClosureWithId)
+ ty.display(db, edition).with_closure_style(ClosureStyle::ClosureWithId)
)?;
}
MirEvalError::MirLowerError(func, err) => {
@@ -423,16 +424,17 @@ impl MirEvalError {
writeln!(
f,
"MIR lowering for function `{}` ({:?}) failed due:",
- function_name.name.display(db.upcast()),
+ function_name.name.display(db.upcast(), edition),
func
)?;
- err.pretty_print(f, db, span_formatter)?;
+ err.pretty_print(f, db, span_formatter, edition)?;
}
MirEvalError::ConstEvalError(name, err) => {
MirLowerError::ConstEvalError((**name).into(), err.clone()).pretty_print(
f,
db,
span_formatter,
+ edition,
)?;
}
MirEvalError::UndefinedBehavior(_)
@@ -2675,10 +2677,11 @@ impl Evaluator<'_> {
let db = self.db.upcast();
let loc = variant.lookup(db);
let enum_loc = loc.parent.lookup(db);
+ let edition = self.db.crate_graph()[self.crate_id].edition;
let name = format!(
"{}::{}",
- enum_loc.id.item_tree(db)[enum_loc.id.value].name.display(db.upcast()),
- loc.id.item_tree(db)[loc.id.value].name.display(db.upcast()),
+ enum_loc.id.item_tree(db)[enum_loc.id.value].name.display(db.upcast(), edition),
+ loc.id.item_tree(db)[loc.id.value].name.display(db.upcast(), edition),
);
Err(MirEvalError::ConstEvalError(name, Box::new(e)))
}
diff --git a/crates/hir-ty/src/mir/eval/shim.rs b/crates/hir-ty/src/mir/eval/shim.rs
index d76f538187..0cdad74a4f 100644
--- a/crates/hir-ty/src/mir/eval/shim.rs
+++ b/crates/hir-ty/src/mir/eval/shim.rs
@@ -856,7 +856,11 @@ impl Evaluator<'_> {
Ok(ty_name) => ty_name,
// Fallback to human readable display in case of `Err`. Ideally we want to use `display_source_code` to
// render full paths.
- Err(_) => ty.display(self.db).to_string(),
+ 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()
+ }
};
let len = ty_name.len();
let addr = self.heap_allocate(len, 1)?;
diff --git a/crates/hir-ty/src/mir/eval/tests.rs b/crates/hir-ty/src/mir/eval/tests.rs
index b21a401fa7..371a5278dc 100644
--- a/crates/hir-ty/src/mir/eval/tests.rs
+++ b/crates/hir-ty/src/mir/eval/tests.rs
@@ -1,5 +1,5 @@
use hir_def::db::DefDatabase;
-use span::EditionedFileId;
+use span::{Edition, EditionedFileId};
use syntax::{TextRange, TextSize};
use test_fixture::WithFixture;
@@ -15,7 +15,7 @@ fn eval_main(db: &TestDB, file_id: EditionedFileId) -> Result<(String, String),
.declarations()
.find_map(|x| match x {
hir_def::ModuleDefId::FunctionId(x) => {
- if db.function_data(x).name.display(db).to_string() == "main" {
+ if db.function_data(x).name.display(db, Edition::CURRENT).to_string() == "main" {
Some(x)
} else {
None
@@ -63,7 +63,7 @@ fn check_pass_and_stdio(ra_fixture: &str, expected_stdout: &str, expected_stderr
let span_formatter = |file, range: TextRange| {
format!("{:?} {:?}..{:?}", file, line_index(range.start()), line_index(range.end()))
};
- e.pretty_print(&mut err, &db, span_formatter).unwrap();
+ e.pretty_print(&mut err, &db, span_formatter, Edition::CURRENT).unwrap();
panic!("Error in interpreting: {err}");
}
Ok((stdout, stderr)) => {
diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs
index 9aa2eeebc1..a15549f9f9 100644
--- a/crates/hir-ty/src/mir/lower.rs
+++ b/crates/hir-ty/src/mir/lower.rs
@@ -21,7 +21,7 @@ use hir_expand::name::Name;
use la_arena::ArenaMap;
use rustc_apfloat::Float;
use rustc_hash::FxHashMap;
-use span::FileId;
+use span::{Edition, FileId};
use syntax::TextRange;
use triomphe::Arc;
@@ -157,13 +157,18 @@ impl MirLowerError {
f: &mut String,
db: &dyn HirDatabase,
span_formatter: impl Fn(FileId, TextRange) -> String,
+ edition: Edition,
) -> 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)?,
- ConstEvalError::MirEvalError(e) => e.pretty_print(f, db, span_formatter)?,
+ ConstEvalError::MirLowerError(e) => {
+ e.pretty_print(f, db, span_formatter, edition)?
+ }
+ ConstEvalError::MirEvalError(e) => {
+ e.pretty_print(f, db, span_formatter, edition)?
+ }
}
}
MirLowerError::MissingFunctionDefinition(owner, it) => {
@@ -171,15 +176,15 @@ impl MirLowerError {
writeln!(
f,
"Missing function definition for {}",
- body.pretty_print_expr(db.upcast(), *owner, *it)
+ body.pretty_print_expr(db.upcast(), *owner, *it, edition)
)?;
}
MirLowerError::TypeMismatch(e) => match e {
Some(e) => writeln!(
f,
"Type mismatch: Expected {}, found {}",
- e.expected.display(db),
- e.actual.display(db),
+ e.expected.display(db, edition),
+ e.actual.display(db, edition),
)?,
None => writeln!(f, "Type mismatch: types mismatch with {{unknown}}",)?,
},
@@ -189,11 +194,11 @@ impl MirLowerError {
writeln!(
f,
"Generic arg not provided for {}",
- param.name().unwrap_or(&Name::missing()).display(db.upcast())
+ param.name().unwrap_or(&Name::missing()).display(db.upcast(), edition)
)?;
writeln!(f, "Provided args: [")?;
for g in subst.iter(Interner) {
- write!(f, " {},", g.display(db))?;
+ write!(f, " {},", g.display(db, edition))?;
}
writeln!(f, "]")?;
}
@@ -242,8 +247,8 @@ impl From<LayoutError> for MirLowerError {
}
impl MirLowerError {
- fn unresolved_path(db: &dyn HirDatabase, p: &Path) -> Self {
- Self::UnresolvedName(p.display(db).to_string())
+ fn unresolved_path(db: &dyn HirDatabase, p: &Path, edition: Edition) -> Self {
+ Self::UnresolvedName(p.display(db, edition).to_string())
}
}
@@ -436,7 +441,8 @@ impl<'ctx> MirLowerCtx<'ctx> {
VariantId::UnionId(_) => implementation_error!("Union variant as path"),
}
} else {
- let unresolved_name = || MirLowerError::unresolved_path(self.db, p);
+ let unresolved_name =
+ || MirLowerError::unresolved_path(self.db, p, self.edition());
let resolver = resolver_for_expr(self.db.upcast(), self.owner, expr_id);
resolver
.resolve_path_in_value_ns_fully(self.db.upcast(), p)
@@ -662,7 +668,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
let (func_id, generic_args) =
self.infer.method_resolution(expr_id).ok_or_else(|| {
MirLowerError::UnresolvedMethod(
- method_name.display(self.db.upcast()).to_string(),
+ method_name.display(self.db.upcast(), self.edition()).to_string(),
)
})?;
let func = Operand::from_fn(self.db, func_id, generic_args);
@@ -803,7 +809,9 @@ impl<'ctx> MirLowerCtx<'ctx> {
};
let variant_id =
self.infer.variant_resolution_for_expr(expr_id).ok_or_else(|| match path {
- Some(p) => MirLowerError::UnresolvedName(p.display(self.db).to_string()),
+ Some(p) => MirLowerError::UnresolvedName(
+ p.display(self.db, self.edition()).to_string(),
+ ),
None => MirLowerError::RecordLiteralWithoutPath,
})?;
let subst = match self.expr_ty_without_adjust(expr_id).kind(Interner) {
@@ -1378,7 +1386,9 @@ impl<'ctx> MirLowerCtx<'ctx> {
"only `char` and numeric types are allowed in range patterns"
),
};
- let unresolved_name = || MirLowerError::unresolved_path(self.db, c.as_ref());
+ let edition = self.edition();
+ let unresolved_name =
+ || MirLowerError::unresolved_path(self.db, c.as_ref(), edition);
let resolver = self.owner.resolver(self.db.upcast());
let pr = resolver
.resolve_path_in_value_ns(self.db.upcast(), c.as_ref())
@@ -1904,19 +1914,25 @@ impl<'ctx> MirLowerCtx<'ctx> {
match r {
Ok(r) => Ok(r),
Err(e) => {
+ let edition = self.edition();
let db = self.db.upcast();
let loc = variant.lookup(db);
let enum_loc = loc.parent.lookup(db);
let name = format!(
"{}::{}",
- enum_loc.id.item_tree(db)[enum_loc.id.value].name.display(db.upcast()),
- loc.id.item_tree(db)[loc.id.value].name.display(db.upcast()),
+ enum_loc.id.item_tree(db)[enum_loc.id.value].name.display(db.upcast(), edition),
+ loc.id.item_tree(db)[loc.id.value].name.display(db.upcast(), edition),
);
Err(MirLowerError::ConstEvalError(name.into(), Box::new(e)))
}
}
}
+ fn edition(&self) -> Edition {
+ let krate = self.owner.krate(self.db.upcast());
+ self.db.crate_graph()[krate].edition
+ }
+
fn drop_until_scope(
&mut self,
scope_index: usize,
@@ -2121,18 +2137,24 @@ pub fn mir_body_for_closure_query(
}
pub fn mir_body_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Result<Arc<MirBody>> {
+ let krate = def.krate(db.upcast());
+ let edition = db.crate_graph()[krate].edition;
let detail = match def {
- DefWithBodyId::FunctionId(it) => db.function_data(it).name.display(db.upcast()).to_string(),
- DefWithBodyId::StaticId(it) => db.static_data(it).name.display(db.upcast()).to_string(),
+ DefWithBodyId::FunctionId(it) => {
+ db.function_data(it).name.display(db.upcast(), edition).to_string()
+ }
+ DefWithBodyId::StaticId(it) => {
+ db.static_data(it).name.display(db.upcast(), edition).to_string()
+ }
DefWithBodyId::ConstId(it) => db
.const_data(it)
.name
.clone()
.unwrap_or_else(Name::missing)
- .display(db.upcast())
+ .display(db.upcast(), edition)
.to_string(),
DefWithBodyId::VariantId(it) => {
- db.enum_variant_data(it).name.display(db.upcast()).to_string()
+ db.enum_variant_data(it).name.display(db.upcast(), edition).to_string()
}
DefWithBodyId::InTypeConstId(it) => format!("in type const {it:?}"),
};
diff --git a/crates/hir-ty/src/mir/lower/pattern_matching.rs b/crates/hir-ty/src/mir/lower/pattern_matching.rs
index 34e0f30afb..b1c0d1f2b3 100644
--- a/crates/hir-ty/src/mir/lower/pattern_matching.rs
+++ b/crates/hir-ty/src/mir/lower/pattern_matching.rs
@@ -347,7 +347,8 @@ impl MirLowerCtx<'_> {
// A const don't bind anything. Only needs check.
return Ok((current, current_else));
}
- let unresolved_name = || MirLowerError::unresolved_path(self.db, p);
+ let unresolved_name =
+ || MirLowerError::unresolved_path(self.db, p, self.edition());
let resolver = self.owner.resolver(self.db.upcast());
let pr = resolver
.resolve_path_in_value_ns(self.db.upcast(), p)
diff --git a/crates/hir-ty/src/mir/pretty.rs b/crates/hir-ty/src/mir/pretty.rs
index 0c641d7c6c..df56071aa9 100644
--- a/crates/hir-ty/src/mir/pretty.rs
+++ b/crates/hir-ty/src/mir/pretty.rs
@@ -9,6 +9,7 @@ use either::Either;
use hir_def::{body::Body, hir::BindingId};
use hir_expand::{name::Name, Lookup};
use la_arena::ArenaMap;
+use span::Edition;
use crate::{
db::HirDatabase,
@@ -44,18 +45,21 @@ impl MirBody {
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()));
+ w!(this, "fn {}() ", data.name.display(db.upcast(), Edition::LATEST));
}
hir_def::DefWithBodyId::StaticId(id) => {
let data = db.static_data(id);
- w!(this, "static {}: _ = ", data.name.display(db.upcast()));
+ w!(this, "static {}: _ = ", data.name.display(db.upcast(), Edition::LATEST));
}
hir_def::DefWithBodyId::ConstId(id) => {
let data = db.const_data(id);
w!(
this,
"const {}: _ = ",
- data.name.as_ref().unwrap_or(&Name::missing()).display(db.upcast())
+ data.name
+ .as_ref()
+ .unwrap_or(&Name::missing())
+ .display(db.upcast(), Edition::LATEST)
);
}
hir_def::DefWithBodyId::VariantId(id) => {
@@ -64,8 +68,12 @@ impl MirBody {
w!(
this,
"enum {}::{} = ",
- enum_loc.id.item_tree(db.upcast())[enum_loc.id.value].name.display(db.upcast()),
- loc.id.item_tree(db.upcast())[loc.id.value].name.display(db.upcast()),
+ enum_loc.id.item_tree(db.upcast())[enum_loc.id.value]
+ .name
+ .display(db.upcast(), Edition::LATEST),
+ loc.id.item_tree(db.upcast())[loc.id.value]
+ .name
+ .display(db.upcast(), Edition::LATEST),
)
}
hir_def::DefWithBodyId::InTypeConstId(id) => {
@@ -122,7 +130,7 @@ impl HirDisplay for LocalName {
match self {
LocalName::Unknown(l) => write!(f, "_{}", u32::from(l.into_raw())),
LocalName::Binding(n, l) => {
- write!(f, "{}_{}", n.display(f.db.upcast()), u32::from(l.into_raw()))
+ write!(f, "{}_{}", n.display(f.db.upcast(), f.edition()), u32::from(l.into_raw()))
}
}
}
@@ -200,7 +208,7 @@ impl<'a> MirPrettyCtx<'a> {
wln!(
self,
"let {}: {};",
- self.local_name(id).display(self.db),
+ self.local_name(id).display_test(self.db),
self.hir_display(&local.ty)
);
}
@@ -231,10 +239,18 @@ impl<'a> MirPrettyCtx<'a> {
wln!(this, ";");
}
StatementKind::StorageDead(p) => {
- wln!(this, "StorageDead({})", this.local_name(*p).display(self.db));
+ wln!(
+ this,
+ "StorageDead({})",
+ this.local_name(*p).display_test(self.db)
+ );
}
StatementKind::StorageLive(p) => {
- wln!(this, "StorageLive({})", this.local_name(*p).display(self.db));
+ wln!(
+ this,
+ "StorageLive({})",
+ this.local_name(*p).display_test(self.db)
+ );
}
StatementKind::Deinit(p) => {
w!(this, "Deinit(");
@@ -297,7 +313,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(this.db));
+ w!(this, "{}", this.local_name(local).display_test(this.db));
return;
};
match last {
@@ -317,13 +333,13 @@ impl<'a> MirPrettyCtx<'a> {
w!(
this,
" as {}).{}",
- variant_name.display(this.db.upcast()),
- name.display(this.db.upcast())
+ variant_name.display(this.db.upcast(), Edition::LATEST),
+ name.display(this.db.upcast(), Edition::LATEST)
);
}
hir_def::VariantId::StructId(_) | hir_def::VariantId::UnionId(_) => {
f(this, local, head);
- w!(this, ".{}", name.display(this.db.upcast()));
+ w!(this, ".{}", name.display(this.db.upcast(), Edition::LATEST));
}
}
}
@@ -337,7 +353,7 @@ impl<'a> MirPrettyCtx<'a> {
}
ProjectionElem::Index(l) => {
f(this, local, head);
- w!(this, "[{}]", this.local_name(*l).display(this.db));
+ w!(this, "[{}]", this.local_name(*l).display_test(this.db));
}
it => {
f(this, local, head);
@@ -387,7 +403,7 @@ impl<'a> MirPrettyCtx<'a> {
Rvalue::Repeat(op, len) => {
w!(self, "[");
self.operand(op);
- w!(self, "; {}]", len.display(self.db));
+ w!(self, "; {}]", len.display_test(self.db));
}
Rvalue::Aggregate(AggregateKind::Adt(_, _), it) => {
w!(self, "Adt(");
@@ -458,6 +474,6 @@ impl<'a> MirPrettyCtx<'a> {
}
fn hir_display<T: HirDisplay>(&self, ty: &'a T) -> impl Display + 'a {
- ty.display(self.db).with_closure_style(ClosureStyle::ClosureWithSubst)
+ ty.display_test(self.db).with_closure_style(ClosureStyle::ClosureWithSubst)
}
}
diff --git a/crates/hir-ty/src/tls.rs b/crates/hir-ty/src/tls.rs
index db5fa32057..6cb59491fa 100644
--- a/crates/hir-ty/src/tls.rs
+++ b/crates/hir-ty/src/tls.rs
@@ -2,6 +2,7 @@
use std::fmt::{self, Display};
use itertools::Itertools;
+use span::Edition;
use crate::{
chalk_db, db::HirDatabase, from_assoc_type_id, from_chalk_trait_id, mapping::from_chalk,
@@ -24,7 +25,7 @@ impl DebugContext<'_> {
AdtId::UnionId(it) => self.0.union_data(it).name.clone(),
AdtId::EnumId(it) => self.0.enum_data(it).name.clone(),
};
- name.display(self.0.upcast()).fmt(f)?;
+ name.display(self.0.upcast(), Edition::LATEST).fmt(f)?;
Ok(())
}
@@ -35,7 +36,7 @@ impl DebugContext<'_> {
) -> Result<(), fmt::Error> {
let trait_: hir_def::TraitId = from_chalk_trait_id(id);
let trait_data = self.0.trait_data(trait_);
- trait_data.name.display(self.0.upcast()).fmt(f)?;
+ trait_data.name.display(self.0.upcast(), Edition::LATEST).fmt(f)?;
Ok(())
}
@@ -54,8 +55,8 @@ impl DebugContext<'_> {
write!(
fmt,
"{}::{}",
- trait_data.name.display(self.0.upcast()),
- type_alias_data.name.display(self.0.upcast())
+ trait_data.name.display(self.0.upcast(), Edition::LATEST),
+ type_alias_data.name.display(self.0.upcast(), Edition::LATEST)
)?;
Ok(())
}
@@ -75,7 +76,7 @@ impl DebugContext<'_> {
let trait_ref = projection_ty.trait_ref(self.0);
let trait_params = trait_ref.substitution.as_slice(Interner);
let self_ty = trait_ref.self_type_parameter(Interner);
- write!(fmt, "<{self_ty:?} as {}", trait_name.display(self.0.upcast()))?;
+ write!(fmt, "<{self_ty:?} as {}", trait_name.display(self.0.upcast(), Edition::LATEST))?;
if trait_params.len() > 1 {
write!(
fmt,
@@ -83,7 +84,7 @@ impl DebugContext<'_> {
trait_params[1..].iter().format_with(", ", |x, f| f(&format_args!("{x:?}"))),
)?;
}
- write!(fmt, ">::{}", type_alias_data.name.display(self.0.upcast()))?;
+ write!(fmt, ">::{}", type_alias_data.name.display(self.0.upcast(), Edition::LATEST))?;
let proj_params_count = projection_ty.substitution.len(Interner) - trait_params.len();
let proj_params = &projection_ty.substitution.as_slice(Interner)[..proj_params_count];
@@ -110,9 +111,11 @@ impl DebugContext<'_> {
CallableDefId::EnumVariantId(e) => self.0.enum_variant_data(e).name.clone(),
};
match def {
- CallableDefId::FunctionId(_) => write!(fmt, "{{fn {}}}", name.display(self.0.upcast())),
+ CallableDefId::FunctionId(_) => {
+ write!(fmt, "{{fn {}}}", name.display(self.0.upcast(), Edition::LATEST))
+ }
CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_) => {
- write!(fmt, "{{ctor {}}}", name.display(self.0.upcast()))
+ write!(fmt, "{{ctor {}}}", name.display(self.0.upcast(), Edition::LATEST))
}
}
}
diff --git a/crates/hir-ty/src/traits.rs b/crates/hir-ty/src/traits.rs
index 00791c5149..51ccd4ef29 100644
--- a/crates/hir-ty/src/traits.rs
+++ b/crates/hir-ty/src/traits.rs
@@ -14,6 +14,7 @@ use hir_def::{
};
use hir_expand::name::Name;
use intern::sym;
+use span::Edition;
use stdx::{never, panic_context};
use triomphe::Arc;
@@ -114,7 +115,7 @@ pub(crate) fn trait_solve_query(
) -> Option<Solution> {
let detail = match &goal.value.goal.data(Interner) {
GoalData::DomainGoal(DomainGoal::Holds(WhereClause::Implemented(it))) => {
- db.trait_data(it.hir_trait_id()).name.display(db.upcast()).to_string()
+ db.trait_data(it.hir_trait_id()).name.display(db.upcast(), Edition::LATEST).to_string()
}
GoalData::DomainGoal(DomainGoal::Holds(WhereClause::AliasEq(_))) => "alias_eq".to_owned(),
_ => "??".to_owned(),
diff --git a/crates/hir/src/attrs.rs b/crates/hir/src/attrs.rs
index 02d92620e0..af60c233e5 100644
--- a/crates/hir/src/attrs.rs
+++ b/crates/hir/src/attrs.rs
@@ -328,11 +328,9 @@ fn doc_modpath_from_str(link: &str) -> Option<ModPath> {
};
let parts = first_segment.into_iter().chain(parts).map(|segment| match segment.parse() {
Ok(idx) => Name::new_tuple_field(idx),
- Err(_) => Name::new(
- segment.split_once('<').map_or(segment, |it| it.0),
- tt::IdentIsRaw::No,
- SyntaxContextId::ROOT,
- ),
+ Err(_) => {
+ Name::new(segment.split_once('<').map_or(segment, |it| it.0), SyntaxContextId::ROOT)
+ }
});
Some(ModPath::from_segments(kind, parts))
};
diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs
index 12dd8b5bf4..923dca6466 100644
--- a/crates/hir/src/display.rs
+++ b/crates/hir/src/display.rs
@@ -84,7 +84,7 @@ impl HirDisplay for Function {
if let Some(abi) = &data.abi {
write!(f, "extern \"{}\" ", abi.as_str())?;
}
- write!(f, "fn {}", data.name.display(f.db.upcast()))?;
+ write!(f, "fn {}", data.name.display(f.db.upcast(), f.edition()))?;
write_generic_params(GenericDefId::FunctionId(self.id), f)?;
@@ -107,7 +107,7 @@ impl HirDisplay for Function {
first = false;
}
match local {
- Some(name) => write!(f, "{}: ", name.display(f.db.upcast()))?,
+ Some(name) => write!(f, "{}: ", name.display(f.db.upcast(), f.edition()))?,
None => f.write_str("_: ")?,
}
type_ref.hir_fmt(f)?;
@@ -177,7 +177,7 @@ fn write_impl_header(impl_: &Impl, f: &mut HirFormatter<'_>) -> Result<(), HirDi
if let Some(trait_) = impl_.trait_(db) {
let trait_data = db.trait_data(trait_.id);
- write!(f, " {} for", trait_data.name.display(db.upcast()))?;
+ write!(f, " {} for", trait_data.name.display(db.upcast(), f.edition()))?;
}
f.write_char(' ')?;
@@ -196,7 +196,7 @@ impl HirDisplay for SelfParam {
{
f.write_char('&')?;
if let Some(lifetime) = lifetime {
- write!(f, "{} ", lifetime.name.display(f.db.upcast()))?;
+ write!(f, "{} ", lifetime.name.display(f.db.upcast(), f.edition()))?;
}
if let hir_def::type_ref::Mutability::Mut = mut_ {
f.write_str("mut ")?;
@@ -227,7 +227,7 @@ impl HirDisplay for Struct {
// FIXME: Render repr if its set explicitly?
write_visibility(module_id, self.visibility(f.db), f)?;
f.write_str("struct ")?;
- write!(f, "{}", self.name(f.db).display(f.db.upcast()))?;
+ write!(f, "{}", self.name(f.db).display(f.db.upcast(), f.edition()))?;
let def_id = GenericDefId::AdtId(AdtId::StructId(self.id));
write_generic_params(def_id, f)?;
@@ -266,7 +266,7 @@ impl HirDisplay for Enum {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
f.write_str("enum ")?;
- write!(f, "{}", self.name(f.db).display(f.db.upcast()))?;
+ write!(f, "{}", self.name(f.db).display(f.db.upcast(), f.edition()))?;
let def_id = GenericDefId::AdtId(AdtId::EnumId(self.id));
write_generic_params(def_id, f)?;
@@ -283,7 +283,7 @@ impl HirDisplay for Union {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
f.write_str("union ")?;
- write!(f, "{}", self.name(f.db).display(f.db.upcast()))?;
+ write!(f, "{}", self.name(f.db).display(f.db.upcast(), f.edition()))?;
let def_id = GenericDefId::AdtId(AdtId::UnionId(self.id));
write_generic_params(def_id, f)?;
@@ -343,7 +343,7 @@ fn write_variants(
} else {
f.write_str("{\n")?;
for variant in &variants[..count] {
- write!(f, " {}", variant.name(f.db).display(f.db.upcast()))?;
+ write!(f, " {}", variant.name(f.db).display(f.db.upcast(), f.edition()))?;
match variant.kind(f.db) {
StructKind::Tuple => {
let fields_str =
@@ -372,21 +372,21 @@ fn write_variants(
impl HirDisplay for Field {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
write_visibility(self.parent.module(f.db).id, self.visibility(f.db), f)?;
- write!(f, "{}: ", self.name(f.db).display(f.db.upcast()))?;
+ write!(f, "{}: ", self.name(f.db).display(f.db.upcast(), f.edition()))?;
self.ty(f.db).hir_fmt(f)
}
}
impl HirDisplay for TupleField {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
- write!(f, "pub {}: ", self.name().display(f.db.upcast()))?;
+ write!(f, "pub {}: ", self.name().display(f.db.upcast(), f.edition()))?;
self.ty(f.db).hir_fmt(f)
}
}
impl HirDisplay for Variant {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
- write!(f, "{}", self.name(f.db).display(f.db.upcast()))?;
+ write!(f, "{}", self.name(f.db).display(f.db.upcast(), f.edition()))?;
let data = self.variant_data(f.db);
match &*data {
VariantData::Unit => {}
@@ -424,9 +424,9 @@ impl HirDisplay for ExternCrateDecl {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
f.write_str("extern crate ")?;
- write!(f, "{}", self.name(f.db).display(f.db.upcast()))?;
+ write!(f, "{}", self.name(f.db).display(f.db.upcast(), f.edition()))?;
if let Some(alias) = self.alias(f.db) {
- write!(f, " as {alias}",)?;
+ write!(f, " as {}", alias.display(f.edition()))?;
}
Ok(())
}
@@ -478,7 +478,7 @@ impl HirDisplay for TypeParam {
match param_data {
TypeOrConstParamData::TypeParamData(p) => match p.provenance {
TypeParamProvenance::TypeParamList | TypeParamProvenance::TraitSelf => {
- write!(f, "{}", p.name.clone().unwrap().display(f.db.upcast()))?
+ write!(f, "{}", p.name.clone().unwrap().display(f.db.upcast(), f.edition()))?
}
TypeParamProvenance::ArgumentImplTrait => {
return write_bounds_like_dyn_trait_with_prefix(
@@ -491,7 +491,7 @@ impl HirDisplay for TypeParam {
}
},
TypeOrConstParamData::ConstParamData(p) => {
- write!(f, "{}", p.name.display(f.db.upcast()))?;
+ write!(f, "{}", p.name.display(f.db.upcast(), f.edition()))?;
}
}
@@ -525,13 +525,13 @@ impl HirDisplay for TypeParam {
impl HirDisplay for LifetimeParam {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
- write!(f, "{}", self.name(f.db).display(f.db.upcast()))
+ write!(f, "{}", self.name(f.db).display(f.db.upcast(), f.edition()))
}
}
impl HirDisplay for ConstParam {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
- write!(f, "const {}: ", self.name(f.db).display(f.db.upcast()))?;
+ write!(f, "const {}: ", self.name(f.db).display(f.db.upcast(), f.edition()))?;
self.ty(f.db).hir_fmt(f)
}
}
@@ -563,7 +563,7 @@ fn write_generic_params(
};
for (_, lifetime) in params.iter_lt() {
delim(f)?;
- write!(f, "{}", lifetime.name.display(f.db.upcast()))?;
+ write!(f, "{}", lifetime.name.display(f.db.upcast(), f.edition()))?;
}
for (_, ty) in params.iter_type_or_consts() {
if let Some(name) = &ty.name() {
@@ -573,7 +573,7 @@ fn write_generic_params(
continue;
}
delim(f)?;
- write!(f, "{}", name.display(f.db.upcast()))?;
+ write!(f, "{}", name.display(f.db.upcast(), f.edition()))?;
if let Some(default) = &ty.default {
f.write_str(" = ")?;
default.hir_fmt(f)?;
@@ -581,12 +581,12 @@ fn write_generic_params(
}
TypeOrConstParamData::ConstParamData(c) => {
delim(f)?;
- write!(f, "const {}: ", name.display(f.db.upcast()))?;
+ write!(f, "const {}: ", name.display(f.db.upcast(), f.edition()))?;
c.ty.hir_fmt(f)?;
if let Some(default) = &c.default {
f.write_str(" = ")?;
- write!(f, "{}", default.display(f.db.upcast()))?;
+ write!(f, "{}", default.display(f.db.upcast(), f.edition()))?;
}
}
}
@@ -639,7 +639,7 @@ fn write_where_predicates(
let write_target = |target: &WherePredicateTypeTarget, f: &mut HirFormatter<'_>| match target {
WherePredicateTypeTarget::TypeRef(ty) => ty.hir_fmt(f),
WherePredicateTypeTarget::TypeOrConstParam(id) => match params[*id].name() {
- Some(name) => write!(f, "{}", name.display(f.db.upcast())),
+ Some(name) => write!(f, "{}", name.display(f.db.upcast(), f.edition())),
None => f.write_str("{unnamed}"),
},
};
@@ -668,12 +668,13 @@ fn write_where_predicates(
bound.hir_fmt(f)?;
}
Lifetime { target, bound } => {
- let target = target.name.display(f.db.upcast());
- let bound = bound.name.display(f.db.upcast());
+ let target = target.name.display(f.db.upcast(), f.edition());
+ let bound = bound.name.display(f.db.upcast(), f.edition());
write!(f, "{target}: {bound}")?;
}
ForLifetime { lifetimes, target, bound } => {
- let lifetimes = lifetimes.iter().map(|it| it.display(f.db.upcast())).join(", ");
+ let lifetimes =
+ lifetimes.iter().map(|it| it.display(f.db.upcast(), f.edition())).join(", ");
write!(f, "for<{lifetimes}> ")?;
write_target(target, f)?;
f.write_str(": ")?;
@@ -685,7 +686,9 @@ fn write_where_predicates(
f.write_str(" + ")?;
match nxt {
TypeBound { bound, .. } | ForLifetime { bound, .. } => bound.hir_fmt(f)?,
- Lifetime { bound, .. } => write!(f, "{}", bound.name.display(f.db.upcast()))?,
+ Lifetime { bound, .. } => {
+ write!(f, "{}", bound.name.display(f.db.upcast(), f.edition()))?
+ }
}
}
f.write_str(",")?;
@@ -707,7 +710,7 @@ impl HirDisplay for Const {
let data = db.const_data(self.id);
f.write_str("const ")?;
match &data.name {
- Some(name) => write!(f, "{}: ", name.display(f.db.upcast()))?,
+ Some(name) => write!(f, "{}: ", name.display(f.db.upcast(), f.edition()))?,
None => f.write_str("_: ")?,
}
data.type_ref.hir_fmt(f)?;
@@ -723,7 +726,7 @@ impl HirDisplay for Static {
if data.mutable {
f.write_str("mut ")?;
}
- write!(f, "{}: ", data.name.display(f.db.upcast()))?;
+ write!(f, "{}: ", data.name.display(f.db.upcast(), f.edition()))?;
data.type_ref.hir_fmt(f)?;
Ok(())
}
@@ -777,7 +780,7 @@ fn write_trait_header(trait_: &Trait, f: &mut HirFormatter<'_>) -> Result<(), Hi
if data.is_auto {
f.write_str("auto ")?;
}
- write!(f, "trait {}", data.name.display(f.db.upcast()))?;
+ write!(f, "trait {}", data.name.display(f.db.upcast(), f.edition()))?;
write_generic_params(GenericDefId::TraitId(trait_.id), f)?;
Ok(())
}
@@ -786,7 +789,7 @@ impl HirDisplay for TraitAlias {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
let data = f.db.trait_alias_data(self.id);
- write!(f, "trait {}", data.name.display(f.db.upcast()))?;
+ write!(f, "trait {}", data.name.display(f.db.upcast(), f.edition()))?;
let def_id = GenericDefId::TraitAliasId(self.id);
write_generic_params(def_id, f)?;
f.write_str(" = ")?;
@@ -802,7 +805,7 @@ impl HirDisplay for TypeAlias {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
let data = f.db.type_alias_data(self.id);
- write!(f, "type {}", data.name.display(f.db.upcast()))?;
+ write!(f, "type {}", data.name.display(f.db.upcast(), f.edition()))?;
let def_id = GenericDefId::TypeAliasId(self.id);
write_generic_params(def_id, f)?;
if !data.bounds.is_empty() {
@@ -822,7 +825,7 @@ impl HirDisplay for Module {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
// FIXME: Module doesn't have visibility saved in data.
match self.name(f.db) {
- Some(name) => write!(f, "mod {}", name.display(f.db.upcast())),
+ Some(name) => write!(f, "mod {}", name.display(f.db.upcast(), f.edition())),
None if self.is_crate_root() => match self.krate(f.db).display_name(f.db) {
Some(name) => write!(f, "extern crate {name}"),
None => f.write_str("extern crate {unknown}"),
@@ -839,6 +842,6 @@ impl HirDisplay for Macro {
hir_def::MacroId::MacroRulesId(_) => f.write_str("macro_rules!"),
hir_def::MacroId::ProcMacroId(_) => f.write_str("proc_macro"),
}?;
- write!(f, " {}", self.name(f.db).display(f.db.upcast()))
+ write!(f, " {}", self.name(f.db).display(f.db.upcast(), f.edition()))
}
}
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 1a3becdf50..57f810c7c7 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -340,13 +340,13 @@ impl ModuleDef {
}
}
- pub fn canonical_path(&self, db: &dyn HirDatabase) -> Option<String> {
+ pub fn canonical_path(&self, db: &dyn HirDatabase, edition: Edition) -> Option<String> {
let mut segments = vec![self.name(db)?];
for m in self.module(db)?.path_to_root(db) {
segments.extend(m.name(db))
}
segments.reverse();
- Some(segments.iter().map(|it| it.display(db.upcast())).join("::"))
+ Some(segments.iter().map(|it| it.display(db.upcast(), edition)).join("::"))
}
pub fn canonical_module_path(
@@ -556,13 +556,14 @@ impl Module {
style_lints: bool,
) {
let _p = tracing::info_span!("Module::diagnostics", name = ?self.name(db)).entered();
+ let edition = db.crate_graph()[self.id.krate()].edition;
let def_map = self.id.def_map(db.upcast());
for diag in def_map.diagnostics() {
if diag.in_module != self.id.local_id {
// FIXME: This is accidentally quadratic.
continue;
}
- emit_def_diagnostic(db, acc, diag);
+ emit_def_diagnostic(db, acc, diag, edition);
}
if !self.id.is_block_module() {
@@ -582,7 +583,7 @@ impl Module {
}
ModuleDef::Trait(t) => {
for diag in db.trait_data_with_diagnostics(t.id).1.iter() {
- emit_def_diagnostic(db, acc, diag);
+ emit_def_diagnostic(db, acc, diag, edition);
}
for item in t.items(db) {
@@ -599,19 +600,19 @@ impl Module {
match adt {
Adt::Struct(s) => {
for diag in db.struct_data_with_diagnostics(s.id).1.iter() {
- emit_def_diagnostic(db, acc, diag);
+ emit_def_diagnostic(db, acc, diag, edition);
}
}
Adt::Union(u) => {
for diag in db.union_data_with_diagnostics(u.id).1.iter() {
- emit_def_diagnostic(db, acc, diag);
+ emit_def_diagnostic(db, acc, diag, edition);
}
}
Adt::Enum(e) => {
for v in e.variants(db) {
acc.extend(ModuleDef::Variant(v).diagnostics(db, style_lints));
for diag in db.enum_variant_data_with_diagnostics(v.id).1.iter() {
- emit_def_diagnostic(db, acc, diag);
+ emit_def_diagnostic(db, acc, diag, edition);
}
}
}
@@ -645,7 +646,7 @@ impl Module {
let ast_id_map = db.ast_id_map(file_id);
for diag in db.impl_data_with_diagnostics(impl_def.id).1.iter() {
- emit_def_diagnostic(db, acc, diag);
+ emit_def_diagnostic(db, acc, diag, edition);
}
if inherent_impls.invalid_impls().contains(&impl_def.id) {
@@ -869,23 +870,32 @@ fn emit_macro_def_diagnostics(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>
never!("declarative expander for non decl-macro: {:?}", e);
return;
};
+ let krate = HasModule::krate(&m.id, db.upcast());
+ let edition = db.crate_graph()[krate].edition;
emit_def_diagnostic_(
db,
acc,
&DefDiagnosticKind::MacroDefError { ast, message: e.to_string() },
+ edition,
);
}
}
}
-fn emit_def_diagnostic(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>, diag: &DefDiagnostic) {
- emit_def_diagnostic_(db, acc, &diag.kind)
+fn emit_def_diagnostic(
+ db: &dyn HirDatabase,
+ acc: &mut Vec<AnyDiagnostic>,
+ diag: &DefDiagnostic,
+ edition: Edition,
+) {
+ emit_def_diagnostic_(db, acc, &diag.kind, edition)
}
fn emit_def_diagnostic_(
db: &dyn HirDatabase,
acc: &mut Vec<AnyDiagnostic>,
diag: &DefDiagnosticKind,
+ edition: Edition,
) {
match diag {
DefDiagnosticKind::UnresolvedModule { ast: declaration, candidates } => {
@@ -910,7 +920,7 @@ fn emit_def_diagnostic_(
MacroError {
node: InFile::new(ast.file_id, item.syntax_node_ptr()),
precise_location: None,
- message: format!("{}: {message}", path.display(db.upcast())),
+ message: format!("{}: {message}", path.display(db.upcast(), edition)),
error,
}
.into(),
@@ -1764,7 +1774,7 @@ impl DefWithBody {
/// A textual representation of the HIR of this def's body for debugging purposes.
pub fn debug_hir(self, db: &dyn HirDatabase) -> String {
let body = db.body(self.id());
- body.pretty_print(db.upcast(), self.id())
+ body.pretty_print(db.upcast(), self.id(), Edition::CURRENT)
}
/// A textual representation of the MIR of this def's body for debugging purposes.
@@ -2259,6 +2269,8 @@ impl Function {
db: &dyn HirDatabase,
span_formatter: impl Fn(FileId, TextRange) -> String,
) -> String {
+ let krate = HasModule::krate(&self.id, db.upcast());
+ let edition = db.crate_graph()[krate].edition;
let body = match db.monomorphized_mir_body(
self.id.into(),
Substitution::empty(Interner),
@@ -2267,7 +2279,7 @@ impl Function {
Ok(body) => body,
Err(e) => {
let mut r = String::new();
- _ = e.pretty_print(&mut r, db, &span_formatter);
+ _ = e.pretty_print(&mut r, db, &span_formatter, edition);
return r;
}
};
@@ -2276,7 +2288,7 @@ impl Function {
Ok(_) => "pass".to_owned(),
Err(e) => {
let mut r = String::new();
- _ = e.pretty_print(&mut r, db, &span_formatter);
+ _ = e.pretty_print(&mut r, db, &span_formatter, edition);
r
}
};
@@ -2510,7 +2522,11 @@ impl Const {
Type::from_value_def(db, self.id)
}
- pub fn render_eval(self, db: &dyn HirDatabase) -> Result<String, ConstEvalError> {
+ pub fn render_eval(
+ self,
+ db: &dyn HirDatabase,
+ edition: Edition,
+ ) -> Result<String, ConstEvalError> {
let c = db.const_eval(self.id.into(), Substitution::empty(Interner), None)?;
let data = &c.data(Interner);
if let TyKind::Scalar(s) = data.ty.kind(Interner) {
@@ -2532,7 +2548,7 @@ impl Const {
if let Ok(s) = mir::render_const_using_debug_impl(db, self.id, &c) {
Ok(s)
} else {
- Ok(format!("{}", c.display(db)))
+ Ok(format!("{}", c.display(db, edition)))
}
}
}
@@ -3728,9 +3744,9 @@ impl ConstParam {
Type::new(db, self.id.parent(), db.const_param_ty(self.id))
}
- pub fn default(self, db: &dyn HirDatabase) -> Option<ast::ConstArg> {
+ pub fn default(self, db: &dyn HirDatabase, edition: Edition) -> Option<ast::ConstArg> {
let arg = generic_arg_from_param(db, self.id.into())?;
- known_const_to_ast(arg.constant(Interner)?, db)
+ known_const_to_ast(arg.constant(Interner)?, db, edition)
}
}
@@ -4038,12 +4054,20 @@ impl Closure {
TyKind::Closure(self.id, self.subst).intern(Interner)
}
- pub fn display_with_id(&self, db: &dyn HirDatabase) -> String {
- self.clone().as_ty().display(db).with_closure_style(ClosureStyle::ClosureWithId).to_string()
+ pub fn display_with_id(&self, db: &dyn HirDatabase, edition: Edition) -> String {
+ self.clone()
+ .as_ty()
+ .display(db, edition)
+ .with_closure_style(ClosureStyle::ClosureWithId)
+ .to_string()
}
- pub fn display_with_impl(&self, db: &dyn HirDatabase) -> String {
- self.clone().as_ty().display(db).with_closure_style(ClosureStyle::ImplFn).to_string()
+ pub fn display_with_impl(&self, db: &dyn HirDatabase, edition: Edition) -> String {
+ self.clone()
+ .as_ty()
+ .display(db, edition)
+ .with_closure_style(ClosureStyle::ImplFn)
+ .to_string()
}
pub fn captured_items(&self, db: &dyn HirDatabase) -> Vec<ClosureCapture> {
@@ -4704,18 +4728,20 @@ impl Type {
pub fn type_and_const_arguments<'a>(
&'a self,
db: &'a dyn HirDatabase,
+ edition: Edition,
) -> impl Iterator<Item = SmolStr> + 'a {
self.ty
.strip_references()
.as_adt()
.into_iter()
.flat_map(|(_, substs)| substs.iter(Interner))
- .filter_map(|arg| {
+ .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)))
+ Some(format_smolstr!("{}", ty.display(db, edition)))
} else {
- arg.constant(Interner).map(|const_| format_smolstr!("{}", const_.display(db)))
+ arg.constant(Interner)
+ .map(|const_| format_smolstr!("{}", const_.display(db, edition)))
}
})
}
@@ -4724,13 +4750,17 @@ impl Type {
pub fn generic_parameters<'a>(
&'a self,
db: &'a dyn HirDatabase,
+ edition: Edition,
) -> impl Iterator<Item = SmolStr> + 'a {
// iterate the lifetime
self.as_adt()
- .and_then(|a| a.lifetime(db).map(|lt| lt.name.display_no_db().to_smolstr()))
+ .and_then(|a| {
+ // Lifetimes do not need edition-specific handling as they cannot be escaped.
+ a.lifetime(db).map(|lt| lt.name.display_no_db(Edition::Edition2015).to_smolstr())
+ })
.into_iter()
// add the type and const parameters
- .chain(self.type_and_const_arguments(db))
+ .chain(self.type_and_const_arguments(db, edition))
}
pub fn iterate_method_candidates_with_traits<T>(
diff --git a/crates/hir/src/symbols.rs b/crates/hir/src/symbols.rs
index b1f5df681f..cabb7e3db3 100644
--- a/crates/hir/src/symbols.rs
+++ b/crates/hir/src/symbols.rs
@@ -9,6 +9,7 @@ use hir_def::{
};
use hir_expand::HirFileId;
use hir_ty::{db::HirDatabase, display::HirDisplay};
+use span::Edition;
use syntax::{ast::HasName, AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, ToSmolStr};
use crate::{Module, ModuleDef, Semantics};
@@ -54,6 +55,7 @@ pub struct SymbolCollector<'a> {
symbols: Vec<FileSymbol>,
work: Vec<SymbolCollectorWork>,
current_container_name: Option<SmolStr>,
+ edition: Edition,
}
/// Given a [`ModuleId`] and a [`HirDatabase`], use the DefMap for the module's crate to collect
@@ -65,10 +67,13 @@ impl<'a> SymbolCollector<'a> {
symbols: Default::default(),
work: Default::default(),
current_container_name: None,
+ edition: Edition::Edition2015,
}
}
pub fn collect(&mut self, module: Module) {
+ self.edition = module.krate().edition(self.db);
+
// The initial work is the root module we're collecting, additional work will
// be populated as we traverse the module's definitions.
self.work.push(SymbolCollectorWork { module_id: module.into(), parent: None });
@@ -209,7 +214,8 @@ impl<'a> SymbolCollector<'a> {
fn collect_from_impl(&mut self, impl_id: ImplId) {
let impl_data = self.db.impl_data(impl_id);
- let impl_name = Some(SmolStr::new(impl_data.self_ty.display(self.db).to_string()));
+ let impl_name =
+ Some(SmolStr::new(impl_data.self_ty.display(self.db, self.edition).to_string()));
self.with_container_name(impl_name, |s| {
for &assoc_item_id in impl_data.items.iter() {
s.push_assoc_item(assoc_item_id)
@@ -239,16 +245,16 @@ impl<'a> SymbolCollector<'a> {
fn def_with_body_id_name(&self, body_id: DefWithBodyId) -> Option<SmolStr> {
match body_id {
DefWithBodyId::FunctionId(id) => {
- Some(self.db.function_data(id).name.display_no_db().to_smolstr())
+ Some(self.db.function_data(id).name.display_no_db(self.edition).to_smolstr())
}
DefWithBodyId::StaticId(id) => {
- Some(self.db.static_data(id).name.display_no_db().to_smolstr())
+ Some(self.db.static_data(id).name.display_no_db(self.edition).to_smolstr())
}
DefWithBodyId::ConstId(id) => {
- Some(self.db.const_data(id).name.as_ref()?.display_no_db().to_smolstr())
+ Some(self.db.const_data(id).name.as_ref()?.display_no_db(self.edition).to_smolstr())
}
DefWithBodyId::VariantId(id) => {
- Some(self.db.enum_variant_data(id).name.display_no_db().to_smolstr())
+ Some(self.db.enum_variant_data(id).name.display_no_db(self.edition).to_smolstr())
}
DefWithBodyId::InTypeConstId(_) => Some("in type const".into()),
}
diff --git a/crates/hir/src/term_search/expr.rs b/crates/hir/src/term_search/expr.rs
index 0c8f6932c7..6ad074e8e5 100644
--- a/crates/hir/src/term_search/expr.rs
+++ b/crates/hir/src/term_search/expr.rs
@@ -7,6 +7,7 @@ use hir_ty::{
display::{DisplaySourceCodeError, HirDisplay},
};
use itertools::Itertools;
+use span::Edition;
use crate::{
Adt, AsAssocItem, AssocItemContainer, Const, ConstParam, Field, Function, Local, ModuleDef,
@@ -29,9 +30,10 @@ fn mod_item_path_str(
sema_scope: &SemanticsScope<'_>,
def: &ModuleDef,
cfg: ImportPathConfig,
+ edition: Edition,
) -> Result<String, DisplaySourceCodeError> {
let path = mod_item_path(sema_scope, def, cfg);
- path.map(|it| it.display(sema_scope.db.upcast()).to_string())
+ path.map(|it| it.display(sema_scope.db.upcast(), edition).to_string())
.ok_or(DisplaySourceCodeError::PathNotFound)
}
@@ -97,37 +99,38 @@ impl Expr {
sema_scope: &SemanticsScope<'_>,
many_formatter: &mut dyn FnMut(&Type) -> String,
cfg: ImportPathConfig,
+ edition: Edition,
) -> Result<String, DisplaySourceCodeError> {
let db = sema_scope.db;
- let mod_item_path_str = |s, def| mod_item_path_str(s, def, cfg);
+ 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)?;
+ let container_name = container_name(container, sema_scope, cfg, edition)?;
let const_name = it
.name(db)
- .map(|c| c.display(db.upcast()).to_string())
+ .map(|c| c.display(db.upcast(), edition).to_string())
.unwrap_or(String::new());
Ok(format!("{container_name}::{const_name}"))
}
None => mod_item_path_str(sema_scope, &ModuleDef::Const(*it)),
},
Expr::Static(it) => mod_item_path_str(sema_scope, &ModuleDef::Static(*it)),
- Expr::Local(it) => Ok(it.name(db).display(db.upcast()).to_string()),
- Expr::ConstParam(it) => Ok(it.name(db).display(db.upcast()).to_string()),
+ Expr::Local(it) => Ok(it.name(db).display(db.upcast(), edition).to_string()),
+ Expr::ConstParam(it) => Ok(it.name(db).display(db.upcast(), edition).to_string()),
Expr::FamousType { value, .. } => Ok(value.to_string()),
Expr::Function { func, params, .. } => {
let args = params
.iter()
- .map(|f| f.gen_source_code(sema_scope, many_formatter, cfg))
+ .map(|f| f.gen_source_code(sema_scope, many_formatter, cfg, edition))
.collect::<Result<Vec<String>, 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)?;
- let fn_name = func.name(db).display(db.upcast()).to_string();
+ let container_name = container_name(container, sema_scope, cfg, edition)?;
+ let fn_name = func.name(db).display(db.upcast(), edition).to_string();
Ok(format!("{container_name}::{fn_name}({args})"))
}
None => {
@@ -141,12 +144,13 @@ impl Expr {
return Ok(many_formatter(&target.ty(db)));
}
- let func_name = func.name(db).display(db.upcast()).to_string();
+ 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)?;
+ let target_str =
+ target.gen_source_code(sema_scope, many_formatter, cfg, edition)?;
let args = params
.iter()
- .map(|f| f.gen_source_code(sema_scope, many_formatter, cfg))
+ .map(|f| f.gen_source_code(sema_scope, many_formatter, cfg, edition))
.collect::<Result<Vec<String>, DisplaySourceCodeError>>()?
.into_iter()
.join(", ");
@@ -176,7 +180,7 @@ impl Expr {
StructKind::Tuple => {
let args = params
.iter()
- .map(|f| f.gen_source_code(sema_scope, many_formatter, cfg))
+ .map(|f| f.gen_source_code(sema_scope, many_formatter, cfg, edition))
.collect::<Result<Vec<String>, DisplaySourceCodeError>>()?
.into_iter()
.join(", ");
@@ -190,8 +194,8 @@ impl Expr {
.map(|(a, f)| {
let tmp = format!(
"{}: {}",
- f.name(db).display(db.upcast()),
- a.gen_source_code(sema_scope, many_formatter, cfg)?
+ f.name(db).display(db.upcast(), edition),
+ a.gen_source_code(sema_scope, many_formatter, cfg, edition)?
);
Ok(tmp)
})
@@ -211,7 +215,7 @@ impl Expr {
StructKind::Tuple => {
let args = params
.iter()
- .map(|a| a.gen_source_code(sema_scope, many_formatter, cfg))
+ .map(|a| a.gen_source_code(sema_scope, many_formatter, cfg, edition))
.collect::<Result<Vec<String>, DisplaySourceCodeError>>()?
.into_iter()
.join(", ");
@@ -225,8 +229,8 @@ impl Expr {
.map(|(a, f)| {
let tmp = format!(
"{}: {}",
- f.name(db).display(db.upcast()),
- a.gen_source_code(sema_scope, many_formatter, cfg)?
+ f.name(db).display(db.upcast(), edition),
+ a.gen_source_code(sema_scope, many_formatter, cfg, edition)?
);
Ok(tmp)
})
@@ -244,7 +248,7 @@ impl Expr {
Expr::Tuple { params, .. } => {
let args = params
.iter()
- .map(|a| a.gen_source_code(sema_scope, many_formatter, cfg))
+ .map(|a| a.gen_source_code(sema_scope, many_formatter, cfg, edition))
.collect::<Result<Vec<String>, DisplaySourceCodeError>>()?
.into_iter()
.join(", ");
@@ -256,8 +260,8 @@ impl Expr {
return Ok(many_formatter(&expr.ty(db)));
}
- let strukt = expr.gen_source_code(sema_scope, many_formatter, cfg)?;
- let field = field.name(db).display(db.upcast()).to_string();
+ let strukt = expr.gen_source_code(sema_scope, many_formatter, cfg, edition)?;
+ let field = field.name(db).display(db.upcast(), edition).to_string();
Ok(format!("{strukt}.{field}"))
}
Expr::Reference(expr) => {
@@ -265,7 +269,7 @@ impl Expr {
return Ok(many_formatter(&expr.ty(db)));
}
- let inner = expr.gen_source_code(sema_scope, many_formatter, cfg)?;
+ let inner = expr.gen_source_code(sema_scope, many_formatter, cfg, edition)?;
Ok(format!("&{inner}"))
}
Expr::Many(ty) => Ok(many_formatter(ty)),
@@ -353,17 +357,18 @@ fn container_name(
container: AssocItemContainer,
sema_scope: &SemanticsScope<'_>,
cfg: ImportPathConfig,
+ edition: Edition,
) -> Result<String, DisplaySourceCodeError> {
let container_name = match container {
crate::AssocItemContainer::Trait(trait_) => {
- mod_item_path_str(sema_scope, &ModuleDef::Trait(trait_), cfg)?
+ mod_item_path_str(sema_scope, &ModuleDef::Trait(trait_), cfg, edition)?
}
crate::AssocItemContainer::Impl(imp) => {
let self_ty = imp.self_ty(sema_scope.db);
// 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()).to_string(),
- None => self_ty.display(sema_scope.db).to_string(),
+ Some(path) => path.display(sema_scope.db.upcast(), edition).to_string(),
+ None => self_ty.display(sema_scope.db, edition).to_string(),
}
}
};
diff --git a/crates/ide-assists/src/handlers/add_missing_impl_members.rs b/crates/ide-assists/src/handlers/add_missing_impl_members.rs
index 4cd15f1c75..7f8ea44fb1 100644
--- a/crates/ide-assists/src/handlers/add_missing_impl_members.rs
+++ b/crates/ide-assists/src/handlers/add_missing_impl_members.rs
@@ -1,5 +1,8 @@
use hir::HasSource;
-use syntax::ast::{self, make, AstNode};
+use syntax::{
+ ast::{self, make, AstNode},
+ Edition,
+};
use crate::{
assist_context::{AssistContext, Assists},
@@ -150,14 +153,22 @@ fn add_missing_impl_members_inner(
&missing_items,
trait_,
&new_impl_def,
- target_scope,
+ &target_scope,
);
if let Some(cap) = ctx.config.snippet_cap {
let mut placeholder = None;
if let DefaultMethods::No = mode {
if let ast::AssocItem::Fn(func) = &first_new_item {
- if try_gen_trait_body(ctx, func, trait_ref, &impl_def).is_none() {
+ if try_gen_trait_body(
+ ctx,
+ func,
+ trait_ref,
+ &impl_def,
+ target_scope.krate().edition(ctx.sema.db),
+ )
+ .is_none()
+ {
if let Some(m) = func.syntax().descendants().find_map(ast::MacroCall::cast)
{
if m.syntax().text() == "todo!()" {
@@ -182,9 +193,11 @@ fn try_gen_trait_body(
func: &ast::Fn,
trait_ref: hir::TraitRef,
impl_def: &ast::Impl,
+ edition: Edition,
) -> Option<()> {
- let trait_path =
- make::ext::ident_path(&trait_ref.trait_().name(ctx.db()).display(ctx.db()).to_string());
+ let trait_path = make::ext::ident_path(
+ &trait_ref.trait_().name(ctx.db()).display(ctx.db(), edition).to_string(),
+ );
let hir_ty = ctx.sema.resolve_type(&impl_def.self_ty()?)?;
let adt = hir_ty.as_adt()?.source(ctx.db())?;
gen_trait_fn_body(func, &trait_path, &adt.value, Some(trait_ref))
diff --git a/crates/ide-assists/src/handlers/add_missing_match_arms.rs b/crates/ide-assists/src/handlers/add_missing_match_arms.rs
index f4569ca848..b6abb06a2a 100644
--- a/crates/ide-assists/src/handlers/add_missing_match_arms.rs
+++ b/crates/ide-assists/src/handlers/add_missing_match_arms.rs
@@ -445,7 +445,8 @@ fn build_pat(
) -> Option<ast::Pat> {
match var {
ExtendedVariant::Variant(var) => {
- let path = mod_path_to_ast(&module.find_path(db, ModuleDef::from(var), cfg)?);
+ let edition = module.krate().edition(db);
+ let path = mod_path_to_ast(&module.find_path(db, ModuleDef::from(var), cfg)?, edition);
// FIXME: use HIR for this; it doesn't currently expose struct vs. tuple vs. unit variants though
Some(match var.source(db)?.value.kind() {
ast::StructKind::Tuple(field_list) => {
diff --git a/crates/ide-assists/src/handlers/auto_import.rs b/crates/ide-assists/src/handlers/auto_import.rs
index db53e49d84..d86948818b 100644
--- a/crates/ide-assists/src/handlers/auto_import.rs
+++ b/crates/ide-assists/src/handlers/auto_import.rs
@@ -8,7 +8,7 @@ use ide_db::{
insert_use::{insert_use, insert_use_as_alias, ImportScope},
},
};
-use syntax::{ast, AstNode, NodeOrToken, SyntaxElement};
+use syntax::{ast, AstNode, Edition, NodeOrToken, SyntaxElement};
use crate::{AssistContext, AssistId, AssistKind, Assists, GroupLabel};
@@ -120,13 +120,14 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<
// prioritize more relevant imports
proposed_imports
.sort_by_key(|import| Reverse(relevance_score(ctx, import, current_module.as_ref())));
+ let edition = current_module.map(|it| it.krate().edition(ctx.db())).unwrap_or(Edition::CURRENT);
let group_label = group_label(import_assets.import_candidate());
for import in proposed_imports {
let import_path = import.import_path;
let (assist_id, import_name) =
- (AssistId("auto_import", AssistKind::QuickFix), import_path.display(ctx.db()));
+ (AssistId("auto_import", AssistKind::QuickFix), import_path.display(ctx.db(), edition));
acc.add_group(
&group_label,
assist_id,
@@ -138,7 +139,7 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<
ImportScope::Module(it) => ImportScope::Module(builder.make_mut(it)),
ImportScope::Block(it) => ImportScope::Block(builder.make_mut(it)),
};
- insert_use(&scope, mod_path_to_ast(&import_path), &ctx.config.insert_use);
+ insert_use(&scope, mod_path_to_ast(&import_path, edition), &ctx.config.insert_use);
},
);
@@ -165,7 +166,7 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<
};
insert_use_as_alias(
&scope,
- mod_path_to_ast(&import_path),
+ mod_path_to_ast(&import_path, edition),
&ctx.config.insert_use,
);
},
diff --git a/crates/ide-assists/src/handlers/bool_to_enum.rs b/crates/ide-assists/src/handlers/bool_to_enum.rs
index 3a0754d60f..cd5fe0f862 100644
--- a/crates/ide-assists/src/handlers/bool_to_enum.rs
+++ b/crates/ide-assists/src/handlers/bool_to_enum.rs
@@ -339,6 +339,7 @@ fn augment_references_with_imports(
let cfg = ctx.config.import_path_config();
+ let edition = target_module.krate().edition(ctx.db());
references
.into_iter()
.filter_map(|FileReference { range, name, .. }| {
@@ -361,7 +362,10 @@ fn augment_references_with_imports(
cfg,
)
.map(|mod_path| {
- make::path_concat(mod_path_to_ast(&mod_path), make::path_from_text("Bool"))
+ make::path_concat(
+ mod_path_to_ast(&mod_path, edition),
+ make::path_from_text("Bool"),
+ )
});
import_scope.zip(path)
diff --git a/crates/ide-assists/src/handlers/convert_bool_then.rs b/crates/ide-assists/src/handlers/convert_bool_then.rs
index 77f9c66b35..a5c5b08d5b 100644
--- a/crates/ide-assists/src/handlers/convert_bool_then.rs
+++ b/crates/ide-assists/src/handlers/convert_bool_then.rs
@@ -159,7 +159,7 @@ pub(crate) fn convert_bool_then_to_if(acc: &mut Assists, ctx: &AssistContext<'_>
};
// Verify this is `bool::then` that is being called.
let func = ctx.sema.resolve_method_call(&mcall)?;
- if func.name(ctx.sema.db).display(ctx.db()).to_string() != "then" {
+ if !func.name(ctx.sema.db).eq_ident("then") {
return None;
}
let assoc = func.as_assoc_item(ctx.sema.db)?;
diff --git a/crates/ide-assists/src/handlers/convert_into_to_from.rs b/crates/ide-assists/src/handlers/convert_into_to_from.rs
index 5aa94590e6..8c59ef4314 100644
--- a/crates/ide-assists/src/handlers/convert_into_to_from.rs
+++ b/crates/ide-assists/src/handlers/convert_into_to_from.rs
@@ -51,7 +51,10 @@ pub(crate) fn convert_into_to_from(acc: &mut Assists, ctx: &AssistContext<'_>) -
Some(hir::PathResolution::Def(module_def)) => module_def,
_ => return None,
};
- mod_path_to_ast(&module.find_path(ctx.db(), src_type_def, cfg)?)
+ mod_path_to_ast(
+ &module.find_path(ctx.db(), src_type_def, cfg)?,
+ module.krate().edition(ctx.db()),
+ )
};
let dest_type = match &ast_trait {
diff --git a/crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs b/crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs
index e86ff0dbeb..3c9a917410 100644
--- a/crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs
+++ b/crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs
@@ -114,12 +114,16 @@ pub(crate) fn convert_for_loop_with_for_each(
|builder| {
let mut buf = String::new();
- if let Some((expr_behind_ref, method)) =
+ if let Some((expr_behind_ref, method, krate)) =
is_ref_and_impls_iter_method(&ctx.sema, &iterable)
{
// We have either "for x in &col" and col implements a method called iter
// or "for x in &mut col" and col implements a method called iter_mut
- format_to!(buf, "{expr_behind_ref}.{}()", method.display(ctx.db()));
+ format_to!(
+ buf,
+ "{expr_behind_ref}.{}()",
+ method.display(ctx.db(), krate.edition(ctx.db()))
+ );
} else if let ast::Expr::RangeExpr(..) = iterable {
// range expressions need to be parenthesized for the syntax to be correct
format_to!(buf, "({iterable})");
@@ -144,7 +148,7 @@ pub(crate) fn convert_for_loop_with_for_each(
fn is_ref_and_impls_iter_method(
sema: &hir::Semantics<'_, ide_db::RootDatabase>,
iterable: &ast::Expr,
-) -> Option<(ast::Expr, hir::Name)> {
+) -> Option<(ast::Expr, hir::Name, hir::Crate)> {
let ref_expr = match iterable {
ast::Expr::RefExpr(r) => r,
_ => return None,
@@ -172,7 +176,7 @@ fn is_ref_and_impls_iter_method(
return None;
}
- Some((expr_behind_ref, wanted_method))
+ Some((expr_behind_ref, wanted_method, krate))
}
/// Whether iterable implements core::Iterator
diff --git a/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs b/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs
index 0f0b4442d8..91af9b05bb 100644
--- a/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs
+++ b/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs
@@ -211,7 +211,7 @@ fn augment_references_with_imports(
)
.map(|mod_path| {
make::path_concat(
- mod_path_to_ast(&mod_path),
+ mod_path_to_ast(&mod_path, target_module.krate().edition(ctx.db())),
make::path_from_text(struct_name),
)
});
diff --git a/crates/ide-assists/src/handlers/destructure_struct_binding.rs b/crates/ide-assists/src/handlers/destructure_struct_binding.rs
index 095b8f958d..b229b750e8 100644
--- a/crates/ide-assists/src/handlers/destructure_struct_binding.rs
+++ b/crates/ide-assists/src/handlers/destructure_struct_binding.rs
@@ -7,7 +7,7 @@ use ide_db::{
FxHashMap, FxHashSet,
};
use itertools::Itertools;
-use syntax::{ast, ted, AstNode, SmolStr, SyntaxNode, ToSmolStr};
+use syntax::{ast, ted, AstNode, Edition, SmolStr, SyntaxNode, ToSmolStr};
use text_edit::TextRange;
use crate::{
@@ -81,6 +81,7 @@ struct StructEditData {
has_private_members: bool,
is_nested: bool,
is_ref: bool,
+ edition: Edition,
}
fn collect_data(ident_pat: ast::IdentPat, ctx: &AssistContext<'_>) -> Option<StructEditData> {
@@ -145,6 +146,7 @@ fn collect_data(ident_pat: ast::IdentPat, ctx: &AssistContext<'_>) -> Option<Str
names_in_scope,
is_nested,
is_ref,
+ edition: module.krate().edition(ctx.db()),
})
}
@@ -180,7 +182,7 @@ fn build_assignment_edit(
) -> AssignmentEdit {
let ident_pat = builder.make_mut(data.ident_pat.clone());
- let struct_path = mod_path_to_ast(&data.struct_def_path);
+ let struct_path = mod_path_to_ast(&data.struct_def_path, data.edition);
let is_ref = ident_pat.ref_token().is_some();
let is_mut = ident_pat.mut_token().is_some();
@@ -247,7 +249,7 @@ fn generate_field_names(ctx: &AssistContext<'_>, data: &StructEditData) -> Vec<(
.visible_fields
.iter()
.map(|field| {
- let field_name = field.name(ctx.db()).display_no_db().to_smolstr();
+ let field_name = field.name(ctx.db()).display_no_db(data.edition).to_smolstr();
let new_name = new_field_name(field_name.clone(), &data.names_in_scope);
(field_name, new_name)
})
diff --git a/crates/ide-assists/src/handlers/expand_glob_import.rs b/crates/ide-assists/src/handlers/expand_glob_import.rs
index 9beb616d99..3d6d37ad93 100644
--- a/crates/ide-assists/src/handlers/expand_glob_import.rs
+++ b/crates/ide-assists/src/handlers/expand_glob_import.rs
@@ -66,7 +66,9 @@ pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext<'_>) ->
let names_to_import = find_names_to_import(ctx, refs_in_target, imported_defs);
let expanded = make::use_tree_list(names_to_import.iter().map(|n| {
- let path = make::ext::ident_path(&n.display(ctx.db()).to_string());
+ let path = make::ext::ident_path(
+ &n.display(ctx.db(), current_module.krate().edition(ctx.db())).to_string(),
+ );
make::use_tree(path, None, None, false)
}))
.clone_for_update();
diff --git a/crates/ide-assists/src/handlers/extract_function.rs b/crates/ide-assists/src/handlers/extract_function.rs
index 0a2cb6d5ef..cfcb09b9f7 100644
--- a/crates/ide-assists/src/handlers/extract_function.rs
+++ b/crates/ide-assists/src/handlers/extract_function.rs
@@ -23,7 +23,7 @@ use syntax::{
self, edit::IndentLevel, edit_in_place::Indent, AstNode, AstToken, HasGenericParams,
HasName,
},
- match_ast, ted, SyntaxElement,
+ match_ast, ted, Edition, SyntaxElement,
SyntaxKind::{self, COMMENT},
SyntaxNode, SyntaxToken, TextRange, TextSize, TokenAtOffset, WalkEvent, T,
};
@@ -84,7 +84,6 @@ pub(crate) fn extract_function(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
};
let body = extraction_target(&node, range)?;
- let (container_info, contains_tail_expr) = body.analyze_container(&ctx.sema)?;
let (locals_used, self_param) = body.analyze(&ctx.sema);
@@ -92,6 +91,9 @@ pub(crate) fn extract_function(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
let insert_after = node_to_insert_after(&body, anchor)?;
let semantics_scope = ctx.sema.scope(&insert_after)?;
let module = semantics_scope.module();
+ let edition = semantics_scope.krate().edition(ctx.db());
+
+ let (container_info, contains_tail_expr) = body.analyze_container(&ctx.sema, edition)?;
let ret_ty = body.return_ty(ctx)?;
let control_flow = body.external_control_flow(ctx, &container_info)?;
@@ -217,7 +219,11 @@ pub(crate) fn extract_function(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
);
if let Some(mod_path) = mod_path {
- insert_use(&scope, mod_path_to_ast(&mod_path), &ctx.config.insert_use);
+ insert_use(
+ &scope,
+ mod_path_to_ast(&mod_path, edition),
+ &ctx.config.insert_use,
+ );
}
}
}
@@ -238,7 +244,13 @@ pub(crate) fn extract_function(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
fn make_function_name(semantics_scope: &hir::SemanticsScope<'_>) -> ast::NameRef {
let mut names_in_scope = vec![];
semantics_scope.process_all_names(&mut |name, _| {
- names_in_scope.push(name.display(semantics_scope.db.upcast()).to_string())
+ names_in_scope.push(
+ name.display(
+ semantics_scope.db.upcast(),
+ semantics_scope.krate().edition(semantics_scope.db),
+ )
+ .to_string(),
+ )
});
let default_name = "fun_name";
@@ -366,6 +378,7 @@ struct ContainerInfo {
ret_type: Option<hir::Type>,
generic_param_lists: Vec<ast::GenericParamList>,
where_clauses: Vec<ast::WhereClause>,
+ edition: Edition,
}
/// Control flow that is exported from extracted function
@@ -489,8 +502,8 @@ impl Param {
}
}
- fn to_arg(&self, ctx: &AssistContext<'_>) -> ast::Expr {
- let var = path_expr_from_local(ctx, self.var);
+ fn to_arg(&self, ctx: &AssistContext<'_>, edition: Edition) -> ast::Expr {
+ let var = path_expr_from_local(ctx, self.var, edition);
match self.kind() {
ParamKind::Value | ParamKind::MutValue => var,
ParamKind::SharedRef => make::expr_ref(var, false),
@@ -498,8 +511,13 @@ impl Param {
}
}
- fn to_param(&self, ctx: &AssistContext<'_>, module: hir::Module) -> ast::Param {
- let var = self.var.name(ctx.db()).display(ctx.db()).to_string();
+ fn to_param(
+ &self,
+ ctx: &AssistContext<'_>,
+ module: hir::Module,
+ edition: Edition,
+ ) -> ast::Param {
+ let var = self.var.name(ctx.db()).display(ctx.db(), edition).to_string();
let var_name = make::name(&var);
let pat = match self.kind() {
ParamKind::MutValue => make::ident_pat(false, true, var_name),
@@ -520,7 +538,7 @@ impl Param {
}
impl TryKind {
- fn of_ty(ty: hir::Type, ctx: &AssistContext<'_>) -> Option<TryKind> {
+ fn of_ty(ty: hir::Type, ctx: &AssistContext<'_>, edition: Edition) -> Option<TryKind> {
if ty.is_unknown() {
// We favour Result for `expr?`
return Some(TryKind::Result { ty });
@@ -529,7 +547,7 @@ impl TryKind {
let name = adt.name(ctx.db());
// FIXME: use lang items to determine if it is std type or user defined
// E.g. if user happens to define type named `Option`, we would have false positive
- let name = &name.display(ctx.db()).to_string();
+ let name = &name.display(ctx.db(), edition).to_string();
match name.as_str() {
"Option" => Some(TryKind::Option),
"Result" => Some(TryKind::Result { ty }),
@@ -828,6 +846,7 @@ impl FunctionBody {
fn analyze_container(
&self,
sema: &Semantics<'_, RootDatabase>,
+ edition: Edition,
) -> Option<(ContainerInfo, bool)> {
let mut ancestors = self.parent()?.ancestors();
let infer_expr_opt = |expr| sema.type_of_expr(&expr?).map(TypeInfo::adjusted);
@@ -927,6 +946,7 @@ impl FunctionBody {
ret_type: ty,
generic_param_lists,
where_clauses,
+ edition,
},
contains_tail_expr,
))
@@ -1015,7 +1035,7 @@ impl FunctionBody {
let kind = match (try_expr, ret_expr, break_expr, continue_expr) {
(Some(_), _, None, None) => {
let ret_ty = container_info.ret_type.clone()?;
- let kind = TryKind::of_ty(ret_ty, ctx)?;
+ let kind = TryKind::of_ty(ret_ty, ctx, container_info.edition)?;
Some(FlowKind::Try { kind })
}
@@ -1397,7 +1417,7 @@ fn fixup_call_site(builder: &mut SourceChangeBuilder, body: &FunctionBody) {
fn make_call(ctx: &AssistContext<'_>, fun: &Function, indent: IndentLevel) -> SyntaxNode {
let ret_ty = fun.return_type(ctx);
- let args = make::arg_list(fun.params.iter().map(|param| param.to_arg(ctx)));
+ let args = make::arg_list(fun.params.iter().map(|param| param.to_arg(ctx, fun.mods.edition)));
let name = fun.name.clone();
let mut call_expr = if fun.self_param.is_some() {
let self_arg = make::expr_path(make::ext::ident_path("self"));
@@ -1420,13 +1440,13 @@ fn make_call(ctx: &AssistContext<'_>, fun: &Function, indent: IndentLevel) -> Sy
[] => None,
[var] => {
let name = var.local.name(ctx.db());
- let name = make::name(&name.display(ctx.db()).to_string());
+ let name = make::name(&name.display(ctx.db(), fun.mods.edition).to_string());
Some(ast::Pat::IdentPat(make::ident_pat(false, var.mut_usage_outside_body, name)))
}
vars => {
let binding_pats = vars.iter().map(|var| {
let name = var.local.name(ctx.db());
- let name = make::name(&name.display(ctx.db()).to_string());
+ let name = make::name(&name.display(ctx.db(), fun.mods.edition).to_string());
make::ident_pat(false, var.mut_usage_outside_body, name).into()
});
Some(ast::Pat::TuplePat(make::tuple_pat(binding_pats)))
@@ -1569,8 +1589,8 @@ impl FlowHandler {
}
}
-fn path_expr_from_local(ctx: &AssistContext<'_>, var: Local) -> ast::Expr {
- let name = var.name(ctx.db()).display(ctx.db()).to_string();
+fn path_expr_from_local(ctx: &AssistContext<'_>, var: Local, edition: Edition) -> ast::Expr {
+ let name = var.name(ctx.db()).display(ctx.db(), edition).to_string();
make::expr_path(make::ext::ident_path(&name))
}
@@ -1581,7 +1601,7 @@ fn format_function(
old_indent: IndentLevel,
) -> ast::Fn {
let fun_name = make::name(&fun.name.text());
- let params = fun.make_param_list(ctx, module);
+ let params = fun.make_param_list(ctx, module, fun.mods.edition);
let ret_ty = fun.make_ret_ty(ctx, module);
let body = make_body(ctx, old_indent, fun);
let (generic_params, where_clause) = make_generic_params_and_where_clause(ctx, fun);
@@ -1707,9 +1727,14 @@ impl Function {
type_params_in_descendant_paths.chain(type_params_in_params).collect()
}
- fn make_param_list(&self, ctx: &AssistContext<'_>, module: hir::Module) -> ast::ParamList {
+ fn make_param_list(
+ &self,
+ ctx: &AssistContext<'_>,
+ module: hir::Module,
+ edition: Edition,
+ ) -> ast::ParamList {
let self_param = self.self_param.clone();
- let params = self.params.iter().map(|param| param.to_param(ctx, module));
+ let params = self.params.iter().map(|param| param.to_param(ctx, module, edition));
make::param_list(self_param, params)
}
@@ -1842,10 +1867,12 @@ fn make_body(ctx: &AssistContext<'_>, old_indent: IndentLevel, fun: &Function) -
None => match fun.outliving_locals.as_slice() {
[] => {}
[var] => {
- tail_expr = Some(path_expr_from_local(ctx, var.local));
+ tail_expr = Some(path_expr_from_local(ctx, var.local, fun.mods.edition));
}
vars => {
- let exprs = vars.iter().map(|var| path_expr_from_local(ctx, var.local));
+ let exprs = vars
+ .iter()
+ .map(|var| path_expr_from_local(ctx, var.local, fun.mods.edition));
let expr = make::expr_tuple(exprs);
tail_expr = Some(expr);
}
diff --git a/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs b/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs
index a62fdeb617..615b5d3f98 100644
--- a/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs
+++ b/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs
@@ -1,7 +1,7 @@
use std::iter;
use either::Either;
-use hir::{Module, ModuleDef, Name, Variant};
+use hir::{HasCrate, Module, ModuleDef, Name, Variant};
use ide_db::{
defs::Definition,
helpers::mod_path_to_ast,
@@ -16,7 +16,7 @@ use syntax::{
self, edit::IndentLevel, edit_in_place::Indent, make, AstNode, HasAttrs, HasGenericParams,
HasName, HasVisibility,
},
- match_ast, ted, SyntaxElement,
+ match_ast, ted, Edition, SyntaxElement,
SyntaxKind::*,
SyntaxNode, T,
};
@@ -58,6 +58,7 @@ pub(crate) fn extract_struct_from_enum_variant(
"Extract struct from enum variant",
target,
|builder| {
+ let edition = enum_hir.krate(ctx.db()).edition(ctx.db());
let variant_hir_name = variant_hir.name(ctx.db());
let enum_module_def = ModuleDef::from(enum_hir);
let usages = Definition::Variant(variant_hir).usages(&ctx.sema).all();
@@ -82,7 +83,7 @@ pub(crate) fn extract_struct_from_enum_variant(
references,
);
processed.into_iter().for_each(|(path, node, import)| {
- apply_references(ctx.config.insert_use, path, node, import)
+ apply_references(ctx.config.insert_use, path, node, import, edition)
});
}
builder.edit_file(ctx.file_id());
@@ -98,7 +99,7 @@ pub(crate) fn extract_struct_from_enum_variant(
references,
);
processed.into_iter().for_each(|(path, node, import)| {
- apply_references(ctx.config.insert_use, path, node, import)
+ apply_references(ctx.config.insert_use, path, node, import, edition)
});
}
@@ -169,7 +170,7 @@ fn existing_definition(db: &RootDatabase, variant_name: &ast::Name, variant: &Va
),
_ => false,
})
- .any(|(name, _)| name.display(db).to_string() == variant_name.to_string())
+ .any(|(name, _)| name.eq_ident(variant_name.text().as_str()))
}
fn extract_generic_params(
@@ -359,9 +360,10 @@ fn apply_references(
segment: ast::PathSegment,
node: SyntaxNode,
import: Option<(ImportScope, hir::ModPath)>,
+ edition: Edition,
) {
if let Some((scope, path)) = import {
- insert_use(&scope, mod_path_to_ast(&path), &insert_use_cfg);
+ insert_use(&scope, mod_path_to_ast(&path, edition), &insert_use_cfg);
}
// deep clone to prevent cycle
let path = make::path_from_segments(iter::once(segment.clone_subtree()), false);
diff --git a/crates/ide-assists/src/handlers/fill_record_pattern_fields.rs b/crates/ide-assists/src/handlers/fill_record_pattern_fields.rs
index 758f50d3f4..ee32186480 100644
--- a/crates/ide-assists/src/handlers/fill_record_pattern_fields.rs
+++ b/crates/ide-assists/src/handlers/fill_record_pattern_fields.rs
@@ -45,8 +45,9 @@ pub(crate) fn fill_record_pattern_fields(acc: &mut Assists, ctx: &AssistContext<
let new_field_list =
make::record_pat_field_list(old_field_list.fields(), None).clone_for_update();
for (f, _) in missing_fields.iter() {
+ let edition = ctx.sema.scope(record_pat.syntax())?.krate().edition(ctx.db());
let field = make::record_pat_field_shorthand(make::name_ref(
- &f.name(ctx.sema.db).display_no_db().to_smolstr(),
+ &f.name(ctx.sema.db).display_no_db(edition).to_smolstr(),
));
new_field_list.add_field(field.clone_for_update());
}
diff --git a/crates/ide-assists/src/handlers/fix_visibility.rs b/crates/ide-assists/src/handlers/fix_visibility.rs
index 9950f9c147..7a92d8911b 100644
--- a/crates/ide-assists/src/handlers/fix_visibility.rs
+++ b/crates/ide-assists/src/handlers/fix_visibility.rs
@@ -4,7 +4,7 @@ use hir::{
use ide_db::FileId;
use syntax::{
ast::{self, edit_in_place::HasVisibilityEdit, make, HasVisibility as _},
- AstNode, TextRange, ToSmolStr,
+ AstNode, TextRange,
};
use crate::{AssistContext, AssistId, AssistKind, Assists};
@@ -48,7 +48,7 @@ fn add_vis_to_referenced_module_def(acc: &mut Assists, ctx: &AssistContext<'_>)
let (_, def) = module
.scope(ctx.db(), None)
.into_iter()
- .find(|(name, _)| name.display_no_db().to_smolstr() == name_ref.text().as_str())?;
+ .find(|(name, _)| name.eq_ident(name_ref.text().as_str()))?;
let ScopeDef::ModuleDef(def) = def else {
return None;
};
@@ -71,7 +71,10 @@ fn add_vis_to_referenced_module_def(acc: &mut Assists, ctx: &AssistContext<'_>)
let assist_label = match target_name {
None => format!("Change visibility to {missing_visibility}"),
Some(name) => {
- format!("Change visibility of {} to {missing_visibility}", name.display(ctx.db()))
+ format!(
+ "Change visibility of {} to {missing_visibility}",
+ name.display(ctx.db(), current_module.krate().edition(ctx.db()))
+ )
}
};
@@ -92,6 +95,7 @@ fn add_vis_to_referenced_record_field(acc: &mut Assists, ctx: &AssistContext<'_>
let (record_field_def, _, _) = ctx.sema.resolve_record_field(&record_field)?;
let current_module = ctx.sema.scope(record_field.syntax())?.module();
+ let current_edition = current_module.krate().edition(ctx.db());
let visibility = record_field_def.visibility(ctx.db());
if visibility.is_visible_from(ctx.db(), current_module.into()) {
return None;
@@ -123,8 +127,8 @@ fn add_vis_to_referenced_record_field(acc: &mut Assists, ctx: &AssistContext<'_>
let target_name = record_field_def.name(ctx.db());
let assist_label = format!(
"Change visibility of {}.{} to {missing_visibility}",
- parent_name.display(ctx.db()),
- target_name.display(ctx.db())
+ parent_name.display(ctx.db(), current_edition),
+ target_name.display(ctx.db(), current_edition)
);
acc.add(AssistId("fix_visibility", AssistKind::QuickFix), assist_label, target, |edit| {
diff --git a/crates/ide-assists/src/handlers/generate_delegate_methods.rs b/crates/ide-assists/src/handlers/generate_delegate_methods.rs
index 2150003bc1..bbb902f8a2 100644
--- a/crates/ide-assists/src/handlers/generate_delegate_methods.rs
+++ b/crates/ide-assists/src/handlers/generate_delegate_methods.rs
@@ -51,6 +51,7 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<'
let strukt = ctx.find_node_at_offset::<ast::Struct>()?;
let strukt_name = strukt.name()?;
let current_module = ctx.sema.scope(strukt.syntax())?.module();
+ let current_edition = current_module.krate().edition(ctx.db());
let (field_name, field_ty, target) = match ctx.find_node_at_offset::<ast::RecordField>() {
Some(field) => {
@@ -89,7 +90,7 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<'
methods.sort_by(|(a, _), (b, _)| a.cmp(b));
for (name, method) in methods {
let adt = ast::Adt::Struct(strukt.clone());
- let name = name.display(ctx.db()).to_string();
+ let name = name.display(ctx.db(), current_edition).to_string();
// if `find_struct_impl` returns None, that means that a function named `name` already exists.
let Some(impl_def) = find_struct_impl(ctx, &adt, std::slice::from_ref(&name)) else {
continue;
diff --git a/crates/ide-assists/src/handlers/generate_delegate_trait.rs b/crates/ide-assists/src/handlers/generate_delegate_trait.rs
index 5a3457e5b7..933ab2058e 100644
--- a/crates/ide-assists/src/handlers/generate_delegate_trait.rs
+++ b/crates/ide-assists/src/handlers/generate_delegate_trait.rs
@@ -22,7 +22,7 @@ use syntax::{
WherePred,
},
ted::{self, Position},
- AstNode, NodeOrToken, SmolStr, SyntaxKind, ToSmolStr,
+ AstNode, Edition, NodeOrToken, SmolStr, SyntaxKind, ToSmolStr,
};
// Assist: generate_delegate_trait
@@ -109,6 +109,7 @@ struct Field {
ty: ast::Type,
range: syntax::TextRange,
impls: Vec<Delegee>,
+ edition: Edition,
}
impl Field {
@@ -119,6 +120,7 @@ impl Field {
let db = ctx.sema.db;
let module = ctx.sema.file_to_module_def(ctx.file_id())?;
+ let edition = module.krate().edition(ctx.db());
let (name, range, ty) = match f {
Either::Left(f) => {
@@ -147,7 +149,7 @@ impl Field {
}
}
- Some(Field { name, ty, range, impls })
+ Some(Field { name, ty, range, impls, edition })
}
}
@@ -163,18 +165,18 @@ enum Delegee {
}
impl Delegee {
- fn signature(&self, db: &dyn HirDatabase) -> String {
+ fn signature(&self, db: &dyn HirDatabase, edition: Edition) -> String {
let mut s = String::new();
let (Delegee::Bound(it) | Delegee::Impls(it, _)) = self;
for m in it.module(db).path_to_root(db).iter().rev() {
if let Some(name) = m.name(db) {
- s.push_str(&format!("{}::", name.display_no_db().to_smolstr()));
+ s.push_str(&format!("{}::", name.display_no_db(edition).to_smolstr()));
}
}
- s.push_str(&it.name(db).display_no_db().to_smolstr());
+ s.push_str(&it.name(db).display_no_db(edition).to_smolstr());
s
}
}
@@ -212,9 +214,11 @@ impl Struct {
// if self.hir_ty.impls_trait(db, trait_, &[]) {
// continue;
// }
- let signature = delegee.signature(db);
+ let signature = delegee.signature(db, field.edition);
- let Some(delegate) = generate_impl(ctx, self, &field.ty, &field.name, delegee) else {
+ let Some(delegate) =
+ generate_impl(ctx, self, &field.ty, &field.name, delegee, field.edition)
+ else {
continue;
};
@@ -240,6 +244,7 @@ fn generate_impl(
field_ty: &ast::Type,
field_name: &str,
delegee: &Delegee,
+ edition: Edition,
) -> Option<ast::Impl> {
let delegate: ast::Impl;
let db = ctx.db();
@@ -259,7 +264,7 @@ fn generate_impl(
strukt_params.clone(),
strukt_params.map(|params| params.to_generic_args()),
delegee.is_auto(db),
- make::ty(&delegee.name(db).display_no_db().to_smolstr()),
+ make::ty(&delegee.name(db).display_no_db(edition).to_smolstr()),
strukt_ty,
bound_def.where_clause(),
ast_strukt.where_clause(),
@@ -350,7 +355,7 @@ fn generate_impl(
let type_gen_args = strukt_params.clone().map(|params| params.to_generic_args());
let path_type =
- make::ty(&trait_.name(db).display_no_db().to_smolstr()).clone_for_update();
+ make::ty(&trait_.name(db).display_no_db(edition).to_smolstr()).clone_for_update();
transform_impl(ctx, ast_strukt, &old_impl, &transform_args, path_type.syntax())?;
// 3) Generate delegate trait impl
diff --git a/crates/ide-assists/src/handlers/generate_deref.rs b/crates/ide-assists/src/handlers/generate_deref.rs
index 2ac7057fe7..e558bb6da8 100644
--- a/crates/ide-assists/src/handlers/generate_deref.rs
+++ b/crates/ide-assists/src/handlers/generate_deref.rs
@@ -4,7 +4,7 @@ use hir::{ModPath, ModuleDef};
use ide_db::{famous_defs::FamousDefs, RootDatabase};
use syntax::{
ast::{self, HasName},
- AstNode, SyntaxNode,
+ AstNode, Edition, SyntaxNode,
};
use crate::{
@@ -77,6 +77,7 @@ fn generate_record_deref(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<(
field_name.syntax(),
deref_type_to_generate,
trait_path,
+ module.krate().edition(ctx.db()),
)
},
)
@@ -117,6 +118,7 @@ fn generate_tuple_deref(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()
field_list_index,
deref_type_to_generate,
trait_path,
+ module.krate().edition(ctx.db()),
)
},
)
@@ -130,6 +132,7 @@ fn generate_edit(
field_name: impl Display,
deref_type: DerefType,
trait_path: ModPath,
+ edition: Edition,
) {
let start_offset = strukt.syntax().text_range().end();
let impl_code = match deref_type {
@@ -147,8 +150,11 @@ fn generate_edit(
),
};
let strukt_adt = ast::Adt::Struct(strukt);
- let deref_impl =
- generate_trait_impl_text(&strukt_adt, &trait_path.display(db).to_string(), &impl_code);
+ let deref_impl = generate_trait_impl_text(
+ &strukt_adt,
+ &trait_path.display(db, edition).to_string(),
+ &impl_code,
+ );
edit.insert(start_offset, deref_impl);
}
diff --git a/crates/ide-assists/src/handlers/generate_documentation_template.rs b/crates/ide-assists/src/handlers/generate_documentation_template.rs
index 51dd488454..c5c70c9f8e 100644
--- a/crates/ide-assists/src/handlers/generate_documentation_template.rs
+++ b/crates/ide-assists/src/handlers/generate_documentation_template.rs
@@ -5,7 +5,7 @@ use stdx::{format_to, to_lower_snake_case};
use syntax::{
algo::skip_whitespace_token,
ast::{self, edit::IndentLevel, HasDocComments, HasGenericArgs, HasName},
- match_ast, AstNode, AstToken,
+ match_ast, AstNode, AstToken, Edition,
};
use crate::assist_context::{AssistContext, Assists};
@@ -139,7 +139,8 @@ fn make_example_for_fn(ast_func: &ast::Fn, ctx: &AssistContext<'_>) -> Option<St
let mut example = String::new();
- let use_path = build_path(ast_func, ctx)?;
+ let edition = ctx.sema.scope(ast_func.syntax())?.krate().edition(ctx.db());
+ let use_path = build_path(ast_func, ctx, edition)?;
let is_unsafe = ast_func.unsafe_token().is_some();
let param_list = ast_func.param_list()?;
let ref_mut_params = ref_mut_params(&param_list);
@@ -472,13 +473,13 @@ fn string_vec_from(string_array: &[&str]) -> Vec<String> {
}
/// Helper function to build the path of the module in the which is the node
-fn build_path(ast_func: &ast::Fn, ctx: &AssistContext<'_>) -> Option<String> {
+fn build_path(ast_func: &ast::Fn, ctx: &AssistContext<'_>, edition: Edition) -> Option<String> {
let crate_name = crate_name(ast_func, ctx)?;
let leaf = self_partial_type(ast_func)
.or_else(|| ast_func.name().map(|n| n.to_string()))
.unwrap_or_else(|| "*".into());
let module_def: ModuleDef = ctx.sema.to_def(ast_func)?.module(ctx.db()).into();
- match module_def.canonical_path(ctx.db()) {
+ match module_def.canonical_path(ctx.db(), edition) {
Some(path) => Some(format!("{crate_name}::{path}::{leaf}")),
None => Some(format!("{crate_name}::{leaf}")),
}
diff --git a/crates/ide-assists/src/handlers/generate_function.rs b/crates/ide-assists/src/handlers/generate_function.rs
index b2980d5c63..cd29f77f0c 100644
--- a/crates/ide-assists/src/handlers/generate_function.rs
+++ b/crates/ide-assists/src/handlers/generate_function.rs
@@ -17,7 +17,7 @@ use syntax::{
self, edit::IndentLevel, edit_in_place::Indent, make, AstNode, BlockExpr, CallExpr,
HasArgList, HasGenericParams, HasModuleItem, HasTypeBounds,
},
- ted, SyntaxKind, SyntaxNode, TextRange, T,
+ ted, Edition, SyntaxKind, SyntaxNode, TextRange, T,
};
use crate::{
@@ -175,6 +175,7 @@ fn add_func_to_accumulator(
edit.edit_file(file);
let target = function_builder.target.clone();
+ let edition = function_builder.target_edition;
let func = function_builder.render(ctx.config.snippet_cap, edit);
if let Some(adt) =
@@ -183,7 +184,7 @@ fn add_func_to_accumulator(
{
let name = make::ty_path(make::ext::ident_path(&format!(
"{}",
- adt.name(ctx.db()).display(ctx.db())
+ adt.name(ctx.db()).display(ctx.db(), edition)
)));
// FIXME: adt may have generic params.
@@ -222,6 +223,7 @@ struct FunctionBuilder {
should_focus_return_type: bool,
visibility: Visibility,
is_async: bool,
+ target_edition: Edition,
}
impl FunctionBuilder {
@@ -237,6 +239,7 @@ impl FunctionBuilder {
) -> Option<Self> {
let target_module =
target_module.or_else(|| ctx.sema.scope(target.syntax()).map(|it| it.module()))?;
+ let target_edition = target_module.krate().edition(ctx.db());
let current_module = ctx.sema.scope(call.syntax())?.module();
let visibility = calculate_necessary_visibility(current_module, target_module, ctx);
@@ -258,7 +261,9 @@ impl FunctionBuilder {
// If generated function has the name "new" and is an associated function, we generate fn body
// as a constructor and assume a "Self" return type.
- if let Some(body) = make_fn_body_as_new_function(ctx, &fn_name.text(), adt_info) {
+ if let Some(body) =
+ make_fn_body_as_new_function(ctx, &fn_name.text(), adt_info, target_edition)
+ {
ret_type = Some(make::ret_type(make::ty_path(make::ext::ident_path("Self"))));
should_focus_return_type = false;
fn_body = body;
@@ -288,6 +293,7 @@ impl FunctionBuilder {
should_focus_return_type,
visibility,
is_async,
+ target_edition,
})
}
@@ -299,6 +305,8 @@ impl FunctionBuilder {
target_module: Module,
target: GeneratedFunctionTarget,
) -> Option<Self> {
+ let target_edition = target_module.krate().edition(ctx.db());
+
let current_module = ctx.sema.scope(call.syntax())?.module();
let visibility = calculate_necessary_visibility(current_module, target_module, ctx);
@@ -336,6 +344,7 @@ impl FunctionBuilder {
should_focus_return_type,
visibility,
is_async,
+ target_edition,
})
}
@@ -425,6 +434,7 @@ fn make_fn_body_as_new_function(
ctx: &AssistContext<'_>,
fn_name: &str,
adt_info: &Option<AdtInfo>,
+ edition: Edition,
) -> Option<ast::BlockExpr> {
if fn_name != "new" {
return None;
@@ -441,7 +451,10 @@ fn make_fn_body_as_new_function(
.iter()
.map(|field| {
make::record_expr_field(
- make::name_ref(&format!("{}", field.name(ctx.db()).display(ctx.db()))),
+ make::name_ref(&format!(
+ "{}",
+ field.name(ctx.db()).display(ctx.db(), edition)
+ )),
Some(placeholder_expr.clone()),
)
})
@@ -1102,8 +1115,9 @@ 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()).to_string())
+ .map(|conversion| conversion.convert_type(ctx.db(), target_edition).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/crates/ide-assists/src/handlers/generate_getter_or_setter.rs b/crates/ide-assists/src/handlers/generate_getter_or_setter.rs
index 60214aaaf6..8e349e84a9 100644
--- a/crates/ide-assists/src/handlers/generate_getter_or_setter.rs
+++ b/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()),
+ conversion.convert_type(ctx.db(), krate.edition(ctx.db())),
conversion.getter(record_field_info.field_name.to_string()),
)
})
diff --git a/crates/ide-assists/src/handlers/generate_new.rs b/crates/ide-assists/src/handlers/generate_new.rs
index b985b5e66c..b9dede7cbd 100644
--- a/crates/ide-assists/src/handlers/generate_new.rs
+++ b/crates/ide-assists/src/handlers/generate_new.rs
@@ -64,10 +64,13 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
ctx.config.import_path_config(),
)?;
+ let edition = current_module.krate().edition(ctx.db());
+
let expr = use_trivial_constructor(
ctx.sema.db,
- ide_db::helpers::mod_path_to_ast(&type_path),
+ ide_db::helpers::mod_path_to_ast(&type_path, edition),
&ty,
+ edition,
)?;
Some(make::record_expr_field(make::name_ref(&name.text()), Some(expr)))
diff --git a/crates/ide-assists/src/handlers/inline_const_as_literal.rs b/crates/ide-assists/src/handlers/inline_const_as_literal.rs
index 111ea50fdc..f1c2acdd3e 100644
--- a/crates/ide-assists/src/handlers/inline_const_as_literal.rs
+++ b/crates/ide-assists/src/handlers/inline_const_as_literal.rs
@@ -51,10 +51,13 @@ pub(crate) fn inline_const_as_literal(acc: &mut Assists, ctx: &AssistContext<'_>
| ast::Expr::MatchExpr(_)
| ast::Expr::MacroExpr(_)
| ast::Expr::BinExpr(_)
- | ast::Expr::CallExpr(_) => match konst.render_eval(ctx.sema.db) {
- Ok(result) => result,
- Err(_) => return None,
- },
+ | ast::Expr::CallExpr(_) => {
+ let edition = ctx.sema.scope(variable.syntax())?.krate().edition(ctx.db());
+ match konst.render_eval(ctx.sema.db, edition) {
+ Ok(result) => result,
+ Err(_) => return None,
+ }
+ }
_ => return None,
};
diff --git a/crates/ide-assists/src/handlers/move_const_to_impl.rs b/crates/ide-assists/src/handlers/move_const_to_impl.rs
index 3057745a97..743ea94761 100644
--- a/crates/ide-assists/src/handlers/move_const_to_impl.rs
+++ b/crates/ide-assists/src/handlers/move_const_to_impl.rs
@@ -104,9 +104,13 @@ pub(crate) fn move_const_to_impl(acc: &mut Assists, ctx: &AssistContext<'_>) ->
};
builder.delete(range_to_delete);
- let const_ref = format!("Self::{}", name.display(ctx.db()));
- for range in usages.file_ranges().map(|it| it.range) {
- builder.replace(range, const_ref.clone());
+ let usages = usages.iter().flat_map(|(file_id, usages)| {
+ let edition = file_id.edition();
+ usages.iter().map(move |usage| (edition, usage.range))
+ });
+ for (edition, range) in usages {
+ let const_ref = format!("Self::{}", name.display(ctx.db(), edition));
+ builder.replace(range, const_ref);
}
// Heuristically inserting the extracted const after the consecutive existing consts
diff --git a/crates/ide-assists/src/handlers/move_from_mod_rs.rs b/crates/ide-assists/src/handlers/move_from_mod_rs.rs
index 14381085a7..8a7a06b380 100644
--- a/crates/ide-assists/src/handlers/move_from_mod_rs.rs
+++ b/crates/ide-assists/src/handlers/move_from_mod_rs.rs
@@ -39,7 +39,7 @@ pub(crate) fn move_from_mod_rs(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
}
let target = source_file.syntax().text_range();
- let module_name = module.name(ctx.db())?.display(ctx.db()).to_string();
+ let module_name = module.name(ctx.db())?.unescaped().display(ctx.db()).to_string();
let path = format!("../{module_name}.rs");
let dst = AnchoredPathBuf { anchor: ctx.file_id().into(), path };
acc.add(
diff --git a/crates/ide-assists/src/handlers/move_module_to_file.rs b/crates/ide-assists/src/handlers/move_module_to_file.rs
index e679a68f44..9692b70592 100644
--- a/crates/ide-assists/src/handlers/move_module_to_file.rs
+++ b/crates/ide-assists/src/handlers/move_module_to_file.rs
@@ -61,7 +61,7 @@ pub(crate) fn move_module_to_file(acc: &mut Assists, ctx: &AssistContext<'_>) ->
.string_value_unescape()
.is_none() =>
{
- format_to!(buf, "{}/", name.display(db))
+ format_to!(buf, "{}/", name.unescaped().display(db))
}
_ => (),
}
diff --git a/crates/ide-assists/src/handlers/move_to_mod_rs.rs b/crates/ide-assists/src/handlers/move_to_mod_rs.rs
index c89d54ff03..2925e2334b 100644
--- a/crates/ide-assists/src/handlers/move_to_mod_rs.rs
+++ b/crates/ide-assists/src/handlers/move_to_mod_rs.rs
@@ -39,7 +39,7 @@ pub(crate) fn move_to_mod_rs(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
}
let target = source_file.syntax().text_range();
- let module_name = module.name(ctx.db())?.display(ctx.db()).to_string();
+ let module_name = module.name(ctx.db())?.unescaped().display(ctx.db()).to_string();
let path = format!("./{module_name}/mod.rs");
let dst = AnchoredPathBuf { anchor: ctx.file_id().into(), path };
acc.add(
diff --git a/crates/ide-assists/src/handlers/qualify_method_call.rs b/crates/ide-assists/src/handlers/qualify_method_call.rs
index b1e98045fc..14518c4d2c 100644
--- a/crates/ide-assists/src/handlers/qualify_method_call.rs
+++ b/crates/ide-assists/src/handlers/qualify_method_call.rs
@@ -42,6 +42,7 @@ pub(crate) fn qualify_method_call(acc: &mut Assists, ctx: &AssistContext<'_>) ->
let resolved_call = ctx.sema.resolve_method_call(&call)?;
let current_module = ctx.sema.scope(call.syntax())?.module();
+ let current_edition = current_module.krate().edition(ctx.db());
let target_module_def = ModuleDef::from(resolved_call);
let item_in_ns = ItemInNs::from(target_module_def);
let receiver_path = current_module.find_path(
@@ -61,6 +62,7 @@ pub(crate) fn qualify_method_call(acc: &mut Assists, ctx: &AssistContext<'_>) ->
|replace_with: String| builder.replace(range, replace_with),
&receiver_path,
item_in_ns,
+ current_edition,
)
},
);
diff --git a/crates/ide-assists/src/handlers/qualify_path.rs b/crates/ide-assists/src/handlers/qualify_path.rs
index d8e7da15d5..ac88861fe4 100644
--- a/crates/ide-assists/src/handlers/qualify_path.rs
+++ b/crates/ide-assists/src/handlers/qualify_path.rs
@@ -8,6 +8,7 @@ use ide_db::{
imports::import_assets::{ImportCandidate, LocatedImport},
};
use syntax::ast::HasGenericArgs;
+use syntax::Edition;
use syntax::{
ast,
ast::{make, HasArgList},
@@ -93,6 +94,8 @@ pub(crate) fn qualify_path(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
NodeOrToken::Token(t) => t.parent()?,
})
.map(|scope| scope.module());
+ let current_edition =
+ current_module.map(|it| it.krate().edition(ctx.db())).unwrap_or(Edition::CURRENT);
// prioritize more relevant imports
proposed_imports.sort_by_key(|import| {
Reverse(super::auto_import::relevance_score(ctx, import, current_module.as_ref()))
@@ -103,13 +106,14 @@ pub(crate) fn qualify_path(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
acc.add_group(
&group_label,
AssistId("qualify_path", AssistKind::QuickFix),
- label(ctx.db(), candidate, &import),
+ label(ctx.db(), candidate, &import, current_edition),
range,
|builder| {
qualify_candidate.qualify(
|replace_with: String| builder.replace(range, replace_with),
&import.import_path,
import.item_to_import,
+ current_edition,
)
},
);
@@ -130,8 +134,9 @@ impl QualifyCandidate<'_> {
mut replacer: impl FnMut(String),
import: &hir::ModPath,
item: hir::ItemInNs,
+ edition: Edition,
) {
- let import = mod_path_to_ast(import);
+ let import = mod_path_to_ast(import, edition);
match self {
QualifyCandidate::QualifierStart(segment, generics) => {
let generics = generics.as_ref().map_or_else(String::new, ToString::to_string);
@@ -203,7 +208,7 @@ fn find_trait_method(
if let Some(hir::AssocItem::Function(method)) =
trait_.items(db).into_iter().find(|item: &hir::AssocItem| {
item.name(db)
- .map(|name| name.display(db).to_string() == trait_method_name.to_string())
+ .map(|name| name.eq_ident(trait_method_name.text().as_str()))
.unwrap_or(false)
})
{
@@ -233,14 +238,19 @@ fn group_label(candidate: &ImportCandidate) -> GroupLabel {
GroupLabel(format!("Qualify {name}"))
}
-fn label(db: &RootDatabase, candidate: &ImportCandidate, import: &LocatedImport) -> String {
+fn label(
+ db: &RootDatabase,
+ candidate: &ImportCandidate,
+ import: &LocatedImport,
+ edition: Edition,
+) -> String {
let import_path = &import.import_path;
match candidate {
ImportCandidate::Path(candidate) if candidate.qualifier.is_none() => {
- format!("Qualify as `{}`", import_path.display(db))
+ format!("Qualify as `{}`", import_path.display(db, edition))
}
- _ => format!("Qualify with `{}`", import_path.display(db)),
+ _ => format!("Qualify with `{}`", import_path.display(db, edition)),
}
}
diff --git a/crates/ide-assists/src/handlers/reorder_fields.rs b/crates/ide-assists/src/handlers/reorder_fields.rs
index 0256256697..df7a5112f1 100644
--- a/crates/ide-assists/src/handlers/reorder_fields.rs
+++ b/crates/ide-assists/src/handlers/reorder_fields.rs
@@ -1,7 +1,7 @@
use either::Either;
use ide_db::FxHashMap;
use itertools::Itertools;
-use syntax::{ast, ted, AstNode};
+use syntax::{ast, ted, AstNode, SmolStr, ToSmolStr};
use crate::{AssistContext, AssistId, AssistKind, Assists};
@@ -25,8 +25,9 @@ pub(crate) fn reorder_fields(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
path.syntax().parent().and_then(<Either<ast::RecordExpr, ast::RecordPat>>::cast)?;
let ranks = compute_fields_ranks(&path, ctx)?;
- let get_rank_of_field =
- |of: Option<_>| *ranks.get(&of.unwrap_or_default()).unwrap_or(&usize::MAX);
+ let get_rank_of_field = |of: Option<SmolStr>| {
+ *ranks.get(of.unwrap_or_default().trim_start_matches("r#")).unwrap_or(&usize::MAX)
+ };
let field_list = match &record {
Either::Left(it) => Either::Left(it.record_expr_field_list()?),
@@ -36,7 +37,7 @@ pub(crate) fn reorder_fields(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
Either::Left(it) => Either::Left((
it.fields()
.sorted_unstable_by_key(|field| {
- get_rank_of_field(field.field_name().map(|it| it.to_string()))
+ get_rank_of_field(field.field_name().map(|it| it.to_smolstr()))
})
.collect::<Vec<_>>(),
it,
@@ -44,7 +45,7 @@ pub(crate) fn reorder_fields(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
Either::Right(it) => Either::Right((
it.fields()
.sorted_unstable_by_key(|field| {
- get_rank_of_field(field.field_name().map(|it| it.to_string()))
+ get_rank_of_field(field.field_name().map(|it| it.to_smolstr()))
})
.collect::<Vec<_>>(),
it,
@@ -97,7 +98,7 @@ fn compute_fields_ranks(
.fields(ctx.db())
.into_iter()
.enumerate()
- .map(|(idx, field)| (field.name(ctx.db()).display(ctx.db()).to_string(), idx))
+ .map(|(idx, field)| (field.name(ctx.db()).unescaped().display(ctx.db()).to_string(), idx))
.collect();
Some(res)
diff --git a/crates/ide-assists/src/handlers/reorder_impl_items.rs b/crates/ide-assists/src/handlers/reorder_impl_items.rs
index cf135f83e7..ada89ce7c4 100644
--- a/crates/ide-assists/src/handlers/reorder_impl_items.rs
+++ b/crates/ide-assists/src/handlers/reorder_impl_items.rs
@@ -77,7 +77,8 @@ pub(crate) fn reorder_impl_items(acc: &mut Assists, ctx: &AssistContext<'_>) ->
ast::AssocItem::MacroCall(_) => None,
};
- name.and_then(|n| ranks.get(&n.to_string()).copied()).unwrap_or(usize::MAX)
+ name.and_then(|n| ranks.get(n.text().as_str().trim_start_matches("r#")).copied())
+ .unwrap_or(usize::MAX)
})
.collect();
@@ -114,7 +115,7 @@ fn compute_item_ranks(
.iter()
.flat_map(|i| i.name(ctx.db()))
.enumerate()
- .map(|(idx, name)| (name.display(ctx.db()).to_string(), idx))
+ .map(|(idx, name)| (name.unescaped().display(ctx.db()).to_string(), idx))
.collect(),
)
}
diff --git a/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs b/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs
index 5ff4af19fb..248f18789c 100644
--- a/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs
+++ b/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs
@@ -70,6 +70,7 @@ pub(crate) fn replace_derive_with_manual_impl(
let current_module = ctx.sema.scope(adt.syntax())?.module();
let current_crate = current_module.krate();
+ let current_edition = current_crate.edition(ctx.db());
let found_traits = items_locator::items_with_name(
&ctx.sema,
@@ -85,7 +86,7 @@ pub(crate) fn replace_derive_with_manual_impl(
current_module
.find_path(ctx.sema.db, hir::ModuleDef::Trait(trait_), ctx.config.import_path_config())
.as_ref()
- .map(mod_path_to_ast)
+ .map(|path| mod_path_to_ast(path, current_edition))
.zip(Some(trait_))
});
@@ -214,7 +215,7 @@ fn impl_def_from_trait(
let impl_def = generate_trait_impl(adt, make::ty_path(trait_path.clone()));
let first_assoc_item =
- add_trait_assoc_items_to_impl(sema, &trait_items, trait_, &impl_def, target_scope);
+ add_trait_assoc_items_to_impl(sema, &trait_items, trait_, &impl_def, &target_scope);
// Generate a default `impl` function body for the derived trait.
if let ast::AssocItem::Fn(ref func) = first_assoc_item {
diff --git a/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs b/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs
index d0aa835e79..65330b34c4 100644
--- a/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs
+++ b/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs
@@ -5,7 +5,7 @@ use ide_db::{
};
use syntax::{
ast::{self, make, HasGenericArgs},
- match_ast, ted, AstNode, SyntaxNode,
+ match_ast, ted, AstNode, Edition, SyntaxNode,
};
use crate::{AssistContext, AssistId, AssistKind, Assists};
@@ -29,32 +29,32 @@ pub(crate) fn replace_qualified_name_with_use(
acc: &mut Assists,
ctx: &AssistContext<'_>,
) -> Option<()> {
- let path: ast::Path = ctx.find_node_at_offset()?;
+ let original_path: ast::Path = ctx.find_node_at_offset()?;
// We don't want to mess with use statements
- if path.syntax().ancestors().find_map(ast::UseTree::cast).is_some() {
+ if original_path.syntax().ancestors().find_map(ast::UseTree::cast).is_some() {
cov_mark::hit!(not_applicable_in_use);
return None;
}
- if path.qualifier().is_none() {
+ if original_path.qualifier().is_none() {
cov_mark::hit!(dont_import_trivial_paths);
return None;
}
// only offer replacement for non assoc items
- match ctx.sema.resolve_path(&path)? {
+ match ctx.sema.resolve_path(&original_path)? {
hir::PathResolution::Def(def) if def.as_assoc_item(ctx.sema.db).is_none() => (),
_ => return None,
}
// then search for an import for the first path segment of what we want to replace
// that way it is less likely that we import the item from a different location due re-exports
- let module = match ctx.sema.resolve_path(&path.first_qualifier_or_self())? {
+ let module = match ctx.sema.resolve_path(&original_path.first_qualifier_or_self())? {
hir::PathResolution::Def(module @ hir::ModuleDef::Module(_)) => module,
_ => return None,
};
let starts_with_name_ref = !matches!(
- path.first_segment().and_then(|it| it.kind()),
+ original_path.first_segment().and_then(|it| it.kind()),
Some(
ast::PathSegmentKind::CrateKw
| ast::PathSegmentKind::SuperKw
@@ -63,7 +63,7 @@ pub(crate) fn replace_qualified_name_with_use(
);
let path_to_qualifier = starts_with_name_ref
.then(|| {
- ctx.sema.scope(path.syntax())?.module().find_use_path(
+ ctx.sema.scope(original_path.syntax())?.module().find_use_path(
ctx.sema.db,
module,
ctx.config.insert_use.prefix_kind,
@@ -72,8 +72,8 @@ pub(crate) fn replace_qualified_name_with_use(
})
.flatten();
- let scope = ImportScope::find_insert_use_container(path.syntax(), &ctx.sema)?;
- let target = path.syntax().text_range();
+ let scope = ImportScope::find_insert_use_container(original_path.syntax(), &ctx.sema)?;
+ let target = original_path.syntax().text_range();
acc.add(
AssistId("replace_qualified_name_with_use", AssistKind::RefactorRewrite),
"Replace qualified path with use",
@@ -86,13 +86,19 @@ pub(crate) fn replace_qualified_name_with_use(
ImportScope::Module(it) => ImportScope::Module(builder.make_mut(it)),
ImportScope::Block(it) => ImportScope::Block(builder.make_mut(it)),
};
- shorten_paths(scope.as_syntax_node(), &path);
- let path = drop_generic_args(&path);
+ shorten_paths(scope.as_syntax_node(), &original_path);
+ let path = drop_generic_args(&original_path);
+ let edition = ctx
+ .sema
+ .scope(original_path.syntax())
+ .map(|semantics_scope| semantics_scope.krate().edition(ctx.db()))
+ .unwrap_or(Edition::CURRENT);
// stick the found import in front of the to be replaced path
- let path = match path_to_qualifier.and_then(|it| mod_path_to_ast(&it).qualifier()) {
- Some(qualifier) => make::path_concat(qualifier, path),
- None => path,
- };
+ let path =
+ match path_to_qualifier.and_then(|it| mod_path_to_ast(&it, edition).qualifier()) {
+ Some(qualifier) => make::path_concat(qualifier, path),
+ None => path,
+ };
insert_use(&scope, path, &ctx.config.insert_use);
},
)
diff --git a/crates/ide-assists/src/handlers/term_search.rs b/crates/ide-assists/src/handlers/term_search.rs
index 4913cfdea9..66671c934c 100644
--- a/crates/ide-assists/src/handlers/term_search.rs
+++ b/crates/ide-assists/src/handlers/term_search.rs
@@ -48,15 +48,17 @@ pub(crate) fn term_search(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<
let mut formatter = |_: &hir::Type| String::from("todo!()");
+ let edition = scope.krate().edition(ctx.db());
let paths = paths
.into_iter()
.filter_map(|path| {
- path.gen_source_code(&scope, &mut formatter, ctx.config.import_path_config()).ok()
+ path.gen_source_code(&scope, &mut formatter, ctx.config.import_path_config(), edition)
+ .ok()
})
.unique();
let macro_name = macro_call.name(ctx.sema.db);
- let macro_name = macro_name.display(ctx.sema.db);
+ let macro_name = macro_name.display(ctx.sema.db, edition);
for code in paths {
acc.add_group(
diff --git a/crates/ide-assists/src/handlers/toggle_async_sugar.rs b/crates/ide-assists/src/handlers/toggle_async_sugar.rs
index 98975a324d..9ab36bf775 100644
--- a/crates/ide-assists/src/handlers/toggle_async_sugar.rs
+++ b/crates/ide-assists/src/handlers/toggle_async_sugar.rs
@@ -141,7 +141,8 @@ pub(crate) fn desugar_async_into_impl_future(
ModuleDef::Trait(future_trait),
ctx.config.import_path_config(),
)?;
- let trait_path = trait_path.display(ctx.db());
+ let edition = scope.krate().edition(ctx.db());
+ let trait_path = trait_path.display(ctx.db(), edition);
acc.add(
AssistId("desugar_async_into_impl_future", AssistKind::RefactorRewrite),
diff --git a/crates/ide-assists/src/utils.rs b/crates/ide-assists/src/utils.rs
index c67693ea2b..b8a6f3b6db 100644
--- a/crates/ide-assists/src/utils.rs
+++ b/crates/ide-assists/src/utils.rs
@@ -14,7 +14,7 @@ use syntax::{
edit_in_place::{AttrsOwnerEdit, Indent, Removable},
make, HasArgList, HasAttrs, HasGenericParams, HasName, HasTypeBounds, Whitespace,
},
- ted, AstNode, AstToken, Direction, NodeOrToken, SourceFile,
+ ted, AstNode, AstToken, Direction, Edition, NodeOrToken, SourceFile,
SyntaxKind::*,
SyntaxNode, SyntaxToken, TextRange, TextSize, T,
};
@@ -174,7 +174,7 @@ pub fn add_trait_assoc_items_to_impl(
original_items: &[InFile<ast::AssocItem>],
trait_: hir::Trait,
impl_: &ast::Impl,
- target_scope: hir::SemanticsScope<'_>,
+ target_scope: &hir::SemanticsScope<'_>,
) -> ast::AssocItem {
let new_indent_level = IndentLevel::from_node(impl_.syntax()) + 1;
let items = original_items.iter().map(|InFile { file_id, value: original_item }| {
@@ -195,7 +195,7 @@ pub fn add_trait_assoc_items_to_impl(
// FIXME: Paths in nested macros are not handled well. See
// `add_missing_impl_members::paths_in_nested_macro_should_get_transformed` test.
let transform =
- PathTransform::trait_impl(&target_scope, &source_scope, trait_, impl_.clone());
+ PathTransform::trait_impl(target_scope, &source_scope, trait_, impl_.clone());
transform.apply(cloned_item.syntax());
}
cloned_item.remove_attrs_and_docs();
@@ -684,31 +684,31 @@ enum ReferenceConversionType {
}
impl ReferenceConversion {
- pub(crate) fn convert_type(&self, db: &dyn HirDatabase) -> ast::Type {
+ pub(crate) fn convert_type(&self, db: &dyn HirDatabase, edition: Edition) -> ast::Type {
let ty = match self.conversion {
- ReferenceConversionType::Copy => self.ty.display(db).to_string(),
+ ReferenceConversionType::Copy => self.ty.display(db, edition).to_string(),
ReferenceConversionType::AsRefStr => "&str".to_owned(),
ReferenceConversionType::AsRefSlice => {
let type_argument_name =
- self.ty.type_arguments().next().unwrap().display(db).to_string();
+ self.ty.type_arguments().next().unwrap().display(db, edition).to_string();
format!("&[{type_argument_name}]")
}
ReferenceConversionType::Dereferenced => {
let type_argument_name =
- self.ty.type_arguments().next().unwrap().display(db).to_string();
+ self.ty.type_arguments().next().unwrap().display(db, edition).to_string();
format!("&{type_argument_name}")
}
ReferenceConversionType::Option => {
let type_argument_name =
- self.ty.type_arguments().next().unwrap().display(db).to_string();
+ self.ty.type_arguments().next().unwrap().display(db, edition).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).to_string();
+ type_arguments.next().unwrap().display(db, edition).to_string();
let second_type_argument_name =
- type_arguments.next().unwrap().display(db).to_string();
+ type_arguments.next().unwrap().display(db, edition).to_string();
format!("Result<&{first_type_argument_name}, &{second_type_argument_name}>")
}
};
diff --git a/crates/ide-assists/src/utils/suggest_name.rs b/crates/ide-assists/src/utils/suggest_name.rs
index fc43d243b3..3130ef0695 100644
--- a/crates/ide-assists/src/utils/suggest_name.rs
+++ b/crates/ide-assists/src/utils/suggest_name.rs
@@ -6,7 +6,7 @@ use itertools::Itertools;
use stdx::to_lower_snake_case;
use syntax::{
ast::{self, HasName},
- match_ast, AstNode, SmolStr,
+ match_ast, AstNode, Edition, SmolStr,
};
/// Trait names, that will be ignored when in `impl Trait` and `dyn Trait`
@@ -271,24 +271,25 @@ fn var_name_from_pat(pat: &ast::Pat) -> Option<ast::Name> {
fn from_type(expr: &ast::Expr, sema: &Semantics<'_, RootDatabase>) -> Option<String> {
let ty = sema.type_of_expr(expr)?.adjusted();
let ty = ty.remove_ref().unwrap_or(ty);
+ let edition = sema.scope(expr.syntax())?.krate().edition(sema.db);
- name_of_type(&ty, sema.db)
+ name_of_type(&ty, sema.db, edition)
}
-fn name_of_type(ty: &hir::Type, db: &RootDatabase) -> Option<String> {
+fn name_of_type(ty: &hir::Type, db: &RootDatabase, edition: Edition) -> Option<String> {
let name = if let Some(adt) = ty.as_adt() {
- let name = adt.name(db).display(db).to_string();
+ let name = adt.name(db).display(db, edition).to_string();
if WRAPPER_TYPES.contains(&name.as_str()) {
let inner_ty = ty.type_arguments().next()?;
- return name_of_type(&inner_ty, db);
+ return name_of_type(&inner_ty, db, edition);
}
name
} else if let Some(trait_) = ty.as_dyn_trait() {
- trait_name(&trait_, db)?
+ trait_name(&trait_, db, edition)?
} else if let Some(traits) = ty.as_impl_traits(db) {
- let mut iter = traits.filter_map(|t| trait_name(&t, db));
+ let mut iter = traits.filter_map(|t| trait_name(&t, db, edition));
let name = iter.next()?;
if iter.next().is_some() {
return None;
@@ -300,8 +301,8 @@ fn name_of_type(ty: &hir::Type, db: &RootDatabase) -> Option<String> {
normalize(&name)
}
-fn trait_name(trait_: &hir::Trait, db: &RootDatabase) -> Option<String> {
- let name = trait_.name(db).display(db).to_string();
+fn trait_name(trait_: &hir::Trait, db: &RootDatabase, edition: Edition) -> Option<String> {
+ let name = trait_.name(db).display(db, edition).to_string();
if USELESS_TRAITS.contains(&name.as_str()) {
return None;
}
diff --git a/crates/ide-completion/src/completions.rs b/crates/ide-completion/src/completions.rs
index 58e9b724df..b537150608 100644
--- a/crates/ide-completion/src/completions.rs
+++ b/crates/ide-completion/src/completions.rs
@@ -85,6 +85,7 @@ impl Completions {
CompletionItemKind::Keyword,
ctx.source_range(),
SmolStr::new_static(keyword),
+ ctx.edition,
);
item.add_to(self, ctx.db);
}
@@ -124,7 +125,8 @@ impl Completions {
kw: &str,
snippet: &str,
) {
- let mut item = CompletionItem::new(CompletionItemKind::Keyword, ctx.source_range(), kw);
+ let mut item =
+ CompletionItem::new(CompletionItemKind::Keyword, ctx.source_range(), kw, ctx.edition);
match ctx.config.snippet_cap {
Some(cap) => {
@@ -149,7 +151,8 @@ impl Completions {
kw: &str,
snippet: &str,
) {
- let mut item = CompletionItem::new(CompletionItemKind::Keyword, ctx.source_range(), kw);
+ let mut item =
+ CompletionItem::new(CompletionItemKind::Keyword, ctx.source_range(), kw, ctx.edition);
match ctx.config.snippet_cap {
Some(cap) => item.insert_snippet(cap, snippet),
@@ -544,7 +547,8 @@ impl Completions {
CompletionItem::new(
SymbolKind::LifetimeParam,
ctx.source_range(),
- name.display_no_db().to_smolstr(),
+ name.display_no_db(ctx.edition).to_smolstr(),
+ ctx.edition,
)
.add_to(self, ctx.db)
}
@@ -553,7 +557,8 @@ impl Completions {
CompletionItem::new(
SymbolKind::Label,
ctx.source_range(),
- name.display_no_db().to_smolstr(),
+ name.display_no_db(ctx.edition).to_smolstr(),
+ ctx.edition,
)
.add_to(self, ctx.db)
}
diff --git a/crates/ide-completion/src/completions/attribute.rs b/crates/ide-completion/src/completions/attribute.rs
index a7a6cdebd3..88f4461f4d 100644
--- a/crates/ide-completion/src/completions/attribute.rs
+++ b/crates/ide-completion/src/completions/attribute.rs
@@ -48,11 +48,15 @@ pub(crate) fn complete_known_attribute_input(
match path.text().as_str() {
"repr" => repr::complete_repr(acc, ctx, tt),
- "feature" => {
- lint::complete_lint(acc, ctx, colon_prefix, &parse_tt_as_comma_sep_paths(tt)?, FEATURES)
- }
+ "feature" => lint::complete_lint(
+ acc,
+ ctx,
+ colon_prefix,
+ &parse_tt_as_comma_sep_paths(tt, ctx.edition)?,
+ FEATURES,
+ ),
"allow" | "warn" | "deny" | "forbid" => {
- let existing_lints = parse_tt_as_comma_sep_paths(tt)?;
+ let existing_lints = parse_tt_as_comma_sep_paths(tt, ctx.edition)?;
let lints: Vec<Lint> = CLIPPY_LINT_GROUPS
.iter()
@@ -66,9 +70,12 @@ pub(crate) fn complete_known_attribute_input(
lint::complete_lint(acc, ctx, colon_prefix, &existing_lints, &lints);
}
"cfg" => cfg::complete_cfg(acc, ctx),
- "macro_use" => {
- macro_use::complete_macro_use(acc, ctx, extern_crate, &parse_tt_as_comma_sep_paths(tt)?)
- }
+ "macro_use" => macro_use::complete_macro_use(
+ acc,
+ ctx,
+ extern_crate,
+ &parse_tt_as_comma_sep_paths(tt, ctx.edition)?,
+ ),
_ => (),
}
Some(())
@@ -130,8 +137,12 @@ pub(crate) fn complete_attribute_path(
});
let add_completion = |attr_completion: &AttrCompletion| {
- let mut item =
- CompletionItem::new(SymbolKind::Attribute, ctx.source_range(), attr_completion.label);
+ let mut item = CompletionItem::new(
+ SymbolKind::Attribute,
+ ctx.source_range(),
+ attr_completion.label,
+ ctx.edition,
+ );
if let Some(lookup) = attr_completion.lookup {
item.lookup_by(lookup);
diff --git a/crates/ide-completion/src/completions/attribute/cfg.rs b/crates/ide-completion/src/completions/attribute/cfg.rs
index 6e7d50ede0..cda0da13b2 100644
--- a/crates/ide-completion/src/completions/attribute/cfg.rs
+++ b/crates/ide-completion/src/completions/attribute/cfg.rs
@@ -8,7 +8,8 @@ use crate::{completions::Completions, context::CompletionContext, CompletionItem
pub(crate) fn complete_cfg(acc: &mut Completions, ctx: &CompletionContext<'_>) {
let add_completion = |item: &str| {
- let mut completion = CompletionItem::new(SymbolKind::BuiltinAttr, ctx.source_range(), item);
+ let mut completion =
+ CompletionItem::new(SymbolKind::BuiltinAttr, ctx.source_range(), item, ctx.edition);
completion.insert_text(format!(r#""{item}""#));
acc.add(completion.build(ctx.db));
};
@@ -41,7 +42,12 @@ pub(crate) fn complete_cfg(acc: &mut Completions, ctx: &CompletionContext<'_>) {
name => ctx.krate.potential_cfg(ctx.db).get_cfg_values(name).cloned().for_each(|s| {
let s = s.as_str();
let insert_text = format!(r#""{s}""#);
- let mut item = CompletionItem::new(SymbolKind::BuiltinAttr, ctx.source_range(), s);
+ let mut item = CompletionItem::new(
+ SymbolKind::BuiltinAttr,
+ ctx.source_range(),
+ s,
+ ctx.edition,
+ );
item.insert_text(insert_text);
acc.add(item.build(ctx.db));
@@ -49,7 +55,8 @@ pub(crate) fn complete_cfg(acc: &mut Completions, ctx: &CompletionContext<'_>) {
},
None => ctx.krate.potential_cfg(ctx.db).get_cfg_keys().cloned().unique().for_each(|s| {
let s = s.as_str();
- let item = CompletionItem::new(SymbolKind::BuiltinAttr, ctx.source_range(), s);
+ let item =
+ CompletionItem::new(SymbolKind::BuiltinAttr, ctx.source_range(), s, ctx.edition);
acc.add(item.build(ctx.db));
}),
}
diff --git a/crates/ide-completion/src/completions/attribute/derive.rs b/crates/ide-completion/src/completions/attribute/derive.rs
index 0127a42824..1f8927401b 100644
--- a/crates/ide-completion/src/completions/attribute/derive.rs
+++ b/crates/ide-completion/src/completions/attribute/derive.rs
@@ -62,7 +62,7 @@ pub(crate) fn complete_derive_path(
_ => return acc.add_macro(ctx, path_ctx, mac, name),
};
- let name_ = name.display_no_db().to_smolstr();
+ let name_ = name.display_no_db(ctx.edition).to_smolstr();
let find = DEFAULT_DERIVE_DEPENDENCIES
.iter()
.find(|derive_completion| derive_completion.label == name_);
@@ -72,10 +72,9 @@ pub(crate) fn complete_derive_path(
let mut components = vec![derive_completion.label];
components.extend(derive_completion.dependencies.iter().filter(
|&&dependency| {
- !existing_derives
- .iter()
- .map(|it| it.name(ctx.db))
- .any(|it| it.display_no_db().to_smolstr() == dependency)
+ !existing_derives.iter().map(|it| it.name(ctx.db)).any(|it| {
+ it.display_no_db(ctx.edition).to_smolstr() == dependency
+ })
},
));
let lookup = components.join(", ");
@@ -85,6 +84,7 @@ pub(crate) fn complete_derive_path(
SymbolKind::Derive,
ctx.source_range(),
SmolStr::from_iter(label),
+ ctx.edition,
);
if let Some(docs) = mac.docs(ctx.db) {
item.documentation(docs);
diff --git a/crates/ide-completion/src/completions/attribute/lint.rs b/crates/ide-completion/src/completions/attribute/lint.rs
index f9dec53806..d5f9cd5fc7 100644
--- a/crates/ide-completion/src/completions/attribute/lint.rs
+++ b/crates/ide-completion/src/completions/attribute/lint.rs
@@ -54,7 +54,8 @@ pub(super) fn complete_lint(
Some(qual) if !is_qualified => format!("{qual}::{name}"),
_ => name.to_owned(),
};
- let mut item = CompletionItem::new(SymbolKind::Attribute, ctx.source_range(), label);
+ let mut item =
+ CompletionItem::new(SymbolKind::Attribute, ctx.source_range(), label, ctx.edition);
item.documentation(Documentation::new(description.to_owned()));
item.add_to(acc, ctx.db)
}
diff --git a/crates/ide-completion/src/completions/attribute/macro_use.rs b/crates/ide-completion/src/completions/attribute/macro_use.rs
index 7e3a62405a..deb12282c0 100644
--- a/crates/ide-completion/src/completions/attribute/macro_use.rs
+++ b/crates/ide-completion/src/completions/attribute/macro_use.rs
@@ -28,7 +28,8 @@ pub(super) fn complete_macro_use(
continue;
}
- let item = CompletionItem::new(SymbolKind::Macro, ctx.source_range(), mac_name);
+ let item =
+ CompletionItem::new(SymbolKind::Macro, ctx.source_range(), mac_name, ctx.edition);
item.add_to(acc, ctx.db);
}
}
diff --git a/crates/ide-completion/src/completions/attribute/repr.rs b/crates/ide-completion/src/completions/attribute/repr.rs
index 14f464b775..12652b4489 100644
--- a/crates/ide-completion/src/completions/attribute/repr.rs
+++ b/crates/ide-completion/src/completions/attribute/repr.rs
@@ -30,7 +30,12 @@ pub(super) fn complete_repr(
continue;
}
- let mut item = CompletionItem::new(SymbolKind::BuiltinAttr, ctx.source_range(), label);
+ let mut item = CompletionItem::new(
+ SymbolKind::BuiltinAttr,
+ ctx.source_range(),
+ label,
+ ctx.edition,
+ );
if let Some(lookup) = lookup {
item.lookup_by(lookup);
}
diff --git a/crates/ide-completion/src/completions/dot.rs b/crates/ide-completion/src/completions/dot.rs
index a07daf4c4e..d55bc3ea5d 100644
--- a/crates/ide-completion/src/completions/dot.rs
+++ b/crates/ide-completion/src/completions/dot.rs
@@ -29,6 +29,7 @@ pub(crate) fn complete_dot(
CompletionItemKind::Keyword,
ctx.source_range(),
SmolStr::new_static("await"),
+ ctx.edition,
);
item.detail("expr.await");
item.add_to(acc, ctx.db);
diff --git a/crates/ide-completion/src/completions/env_vars.rs b/crates/ide-completion/src/completions/env_vars.rs
index 23d93d3b74..c9013d1d17 100644
--- a/crates/ide-completion/src/completions/env_vars.rs
+++ b/crates/ide-completion/src/completions/env_vars.rs
@@ -56,7 +56,7 @@ pub(crate) fn complete_cargo_env_vars(
let range = original.text_range_between_quotes()?;
CARGO_DEFINED_VARS.iter().for_each(|&(var, detail)| {
- let mut item = CompletionItem::new(CompletionItemKind::Keyword, range, var);
+ let mut item = CompletionItem::new(CompletionItemKind::Keyword, range, var, ctx.edition);
item.detail(detail);
item.add_to(acc, ctx.db);
});
diff --git a/crates/ide-completion/src/completions/extern_abi.rs b/crates/ide-completion/src/completions/extern_abi.rs
index b5d5604c75..1a06e0a3a0 100644
--- a/crates/ide-completion/src/completions/extern_abi.rs
+++ b/crates/ide-completion/src/completions/extern_abi.rs
@@ -52,8 +52,13 @@ pub(crate) fn complete_extern_abi(
let abi_str = expanded;
let source_range = abi_str.text_range_between_quotes()?;
for &abi in SUPPORTED_CALLING_CONVENTIONS {
- CompletionItem::new(CompletionItemKind::Keyword, source_range, SmolStr::new_static(abi))
- .add_to(acc, ctx.db);
+ CompletionItem::new(
+ CompletionItemKind::Keyword,
+ source_range,
+ SmolStr::new_static(abi),
+ ctx.edition,
+ )
+ .add_to(acc, ctx.db);
}
Some(())
}
diff --git a/crates/ide-completion/src/completions/extern_crate.rs b/crates/ide-completion/src/completions/extern_crate.rs
index 2427f4e49f..7cb710c2d9 100644
--- a/crates/ide-completion/src/completions/extern_crate.rs
+++ b/crates/ide-completion/src/completions/extern_crate.rs
@@ -19,7 +19,8 @@ pub(crate) fn complete_extern_crate(acc: &mut Completions, ctx: &CompletionConte
let mut item = CompletionItem::new(
CompletionItemKind::SymbolKind(SymbolKind::Module),
ctx.source_range(),
- name.display_no_db().to_smolstr(),
+ name.display_no_db(ctx.edition).to_smolstr(),
+ ctx.edition,
);
item.set_documentation(module.docs(ctx.db));
diff --git a/crates/ide-completion/src/completions/flyimport.rs b/crates/ide-completion/src/completions/flyimport.rs
index fdce7c547a..2a6b310d3a 100644
--- a/crates/ide-completion/src/completions/flyimport.rs
+++ b/crates/ide-completion/src/completions/flyimport.rs
@@ -411,7 +411,7 @@ fn compute_fuzzy_completion_order_key(
cov_mark::hit!(certain_fuzzy_order_test);
let import_name = match proposed_mod_path.segments().last() {
// FIXME: nasty alloc, this is a hot path!
- Some(name) => name.display_no_db().to_smolstr().to_ascii_lowercase(),
+ Some(name) => name.unescaped().display_no_db().to_smolstr().to_ascii_lowercase(),
None => return usize::MAX,
};
match import_name.match_indices(user_input_lowercased).next() {
diff --git a/crates/ide-completion/src/completions/fn_param.rs b/crates/ide-completion/src/completions/fn_param.rs
index a59246229b..ee3b817ee8 100644
--- a/crates/ide-completion/src/completions/fn_param.rs
+++ b/crates/ide-completion/src/completions/fn_param.rs
@@ -32,7 +32,7 @@ pub(crate) fn complete_fn_param(
let comma_wrapper = comma_wrapper(ctx);
let mut add_new_item_to_acc = |label: &str| {
let mk_item = |label: &str, range: TextRange| {
- CompletionItem::new(CompletionItemKind::Binding, range, label)
+ CompletionItem::new(CompletionItemKind::Binding, range, label, ctx.edition)
};
let item = match &comma_wrapper {
Some((fmt, range)) => mk_item(&fmt(label), *range),
@@ -50,7 +50,7 @@ pub(crate) fn complete_fn_param(
ParamKind::Closure(closure) => {
let stmt_list = closure.syntax().ancestors().find_map(ast::StmtList::cast)?;
params_from_stmt_list_scope(ctx, stmt_list, |name, ty| {
- add_new_item_to_acc(&format!("{}: {ty}", name.display(ctx.db)));
+ add_new_item_to_acc(&format!("{}: {ty}", name.display(ctx.db, ctx.edition)));
});
}
}
@@ -101,8 +101,8 @@ fn fill_fn_params(
if let Some(stmt_list) = function.syntax().parent().and_then(ast::StmtList::cast) {
params_from_stmt_list_scope(ctx, stmt_list, |name, ty| {
file_params
- .entry(format!("{}: {ty}", name.display(ctx.db)))
- .or_insert(name.display(ctx.db).to_string());
+ .entry(format!("{}: {ty}", name.display(ctx.db, ctx.edition)))
+ .or_insert(name.display(ctx.db, ctx.edition).to_string());
});
}
remove_duplicated(&mut file_params, param_list.params());
diff --git a/crates/ide-completion/src/completions/format_string.rs b/crates/ide-completion/src/completions/format_string.rs
index 23affc3659..a87c60c694 100644
--- a/crates/ide-completion/src/completions/format_string.rs
+++ b/crates/ide-completion/src/completions/format_string.rs
@@ -35,7 +35,8 @@ pub(crate) fn format_string(
CompletionItem::new(
CompletionItemKind::Binding,
source_range,
- name.display_no_db().to_smolstr(),
+ name.display_no_db(ctx.edition).to_smolstr(),
+ ctx.edition,
)
.add_to(acc, ctx.db);
});
@@ -50,7 +51,8 @@ pub(crate) fn format_string(
CompletionItem::new(
CompletionItemKind::SymbolKind(symbol_kind),
source_range,
- name.display_no_db().to_smolstr(),
+ name.display_no_db(ctx.edition).to_smolstr(),
+ ctx.edition,
)
.add_to(acc, ctx.db);
}
diff --git a/crates/ide-completion/src/completions/item_list/trait_impl.rs b/crates/ide-completion/src/completions/item_list/trait_impl.rs
index 2fd7805e60..fc6e1ebf05 100644
--- a/crates/ide-completion/src/completions/item_list/trait_impl.rs
+++ b/crates/ide-completion/src/completions/item_list/trait_impl.rs
@@ -184,7 +184,7 @@ fn add_function_impl(
let label = format_smolstr!(
"{}fn {}({})",
if is_async { "async " } else { "" },
- fn_name.display(ctx.db),
+ fn_name.display(ctx.db, ctx.edition),
if func.assoc_fn_params(ctx.db).is_empty() { "" } else { ".." }
);
@@ -194,11 +194,11 @@ fn add_function_impl(
SymbolKind::Function
});
- let mut item = CompletionItem::new(completion_kind, replacement_range, label);
+ let mut item = CompletionItem::new(completion_kind, replacement_range, label, ctx.edition);
item.lookup_by(format!(
"{}fn {}",
if is_async { "async " } else { "" },
- fn_name.display(ctx.db)
+ fn_name.display(ctx.db, ctx.edition)
))
.set_documentation(func.docs(ctx.db))
.set_relevance(CompletionRelevance { is_item_from_trait: true, ..Default::default() });
@@ -262,7 +262,8 @@ fn add_type_alias_impl(
let label = format_smolstr!("type {alias_name} =");
- let mut item = CompletionItem::new(SymbolKind::TypeAlias, replacement_range, label);
+ let mut item =
+ CompletionItem::new(SymbolKind::TypeAlias, replacement_range, label, ctx.edition);
item.lookup_by(format!("type {alias_name}"))
.set_documentation(type_alias.docs(ctx.db))
.set_relevance(CompletionRelevance { is_item_from_trait: true, ..Default::default() });
@@ -320,7 +321,7 @@ fn add_const_impl(
const_: hir::Const,
impl_def: hir::Impl,
) {
- let const_name = const_.name(ctx.db).map(|n| n.display_no_db().to_smolstr());
+ let const_name = const_.name(ctx.db).map(|n| n.display_no_db(ctx.edition).to_smolstr());
if let Some(const_name) = const_name {
if let Some(source) = ctx.sema.source(const_) {
@@ -334,7 +335,8 @@ fn add_const_impl(
let label = make_const_compl_syntax(&transformed_const, source.file_id.is_macro());
let replacement = format!("{label} ");
- let mut item = CompletionItem::new(SymbolKind::Const, replacement_range, label);
+ let mut item =
+ CompletionItem::new(SymbolKind::Const, replacement_range, label, ctx.edition);
item.lookup_by(format_smolstr!("const {const_name}"))
.set_documentation(const_.docs(ctx.db))
.set_relevance(CompletionRelevance {
diff --git a/crates/ide-completion/src/completions/lifetime.rs b/crates/ide-completion/src/completions/lifetime.rs
index 03fe93c563..9efc52428e 100644
--- a/crates/ide-completion/src/completions/lifetime.rs
+++ b/crates/ide-completion/src/completions/lifetime.rs
@@ -41,7 +41,7 @@ pub(crate) fn complete_lifetime(
if matches!(
res,
ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_))
- if param_lifetime != Some(&*name.display_no_db().to_smolstr())
+ if param_lifetime != Some(&*name.display_no_db(ctx.edition).to_smolstr())
) {
acc.add_lifetime(ctx, name);
}
diff --git a/crates/ide-completion/src/completions/mod_.rs b/crates/ide-completion/src/completions/mod_.rs
index d9a10893bf..05e2892fdc 100644
--- a/crates/ide-completion/src/completions/mod_.rs
+++ b/crates/ide-completion/src/completions/mod_.rs
@@ -53,7 +53,7 @@ pub(crate) fn complete_mod(
let existing_mod_declarations = current_module
.children(ctx.db)
- .filter_map(|module| Some(module.name(ctx.db)?.display(ctx.db).to_string()))
+ .filter_map(|module| Some(module.name(ctx.db)?.display(ctx.db, ctx.edition).to_string()))
.filter(|module| module != ctx.original_token.text())
.collect::<FxHashSet<_>>();
@@ -99,7 +99,8 @@ pub(crate) fn complete_mod(
if mod_under_caret.semicolon_token().is_none() {
label.push(';');
}
- let item = CompletionItem::new(SymbolKind::Module, ctx.source_range(), &label);
+ let item =
+ CompletionItem::new(SymbolKind::Module, ctx.source_range(), &label, ctx.edition);
item.add_to(acc, ctx.db)
});
@@ -140,7 +141,9 @@ fn directory_to_look_for_submodules(
module_chain_to_containing_module_file(module, db)
.into_iter()
.filter_map(|module| module.name(db))
- .try_fold(base_directory, |path, name| path.join(&name.display_no_db().to_smolstr()))
+ .try_fold(base_directory, |path, name| {
+ path.join(&name.unescaped().display_no_db().to_smolstr())
+ })
}
fn module_chain_to_containing_module_file(
diff --git a/crates/ide-completion/src/completions/postfix.rs b/crates/ide-completion/src/completions/postfix.rs
index 977e0d80a4..a632f14893 100644
--- a/crates/ide-completion/src/completions/postfix.rs
+++ b/crates/ide-completion/src/completions/postfix.rs
@@ -72,7 +72,10 @@ pub(crate) fn complete_postfix(
let mut item = postfix_snippet(
"drop",
"fn drop(&mut self)",
- &format!("{path}($0{receiver_text})", path = path.display(ctx.db)),
+ &format!(
+ "{path}($0{receiver_text})",
+ path = path.display(ctx.db, ctx.edition)
+ ),
);
item.set_documentation(drop_fn.docs(ctx.db));
item.add_to(acc, ctx.db);
@@ -335,8 +338,12 @@ fn build_postfix_snippet_builder<'ctx>(
) -> impl Fn(&str, &str, &str) -> Builder + 'ctx {
move |label, detail, snippet| {
let edit = TextEdit::replace(delete_range, snippet.to_owned());
- let mut item =
- CompletionItem::new(CompletionItemKind::Snippet, ctx.source_range(), label);
+ let mut item = CompletionItem::new(
+ CompletionItemKind::Snippet,
+ ctx.source_range(),
+ label,
+ ctx.edition,
+ );
item.detail(detail).snippet_edit(cap, edit);
let postfix_match = if ctx.original_token.text() == label {
cov_mark::hit!(postfix_exact_match_is_high_priority);
diff --git a/crates/ide-completion/src/completions/record.rs b/crates/ide-completion/src/completions/record.rs
index 1dcf41f8dd..117a5e3d93 100644
--- a/crates/ide-completion/src/completions/record.rs
+++ b/crates/ide-completion/src/completions/record.rs
@@ -73,6 +73,7 @@ pub(crate) fn complete_record_expr_fields(
CompletionItemKind::Snippet,
ctx.source_range(),
SmolStr::new_static(".."),
+ ctx.edition,
);
item.insert_text(".");
item.add_to(acc, ctx.db);
@@ -101,6 +102,7 @@ pub(crate) fn add_default_update(
SymbolKind::Field,
ctx.source_range(),
SmolStr::new_static(completion_text),
+ ctx.edition,
);
let completion_text =
completion_text.strip_prefix(ctx.token.text()).unwrap_or(completion_text);
diff --git a/crates/ide-completion/src/completions/snippet.rs b/crates/ide-completion/src/completions/snippet.rs
index e831113350..357709e0c1 100644
--- a/crates/ide-completion/src/completions/snippet.rs
+++ b/crates/ide-completion/src/completions/snippet.rs
@@ -118,7 +118,8 @@ macro_rules! $1 {
}
fn snippet(ctx: &CompletionContext<'_>, cap: SnippetCap, label: &str, snippet: &str) -> Builder {
- let mut item = CompletionItem::new(CompletionItemKind::Snippet, ctx.source_range(), label);
+ let mut item =
+ CompletionItem::new(CompletionItemKind::Snippet, ctx.source_range(), label, ctx.edition);
item.insert_snippet(cap, snippet);
item
}
diff --git a/crates/ide-completion/src/completions/use_.rs b/crates/ide-completion/src/completions/use_.rs
index 8e5b55360d..45704549e6 100644
--- a/crates/ide-completion/src/completions/use_.rs
+++ b/crates/ide-completion/src/completions/use_.rs
@@ -107,7 +107,11 @@ pub(crate) fn complete_use_path(
let item = CompletionItem::new(
CompletionItemKind::SymbolKind(SymbolKind::Enum),
ctx.source_range(),
- format_smolstr!("{}::", e.name(ctx.db).display(ctx.db)),
+ format_smolstr!(
+ "{}::",
+ e.name(ctx.db).display(ctx.db, ctx.edition)
+ ),
+ ctx.edition,
);
acc.add(item.build(ctx.db));
}
diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs
index 5b64a98a8b..bcd9df9419 100644
--- a/crates/ide-completion/src/context.rs
+++ b/crates/ide-completion/src/context.rs
@@ -437,6 +437,7 @@ pub(crate) struct CompletionContext<'a> {
pub(crate) module: hir::Module,
/// Whether nightly toolchain is used. Cached since this is looked up a lot.
is_nightly: bool,
+ pub(crate) edition: Edition,
/// The expected name of what we are completing.
/// This is usually the parameter name of the function argument we are completing.
@@ -467,9 +468,9 @@ impl CompletionContext<'_> {
cov_mark::hit!(completes_if_lifetime_without_idents);
TextRange::at(self.original_token.text_range().start(), TextSize::from(1))
}
- IDENT | LIFETIME_IDENT | UNDERSCORE | INT_NUMBER => self.original_token.text_range(),
- // FIXME: Edition
- _ if kind.is_keyword(Edition::CURRENT) => self.original_token.text_range(),
+ LIFETIME_IDENT | UNDERSCORE | INT_NUMBER => self.original_token.text_range(),
+ // We want to consider all keywords in all editions.
+ _ if kind.is_any_identifier() => self.original_token.text_range(),
_ => TextRange::empty(self.position.offset),
}
}
@@ -717,6 +718,7 @@ impl<'a> CompletionContext<'a> {
let krate = scope.krate();
let module = scope.module();
+ let edition = krate.edition(db);
let toolchain = db.toolchain_channel(krate.into());
// `toolchain == None` means we're in some detached files. Since we have no information on
@@ -743,6 +745,7 @@ impl<'a> CompletionContext<'a> {
krate,
module,
is_nightly,
+ edition,
expected_name,
expected_type,
qualifier_ctx,
diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs
index 1e972b9b4c..ed359394f1 100644
--- a/crates/ide-completion/src/context/analysis.rs
+++ b/crates/ide-completion/src/context/analysis.rs
@@ -1385,7 +1385,7 @@ fn pattern_context_for(
}).map(|enum_| enum_.variants(sema.db))
})
}).map(|variants| variants.iter().filter_map(|variant| {
- let variant_name = variant.name(sema.db).display(sema.db).to_string();
+ let variant_name = variant.name(sema.db).unescaped().display(sema.db).to_string();
let variant_already_present = match_arm_list.arms().any(|arm| {
arm.pat().and_then(|pat| {
diff --git a/crates/ide-completion/src/item.rs b/crates/ide-completion/src/item.rs
index 3657a7d969..a30a115da1 100644
--- a/crates/ide-completion/src/item.rs
+++ b/crates/ide-completion/src/item.rs
@@ -10,7 +10,7 @@ use ide_db::{
use itertools::Itertools;
use smallvec::SmallVec;
use stdx::{impl_from, never};
-use syntax::{format_smolstr, SmolStr, TextRange, TextSize};
+use syntax::{format_smolstr, Edition, SmolStr, TextRange, TextSize};
use text_edit::TextEdit;
use crate::{
@@ -400,6 +400,7 @@ impl CompletionItem {
kind: impl Into<CompletionItemKind>,
source_range: TextRange,
label: impl Into<SmolStr>,
+ edition: Edition,
) -> Builder {
let label = label.into();
Builder {
@@ -419,6 +420,7 @@ impl CompletionItem {
ref_match: None,
imports_to_add: Default::default(),
doc_aliases: vec![],
+ edition,
}
}
@@ -464,6 +466,7 @@ pub(crate) struct Builder {
trigger_call_info: bool,
relevance: CompletionRelevance,
ref_match: Option<(Mutability, TextSize)>,
+ edition: Edition,
}
impl Builder {
@@ -517,7 +520,7 @@ impl Builder {
label_detail.replace(format_smolstr!(
"{} (use {})",
label_detail.as_deref().unwrap_or_default(),
- import_edit.import_path.display(db)
+ import_edit.import_path.display(db, self.edition)
));
} else if let Some(trait_name) = self.trait_name {
label_detail.replace(format_smolstr!(
@@ -536,8 +539,8 @@ impl Builder {
.into_iter()
.filter_map(|import| {
Some((
- import.import_path.display(db).to_string(),
- import.import_path.segments().last()?.display(db).to_string(),
+ import.import_path.display(db, self.edition).to_string(),
+ import.import_path.segments().last()?.display(db, self.edition).to_string(),
))
})
.collect();
diff --git a/crates/ide-completion/src/lib.rs b/crates/ide-completion/src/lib.rs
index 90c1728074..58d1fad095 100644
--- a/crates/ide-completion/src/lib.rs
+++ b/crates/ide-completion/src/lib.rs
@@ -245,6 +245,7 @@ pub fn resolve_completion_edits(
let current_module = sema.scope(position_for_import)?.module();
let current_crate = current_module.krate();
+ let current_edition = current_crate.edition(db);
let new_ast = scope.clone_for_update();
let mut import_insert = TextEdit::builder();
@@ -261,9 +262,13 @@ pub fn resolve_completion_edits(
.filter_map(|candidate| {
current_module.find_use_path(db, candidate, config.insert_use.prefix_kind, cfg)
})
- .find(|mod_path| mod_path.display(db).to_string() == full_import_path);
+ .find(|mod_path| mod_path.display(db, current_edition).to_string() == full_import_path);
if let Some(import_path) = import {
- insert_use::insert_use(&new_ast, mod_path_to_ast(&import_path), &config.insert_use);
+ insert_use::insert_use(
+ &new_ast,
+ mod_path_to_ast(&import_path, current_edition),
+ &config.insert_use,
+ );
}
});
diff --git a/crates/ide-completion/src/render.rs b/crates/ide-completion/src/render.rs
index 02d667c520..ff5ec3a29f 100644
--- a/crates/ide-completion/src/render.rs
+++ b/crates/ide-completion/src/render.rs
@@ -17,7 +17,7 @@ use ide_db::{
imports::import_assets::LocatedImport,
RootDatabase, SnippetCap, SymbolKind,
};
-use syntax::{ast, format_smolstr, AstNode, SmolStr, SyntaxKind, TextRange, ToSmolStr};
+use syntax::{ast, format_smolstr, AstNode, Edition, SmolStr, SyntaxKind, TextRange, ToSmolStr};
use text_edit::TextEdit;
use crate::{
@@ -133,19 +133,22 @@ pub(crate) fn render_field(
let db = ctx.db();
let is_deprecated = ctx.is_deprecated(field);
let name = field.name(db);
- let (name, escaped_name) =
- (name.unescaped().display(db).to_smolstr(), name.display_no_db().to_smolstr());
+ let (name, escaped_name) = (
+ name.unescaped().display(db).to_smolstr(),
+ name.display_no_db(ctx.completion.edition).to_smolstr(),
+ );
let mut item = CompletionItem::new(
SymbolKind::Field,
ctx.source_range(),
- field_with_receiver(db, receiver.as_ref(), &name),
+ field_with_receiver(db, receiver.as_ref(), &name, ctx.completion.edition),
+ ctx.completion.edition,
);
item.set_relevance(CompletionRelevance {
type_match: compute_type_match(ctx.completion, ty),
exact_name_match: compute_exact_name_match(ctx.completion, name.as_str()),
..CompletionRelevance::default()
});
- item.detail(ty.display(db).to_string())
+ item.detail(ty.display(db, ctx.completion.edition).to_string())
.set_documentation(field.docs(db))
.set_deprecated(is_deprecated)
.lookup_by(name);
@@ -159,7 +162,8 @@ pub(crate) fn render_field(
builder.replace(
ctx.source_range(),
- field_with_receiver(db, receiver.as_ref(), &escaped_name).into(),
+ field_with_receiver(db, receiver.as_ref(), &escaped_name, ctx.completion.edition)
+ .into(),
);
let expected_fn_type =
@@ -183,7 +187,12 @@ pub(crate) fn render_field(
item.text_edit(builder.finish());
} else {
- item.insert_text(field_with_receiver(db, receiver.as_ref(), &escaped_name));
+ item.insert_text(field_with_receiver(
+ db,
+ receiver.as_ref(),
+ &escaped_name,
+ ctx.completion.edition,
+ ));
}
if let Some(receiver) = &dot_access.receiver {
if let Some(original) = ctx.completion.sema.original_ast_node(receiver.clone()) {
@@ -200,10 +209,11 @@ fn field_with_receiver(
db: &RootDatabase,
receiver: Option<&hir::Name>,
field_name: &str,
+ edition: Edition,
) -> SmolStr {
receiver.map_or_else(
|| field_name.into(),
- |receiver| format_smolstr!("{}.{field_name}", receiver.display(db)),
+ |receiver| format_smolstr!("{}.{field_name}", receiver.display(db, edition)),
)
}
@@ -216,9 +226,16 @@ pub(crate) fn render_tuple_field(
let mut item = CompletionItem::new(
SymbolKind::Field,
ctx.source_range(),
- field_with_receiver(ctx.db(), receiver.as_ref(), &field.to_string()),
+ field_with_receiver(
+ ctx.db(),
+ receiver.as_ref(),
+ &field.to_string(),
+ ctx.completion.edition,
+ ),
+ ctx.completion.edition,
);
- item.detail(ty.display(ctx.db()).to_string()).lookup_by(field.to_string());
+ item.detail(ty.display(ctx.db(), ctx.completion.edition).to_string())
+ .lookup_by(field.to_string());
item.build(ctx.db())
}
@@ -226,8 +243,12 @@ pub(crate) fn render_type_inference(
ty_string: String,
ctx: &CompletionContext<'_>,
) -> CompletionItem {
- let mut builder =
- CompletionItem::new(CompletionItemKind::InferredType, ctx.source_range(), ty_string);
+ let mut builder = CompletionItem::new(
+ CompletionItemKind::InferredType,
+ ctx.source_range(),
+ ty_string,
+ ctx.edition,
+ );
builder.set_relevance(CompletionRelevance { is_definite: true, ..Default::default() });
builder.build(ctx.db)
}
@@ -296,7 +317,7 @@ pub(crate) fn render_expr(
let cfg = ctx.config.import_path_config();
- let label = expr.gen_source_code(&ctx.scope, &mut label_formatter, cfg).ok()?;
+ let label = expr.gen_source_code(&ctx.scope, &mut label_formatter, cfg, ctx.edition).ok()?;
let source_range = match ctx.original_token.parent() {
Some(node) => match node.ancestors().find_map(ast::Path::cast) {
@@ -306,10 +327,13 @@ pub(crate) fn render_expr(
None => ctx.source_range(),
};
- let mut item = CompletionItem::new(CompletionItemKind::Expression, source_range, label);
+ let mut item =
+ CompletionItem::new(CompletionItemKind::Expression, source_range, label, ctx.edition);
- let snippet =
- format!("{}$0", expr.gen_source_code(&ctx.scope, &mut snippet_formatter, cfg).ok()?);
+ let snippet = format!(
+ "{}$0",
+ expr.gen_source_code(&ctx.scope, &mut snippet_formatter, cfg, ctx.edition).ok()?
+ );
let edit = TextEdit::replace(source_range, snippet);
item.snippet_edit(ctx.config.snippet_cap?, edit);
item.documentation(Documentation::new(String::from("Autogenerated expression by term search")));
@@ -396,10 +420,10 @@ fn render_resolution_path(
let config = completion.config;
let requires_import = import_to_add.is_some();
- let name = local_name.display_no_db().to_smolstr();
+ let name = local_name.display_no_db(ctx.completion.edition).to_smolstr();
let mut item = render_resolution_simple_(ctx, &local_name, import_to_add, resolution);
- if local_name.is_escaped() {
- item.insert_text(local_name.display_no_db().to_smolstr());
+ if local_name.is_escaped(completion.edition) {
+ item.insert_text(local_name.display_no_db(completion.edition).to_smolstr());
}
// Add `<>` for generic types
let type_path_no_ty_args = matches!(
@@ -421,14 +445,17 @@ fn render_resolution_path(
item.lookup_by(name.clone())
.label(SmolStr::from_iter([&name, "<…>"]))
.trigger_call_info()
- .insert_snippet(cap, format!("{}<$0>", local_name.display(db)));
+ .insert_snippet(
+ cap,
+ format!("{}<$0>", local_name.display(db, completion.edition)),
+ );
}
}
}
let mut set_item_relevance = |ty: Type| {
if !ty.is_unknown() {
- item.detail(ty.display(db).to_string());
+ item.detail(ty.display(db, completion.edition).to_string());
}
item.set_relevance(CompletionRelevance {
@@ -485,6 +512,7 @@ fn render_resolution_simple_(
kind,
ctx.source_range(),
local_name.unescaped().display(db).to_smolstr(),
+ ctx.completion.edition,
);
item.set_relevance(ctx.completion_relevance())
.set_documentation(scope_def_docs(db, resolution))
diff --git a/crates/ide-completion/src/render/const_.rs b/crates/ide-completion/src/render/const_.rs
index 3bfec0de6b..415d87c623 100644
--- a/crates/ide-completion/src/render/const_.rs
+++ b/crates/ide-completion/src/render/const_.rs
@@ -14,11 +14,14 @@ pub(crate) fn render_const(ctx: RenderContext<'_>, const_: hir::Const) -> Option
fn render(ctx: RenderContext<'_>, const_: hir::Const) -> Option<CompletionItem> {
let db = ctx.db();
let name = const_.name(db)?;
- let (name, escaped_name) =
- (name.unescaped().display(db).to_smolstr(), name.display(db).to_smolstr());
- let detail = const_.display(db).to_string();
+ let (name, escaped_name) = (
+ name.unescaped().display(db).to_smolstr(),
+ name.display(db, ctx.completion.edition).to_smolstr(),
+ );
+ let detail = const_.display(db, ctx.completion.edition).to_string();
- let mut item = CompletionItem::new(SymbolKind::Const, ctx.source_range(), name);
+ let mut item =
+ CompletionItem::new(SymbolKind::Const, ctx.source_range(), name, ctx.completion.edition);
item.set_documentation(ctx.docs(const_))
.set_deprecated(ctx.is_deprecated(const_) || ctx.is_deprecated_assoc_item(const_))
.detail(detail)
@@ -26,7 +29,7 @@ fn render(ctx: RenderContext<'_>, const_: hir::Const) -> Option<CompletionItem>
if let Some(actm) = const_.as_assoc_item(db) {
if let Some(trt) = actm.container_or_implemented_trait(db) {
- item.trait_name(trt.name(db).display_no_db().to_smolstr());
+ item.trait_name(trt.name(db).display_no_db(ctx.completion.edition).to_smolstr());
}
}
item.insert_text(escaped_name);
diff --git a/crates/ide-completion/src/render/function.rs b/crates/ide-completion/src/render/function.rs
index 05b2d0ae38..74092b53f5 100644
--- a/crates/ide-completion/src/render/function.rs
+++ b/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, SmolStr, ToSmolStr};
+use syntax::{format_smolstr, AstNode, Edition, SmolStr, ToSmolStr};
use crate::{
context::{CompletionContext, DotAccess, DotAccessKind, PathCompletionCtx, PathKind},
@@ -62,9 +62,16 @@ fn render(
receiver.unescaped().display(ctx.db()),
name.unescaped().display(ctx.db())
),
- format_smolstr!("{}.{}", receiver.display(ctx.db()), name.display(ctx.db())),
+ format_smolstr!(
+ "{}.{}",
+ receiver.display(ctx.db(), completion.edition),
+ name.display(ctx.db(), completion.edition)
+ ),
+ ),
+ _ => (
+ name.unescaped().display(db).to_smolstr(),
+ name.display(db, completion.edition).to_smolstr(),
),
- _ => (name.unescaped().display(db).to_smolstr(), name.display(db).to_smolstr()),
};
let has_self_param = func.self_param(db).is_some();
let mut item = CompletionItem::new(
@@ -75,6 +82,7 @@ fn render(
}),
ctx.source_range(),
call.clone(),
+ completion.edition,
);
let ret_type = func.ret_type(db);
@@ -141,9 +149,9 @@ fn render(
}
let detail = if ctx.completion.config.full_function_signatures {
- detail_full(db, func)
+ detail_full(db, func, ctx.completion.edition)
} else {
- detail(db, func)
+ detail(db, func, ctx.completion.edition)
};
item.set_documentation(ctx.docs(func))
.set_deprecated(ctx.is_deprecated(func) || ctx.is_deprecated_assoc_item(func))
@@ -161,7 +169,9 @@ fn render(
None => {
if let Some(actm) = assoc_item {
if let Some(trt) = actm.container_or_implemented_trait(db) {
- item.trait_name(trt.name(db).display_no_db().to_smolstr());
+ item.trait_name(
+ trt.name(db).display_no_db(ctx.completion.edition).to_smolstr(),
+ );
}
}
}
@@ -219,7 +229,7 @@ pub(super) fn add_call_parens<'b>(
params.iter().enumerate().format_with(", ", |(index, param), f| {
match param.name(ctx.db) {
Some(n) => {
- let smol_str = n.display_no_db().to_smolstr();
+ let smol_str = n.display_no_db(ctx.edition).to_smolstr();
let text = smol_str.as_str().trim_start_matches('_');
let ref_ = ref_of_param(ctx, text, param.ty());
f(&format_args!("${{{}:{ref_}{text}}}", index + offset))
@@ -238,7 +248,7 @@ pub(super) fn add_call_parens<'b>(
format!(
"{}(${{1:{}}}{}{})$0",
escaped_name,
- self_param.display(ctx.db),
+ self_param.display(ctx.db, ctx.edition),
if params.is_empty() { "" } else { ", " },
function_params_snippet
)
@@ -276,7 +286,7 @@ fn ref_of_param(ctx: &CompletionContext<'_>, arg: &str, ty: &hir::Type) -> &'sta
""
}
-fn detail(db: &dyn HirDatabase, func: hir::Function) -> String {
+fn detail(db: &dyn HirDatabase, func: hir::Function, edition: Edition) -> String {
let mut ret_ty = func.ret_type(db);
let mut detail = String::new();
@@ -293,15 +303,15 @@ fn detail(db: &dyn HirDatabase, func: hir::Function) -> String {
format_to!(detail, "unsafe ");
}
- format_to!(detail, "fn({})", params_display(db, func));
+ format_to!(detail, "fn({})", params_display(db, func, edition));
if !ret_ty.is_unit() {
- format_to!(detail, " -> {}", ret_ty.display(db));
+ format_to!(detail, " -> {}", ret_ty.display(db, edition));
}
detail
}
-fn detail_full(db: &dyn HirDatabase, func: hir::Function) -> String {
- let signature = format!("{}", func.display(db));
+fn detail_full(db: &dyn HirDatabase, func: hir::Function, edition: Edition) -> String {
+ let signature = format!("{}", func.display(db, edition));
let mut detail = String::with_capacity(signature.len());
for segment in signature.split_whitespace() {
@@ -315,16 +325,16 @@ fn detail_full(db: &dyn HirDatabase, func: hir::Function) -> String {
detail
}
-fn params_display(db: &dyn HirDatabase, func: hir::Function) -> String {
+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);
let params = assoc_fn_params
.iter()
.skip(1) // skip the self param because we are manually handling that
- .map(|p| p.ty().display(db));
+ .map(|p| p.ty().display(db, edition));
format!(
"{}{}",
- self_param.display(db),
+ self_param.display(db, edition),
params.format_with("", |display, f| {
f(&", ")?;
f(&display)
@@ -332,7 +342,7 @@ fn params_display(db: &dyn HirDatabase, func: hir::Function) -> String {
)
} else {
let assoc_fn_params = func.assoc_fn_params(db);
- assoc_fn_params.iter().map(|p| p.ty().display(db)).join(", ")
+ assoc_fn_params.iter().map(|p| p.ty().display(db, edition)).join(", ")
}
}
diff --git a/crates/ide-completion/src/render/literal.rs b/crates/ide-completion/src/render/literal.rs
index 27435307d5..c71356e530 100644
--- a/crates/ide-completion/src/render/literal.rs
+++ b/crates/ide-completion/src/render/literal.rs
@@ -76,16 +76,16 @@ fn render(
};
let (qualified_name, escaped_qualified_name) = (
qualified_name.unescaped().display(ctx.db()).to_string(),
- qualified_name.display(ctx.db()).to_string(),
+ qualified_name.display(ctx.db(), completion.edition).to_string(),
);
let snippet_cap = ctx.snippet_cap();
let mut rendered = match kind {
StructKind::Tuple if should_add_parens => {
- render_tuple_lit(db, snippet_cap, &fields, &escaped_qualified_name)
+ render_tuple_lit(db, snippet_cap, &fields, &escaped_qualified_name, completion.edition)
}
StructKind::Record if should_add_parens => {
- render_record_lit(db, snippet_cap, &fields, &escaped_qualified_name)
+ render_record_lit(db, snippet_cap, &fields, &escaped_qualified_name, completion.edition)
}
_ => RenderedLiteral {
literal: escaped_qualified_name.clone(),
@@ -103,7 +103,10 @@ fn render(
}
let label = format_literal_label(&qualified_name, kind, snippet_cap);
let lookup = if qualified {
- format_literal_lookup(&short_qualified_name.display(ctx.db()).to_string(), kind)
+ format_literal_lookup(
+ &short_qualified_name.display(ctx.db(), completion.edition).to_string(),
+ kind,
+ )
} else {
format_literal_lookup(&qualified_name, kind)
};
@@ -112,6 +115,7 @@ fn render(
CompletionItemKind::SymbolKind(thing.symbol_kind()),
ctx.source_range(),
label,
+ completion.edition,
);
item.lookup_by(lookup);
diff --git a/crates/ide-completion/src/render/macro_.rs b/crates/ide-completion/src/render/macro_.rs
index de715bcbfa..6490171fbb 100644
--- a/crates/ide-completion/src/render/macro_.rs
+++ b/crates/ide-completion/src/render/macro_.rs
@@ -46,8 +46,10 @@ fn render(
ctx.source_range()
};
- let (name, escaped_name) =
- (name.unescaped().display(ctx.db()).to_smolstr(), name.display(ctx.db()).to_smolstr());
+ let (name, escaped_name) = (
+ name.unescaped().display(ctx.db()).to_smolstr(),
+ name.display(ctx.db(), completion.edition).to_smolstr(),
+ );
let docs = ctx.docs(macro_);
let docs_str = docs.as_ref().map(Documentation::as_str).unwrap_or_default();
let is_fn_like = macro_.is_fn_like(completion.db);
@@ -59,9 +61,10 @@ fn render(
SymbolKind::from(macro_.kind(completion.db)),
source_range,
label(&ctx, needs_bang, bra, ket, &name),
+ completion.edition,
);
item.set_deprecated(ctx.is_deprecated(macro_))
- .detail(macro_.display(completion.db).to_string())
+ .detail(macro_.display(completion.db, completion.edition).to_string())
.set_documentation(docs)
.set_relevance(ctx.completion_relevance());
diff --git a/crates/ide-completion/src/render/pattern.rs b/crates/ide-completion/src/render/pattern.rs
index 598b8762b6..5675dfb5c6 100644
--- a/crates/ide-completion/src/render/pattern.rs
+++ b/crates/ide-completion/src/render/pattern.rs
@@ -3,7 +3,7 @@
use hir::{db::HirDatabase, Name, StructKind};
use ide_db::{documentation::HasDocs, SnippetCap};
use itertools::Itertools;
-use syntax::{SmolStr, ToSmolStr};
+use syntax::{Edition, SmolStr, ToSmolStr};
use crate::{
context::{ParamContext, ParamKind, PathCompletionCtx, PatternContext},
@@ -31,8 +31,10 @@ pub(crate) fn render_struct_pat(
}
let name = local_name.unwrap_or_else(|| strukt.name(ctx.db()));
- let (name, escaped_name) =
- (name.unescaped().display(ctx.db()).to_smolstr(), name.display(ctx.db()).to_smolstr());
+ let (name, escaped_name) = (
+ name.unescaped().display(ctx.db()).to_smolstr(),
+ name.display(ctx.db(), ctx.completion.edition).to_smolstr(),
+ );
let kind = strukt.kind(ctx.db());
let label = format_literal_label(name.as_str(), kind, ctx.snippet_cap());
let lookup = format_literal_lookup(name.as_str(), kind);
@@ -60,13 +62,13 @@ pub(crate) fn render_variant_pat(
let (name, escaped_name) = match path {
Some(path) => (
path.unescaped().display(ctx.db()).to_string().into(),
- path.display(ctx.db()).to_string().into(),
+ path.display(ctx.db(), ctx.completion.edition).to_string().into(),
),
None => {
let name = local_name.unwrap_or_else(|| variant.name(ctx.db()));
let it = (
name.unescaped().display(ctx.db()).to_smolstr(),
- name.display(ctx.db()).to_smolstr(),
+ name.display(ctx.db(), ctx.completion.edition).to_smolstr(),
);
it
}
@@ -119,7 +121,12 @@ fn build_completion(
relevance.type_match = super::compute_type_match(ctx.completion, &adt_ty);
}
- let mut item = CompletionItem::new(CompletionItemKind::Binding, ctx.source_range(), label);
+ let mut item = CompletionItem::new(
+ CompletionItemKind::Binding,
+ ctx.source_range(),
+ label,
+ ctx.completion.edition,
+ );
item.set_documentation(ctx.docs(def))
.set_deprecated(ctx.is_deprecated(def))
.detail(&pat)
@@ -142,9 +149,14 @@ fn render_pat(
) -> Option<String> {
let mut pat = match kind {
StructKind::Tuple => render_tuple_as_pat(ctx.snippet_cap(), fields, name, fields_omitted),
- StructKind::Record => {
- render_record_as_pat(ctx.db(), ctx.snippet_cap(), fields, name, fields_omitted)
- }
+ StructKind::Record => render_record_as_pat(
+ ctx.db(),
+ ctx.snippet_cap(),
+ fields,
+ name,
+ fields_omitted,
+ ctx.completion.edition,
+ ),
StructKind::Unit => name.to_owned(),
};
@@ -173,6 +185,7 @@ fn render_record_as_pat(
fields: &[hir::Field],
name: &str,
fields_omitted: bool,
+ edition: Edition,
) -> String {
let fields = fields.iter();
match snippet_cap {
@@ -180,7 +193,7 @@ fn render_record_as_pat(
format!(
"{name} {{ {}{} }}",
fields.enumerate().format_with(", ", |(idx, field), f| {
- f(&format_args!("{}${}", field.name(db).display(db.upcast()), idx + 1))
+ f(&format_args!("{}${}", field.name(db).display(db.upcast(), edition), idx + 1))
}),
if fields_omitted { ", .." } else { "" },
name = name
@@ -189,7 +202,7 @@ fn render_record_as_pat(
None => {
format!(
"{name} {{ {}{} }}",
- fields.map(|field| field.name(db).display_no_db().to_smolstr()).format(", "),
+ fields.map(|field| field.name(db).display_no_db(edition).to_smolstr()).format(", "),
if fields_omitted { ", .." } else { "" },
name = name
)
diff --git a/crates/ide-completion/src/render/type_alias.rs b/crates/ide-completion/src/render/type_alias.rs
index b81caf2422..09eb19201c 100644
--- a/crates/ide-completion/src/render/type_alias.rs
+++ b/crates/ide-completion/src/render/type_alias.rs
@@ -33,14 +33,22 @@ fn render(
let (name, escaped_name) = if with_eq {
(
SmolStr::from_iter([&name.unescaped().display(db).to_smolstr(), " = "]),
- SmolStr::from_iter([&name.display_no_db().to_smolstr(), " = "]),
+ SmolStr::from_iter([&name.display_no_db(ctx.completion.edition).to_smolstr(), " = "]),
)
} else {
- (name.unescaped().display(db).to_smolstr(), name.display_no_db().to_smolstr())
+ (
+ name.unescaped().display(db).to_smolstr(),
+ name.display_no_db(ctx.completion.edition).to_smolstr(),
+ )
};
- let detail = type_alias.display(db).to_string();
+ let detail = type_alias.display(db, ctx.completion.edition).to_string();
- let mut item = CompletionItem::new(SymbolKind::TypeAlias, ctx.source_range(), name);
+ let mut item = CompletionItem::new(
+ SymbolKind::TypeAlias,
+ ctx.source_range(),
+ name,
+ ctx.completion.edition,
+ );
item.set_documentation(ctx.docs(type_alias))
.set_deprecated(ctx.is_deprecated(type_alias) || ctx.is_deprecated_assoc_item(type_alias))
.detail(detail)
@@ -48,7 +56,7 @@ fn render(
if let Some(actm) = type_alias.as_assoc_item(db) {
if let Some(trt) = actm.container_or_implemented_trait(db) {
- item.trait_name(trt.name(db).display_no_db().to_smolstr());
+ item.trait_name(trt.name(db).display_no_db(ctx.completion.edition).to_smolstr());
}
}
item.insert_text(escaped_name);
diff --git a/crates/ide-completion/src/render/union_literal.rs b/crates/ide-completion/src/render/union_literal.rs
index ca7593c122..e053e299d9 100644
--- a/crates/ide-completion/src/render/union_literal.rs
+++ b/crates/ide-completion/src/render/union_literal.rs
@@ -22,21 +22,29 @@ pub(crate) fn render_union_literal(
let name = local_name.unwrap_or_else(|| un.name(ctx.db()));
let (qualified_name, escaped_qualified_name) = match path {
- Some(p) => (p.unescaped().display(ctx.db()).to_string(), p.display(ctx.db()).to_string()),
- None => {
- (name.unescaped().display(ctx.db()).to_string(), name.display(ctx.db()).to_string())
- }
+ Some(p) => (
+ p.unescaped().display(ctx.db()).to_string(),
+ p.display(ctx.db(), ctx.completion.edition).to_string(),
+ ),
+ None => (
+ name.unescaped().display(ctx.db()).to_string(),
+ name.display(ctx.db(), ctx.completion.edition).to_string(),
+ ),
};
let label = format_literal_label(
- &name.display_no_db().to_smolstr(),
+ &name.display_no_db(ctx.completion.edition).to_smolstr(),
StructKind::Record,
ctx.snippet_cap(),
);
- let lookup = format_literal_lookup(&name.display_no_db().to_smolstr(), StructKind::Record);
+ let lookup = format_literal_lookup(
+ &name.display_no_db(ctx.completion.edition).to_smolstr(),
+ StructKind::Record,
+ );
let mut item = CompletionItem::new(
CompletionItemKind::SymbolKind(SymbolKind::Union),
ctx.source_range(),
label,
+ ctx.completion.edition,
);
item.lookup_by(lookup);
@@ -54,7 +62,10 @@ pub(crate) fn render_union_literal(
escaped_qualified_name,
fields
.iter()
- .map(|field| field.name(ctx.db()).display_no_db().to_smolstr())
+ .map(|field| field
+ .name(ctx.db())
+ .display_no_db(ctx.completion.edition)
+ .to_smolstr())
.format(",")
)
} else {
@@ -62,7 +73,10 @@ pub(crate) fn render_union_literal(
"{} {{ {} }}",
escaped_qualified_name,
fields.iter().format_with(", ", |field, f| {
- f(&format_args!("{}: ()", field.name(ctx.db()).display(ctx.db())))
+ f(&format_args!(
+ "{}: ()",
+ field.name(ctx.db()).display(ctx.db(), ctx.completion.edition)
+ ))
})
)
};
@@ -73,8 +87,8 @@ pub(crate) fn render_union_literal(
fields.iter().format_with(", ", |field, f| {
f(&format_args!(
"{}: {}",
- field.name(ctx.db()).display(ctx.db()),
- field.ty(ctx.db()).display(ctx.db())
+ field.name(ctx.db()).display(ctx.db(), ctx.completion.edition),
+ field.ty(ctx.db()).display(ctx.db(), ctx.completion.edition)
))
}),
if fields_omitted { ", .." } else { "" }
diff --git a/crates/ide-completion/src/render/variant.rs b/crates/ide-completion/src/render/variant.rs
index bc2df9e39f..d8516ea107 100644
--- a/crates/ide-completion/src/render/variant.rs
+++ b/crates/ide-completion/src/render/variant.rs
@@ -4,7 +4,7 @@ use crate::context::CompletionContext;
use hir::{db::HirDatabase, sym, HasAttrs, HasCrate, HasVisibility, HirDisplay, StructKind};
use ide_db::SnippetCap;
use itertools::Itertools;
-use syntax::SmolStr;
+use syntax::{Edition, SmolStr};
/// A rendered struct, union, or enum variant, split into fields for actual
/// auto-completion (`literal`, using `field: ()`) and display in the
@@ -21,20 +21,29 @@ pub(crate) fn render_record_lit(
snippet_cap: Option<SnippetCap>,
fields: &[hir::Field],
path: &str,
+ edition: Edition,
) -> RenderedLiteral {
if snippet_cap.is_none() {
return RenderedLiteral { literal: path.to_owned(), detail: path.to_owned() };
}
let completions = fields.iter().enumerate().format_with(", ", |(idx, field), f| {
if snippet_cap.is_some() {
- f(&format_args!("{}: ${{{}:()}}", field.name(db).display(db.upcast()), idx + 1))
+ f(&format_args!(
+ "{}: ${{{}:()}}",
+ field.name(db).display(db.upcast(), edition),
+ idx + 1
+ ))
} else {
- f(&format_args!("{}: ()", field.name(db).display(db.upcast())))
+ f(&format_args!("{}: ()", field.name(db).display(db.upcast(), edition)))
}
});
let types = fields.iter().format_with(", ", |field, f| {
- f(&format_args!("{}: {}", field.name(db).display(db.upcast()), field.ty(db).display(db)))
+ f(&format_args!(
+ "{}: {}",
+ field.name(db).display(db.upcast(), edition),
+ field.ty(db).display(db, edition)
+ ))
});
RenderedLiteral {
@@ -50,6 +59,7 @@ pub(crate) fn render_tuple_lit(
snippet_cap: Option<SnippetCap>,
fields: &[hir::Field],
path: &str,
+ edition: Edition,
) -> RenderedLiteral {
if snippet_cap.is_none() {
return RenderedLiteral { literal: path.to_owned(), detail: path.to_owned() };
@@ -62,7 +72,7 @@ pub(crate) fn render_tuple_lit(
}
});
- let types = fields.iter().format_with(", ", |field, f| f(&field.ty(db).display(db)));
+ let types = fields.iter().format_with(", ", |field, f| f(&field.ty(db).display(db, edition)));
RenderedLiteral {
literal: format!("{path}({completions})"),
diff --git a/crates/ide-completion/src/tests.rs b/crates/ide-completion/src/tests.rs
index 415f2afeeb..04ba7e1f41 100644
--- a/crates/ide-completion/src/tests.rs
+++ b/crates/ide-completion/src/tests.rs
@@ -17,6 +17,7 @@ mod item_list;
mod pattern;
mod predicate;
mod proc_macros;
+mod raw_identifiers;
mod record;
mod special;
mod type_pos;
@@ -105,22 +106,35 @@ pub(crate) fn completion_list_with_trigger_character(
completion_list_with_config(TEST_CONFIG, ra_fixture, true, trigger_character)
}
-fn completion_list_with_config(
+fn completion_list_with_config_raw(
config: CompletionConfig,
ra_fixture: &str,
include_keywords: bool,
trigger_character: Option<char>,
-) -> String {
+) -> Vec<CompletionItem> {
// filter out all but one built-in type completion for smaller test outputs
let items = get_all_items(config, ra_fixture, trigger_character);
- let items = items
+ items
.into_iter()
.filter(|it| it.kind != CompletionItemKind::BuiltinType || it.label == "u32")
.filter(|it| include_keywords || it.kind != CompletionItemKind::Keyword)
.filter(|it| include_keywords || it.kind != CompletionItemKind::Snippet)
.sorted_by_key(|it| (it.kind, it.label.clone(), it.detail.as_ref().map(ToOwned::to_owned)))
- .collect();
- render_completion_list(items)
+ .collect()
+}
+
+fn completion_list_with_config(
+ config: CompletionConfig,
+ ra_fixture: &str,
+ include_keywords: bool,
+ trigger_character: Option<char>,
+) -> String {
+ render_completion_list(completion_list_with_config_raw(
+ config,
+ ra_fixture,
+ include_keywords,
+ trigger_character,
+ ))
}
/// Creates analysis from a multi-file fixture, returns positions marked with $0.
diff --git a/crates/ide-completion/src/tests/raw_identifiers.rs b/crates/ide-completion/src/tests/raw_identifiers.rs
new file mode 100644
index 0000000000..bc630189ed
--- /dev/null
+++ b/crates/ide-completion/src/tests/raw_identifiers.rs
@@ -0,0 +1,84 @@
+use base_db::SourceDatabase;
+use expect_test::{expect, Expect};
+use itertools::Itertools;
+
+use crate::tests::{completion_list_with_config_raw, position, TEST_CONFIG};
+
+fn check(ra_fixture: &str, expect: Expect) {
+ let completions = completion_list_with_config_raw(TEST_CONFIG, ra_fixture, true, None);
+ let (db, position) = position(ra_fixture);
+ let mut actual = db.file_text(position.file_id).to_string();
+ completions
+ .into_iter()
+ .exactly_one()
+ .expect("more than one completion")
+ .text_edit
+ .apply(&mut actual);
+ expect.assert_eq(&actual);
+}
+
+#[test]
+fn keyword_since_edition_completes_without_raw_on_old_edition() {
+ check(
+ r#"
+//- /a.rs crate:a edition:2015
+pub fn dyn() {}
+
+//- /b.rs crate:b edition:2015 deps:a new_source_root:local
+fn foo() {
+ a::dyn$0
+"#,
+ expect![[r#"
+ fn foo() {
+ a::dyn()$0
+ "#]],
+ );
+
+ check(
+ r#"
+//- /a.rs crate:a edition:2018
+pub fn r#dyn() {}
+
+//- /b.rs crate:b edition:2015 deps:a new_source_root:local
+fn foo() {
+ a::dyn$0
+"#,
+ expect![[r#"
+ fn foo() {
+ a::dyn()$0
+ "#]],
+ );
+}
+
+#[test]
+fn keyword_since_edition_completes_with_raw_on_new_edition() {
+ check(
+ r#"
+//- /a.rs crate:a edition:2015
+pub fn dyn() {}
+
+//- /b.rs crate:b edition:2018 deps:a new_source_root:local
+fn foo() {
+ a::dyn$0
+"#,
+ expect![[r#"
+ fn foo() {
+ a::r#dyn()$0
+ "#]],
+ );
+
+ check(
+ r#"
+//- /a.rs crate:a edition:2018
+pub fn r#dyn() {}
+
+//- /b.rs crate:b edition:2018 deps:a new_source_root:local
+fn foo() {
+ a::dyn$0
+"#,
+ expect![[r#"
+ fn foo() {
+ a::r#dyn()$0
+ "#]],
+ );
+}
diff --git a/crates/ide-db/src/defs.rs b/crates/ide-db/src/defs.rs
index 991bef344a..5d4b199908 100644
--- a/crates/ide-db/src/defs.rs
+++ b/crates/ide-db/src/defs.rs
@@ -14,10 +14,11 @@ use hir::{
ModuleDef, Name, PathResolution, Semantics, Static, StaticLifetime, ToolModule, Trait,
TraitAlias, TupleField, TypeAlias, Variant, VariantDef, Visibility,
};
+use span::Edition;
use stdx::{format_to, impl_from};
use syntax::{
ast::{self, AstNode},
- match_ast, SyntaxKind, SyntaxNode, SyntaxToken, ToSmolStr,
+ match_ast, SyntaxKind, SyntaxNode, SyntaxToken,
};
use crate::documentation::{Documentation, HasDocs};
@@ -157,6 +158,7 @@ impl Definition {
&self,
db: &RootDatabase,
famous_defs: Option<&FamousDefs<'_, '_>>,
+ edition: Edition,
) -> Option<Documentation> {
let docs = match self {
Definition::Macro(it) => it.docs(db),
@@ -173,8 +175,8 @@ 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));
- let doc_owner = find_std_module(fd, &primitive_mod)?;
+ let primitive_mod = format!("prim_{}", it.name().display(fd.0.db, edition));
+ let doc_owner = find_std_module(fd, &primitive_mod, edition)?;
doc_owner.docs(fd.0.db)
})
}
@@ -192,13 +194,18 @@ 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));
+ format_to!(docs, "\n - #\\[{}]", name.display(db, edition));
}
if let Some(list) = list {
- format_to!(docs, "\n - #\\[{}({})]", name.display(db), list);
+ format_to!(docs, "\n - #\\[{}({})]", name.display(db, edition), list);
}
if let Some(name_value_str) = name_value_str {
- format_to!(docs, "\n - #\\[{} = {}]", name.display(db), name_value_str);
+ format_to!(
+ docs,
+ "\n - #\\[{} = {}]",
+ name.display(db, edition),
+ name_value_str
+ );
}
Some(Documentation::new(docs.replace('*', "\\*")))
}
@@ -218,57 +225,63 @@ impl Definition {
})
}
- pub fn label(&self, db: &RootDatabase) -> String {
+ pub fn label(&self, db: &RootDatabase, edition: Edition) -> String {
match *self {
- Definition::Macro(it) => it.display(db).to_string(),
- Definition::Field(it) => it.display(db).to_string(),
- Definition::TupleField(it) => it.display(db).to_string(),
- Definition::Module(it) => it.display(db).to_string(),
- Definition::Function(it) => it.display(db).to_string(),
- Definition::Adt(it) => it.display(db).to_string(),
- Definition::Variant(it) => it.display(db).to_string(),
- Definition::Const(it) => it.display(db).to_string(),
- Definition::Static(it) => it.display(db).to_string(),
- Definition::Trait(it) => it.display(db).to_string(),
- Definition::TraitAlias(it) => it.display(db).to_string(),
- Definition::TypeAlias(it) => it.display(db).to_string(),
- Definition::BuiltinType(it) => it.name().display(db).to_string(),
- Definition::BuiltinLifetime(it) => it.name().display(db).to_string(),
+ 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::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::Local(it) => {
let ty = it.ty(db);
- let ty_display = ty.display_truncated(db, None);
+ let ty_display = ty.display_truncated(db, None, edition);
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))
+ format!("{let_kw}{is_mut}{}: {ty_display}", name.display(db, edition))
}
}
Definition::SelfType(impl_def) => {
let self_ty = &impl_def.self_ty(db);
match self_ty.as_adt() {
- Some(it) => it.display(db).to_string(),
- None => self_ty.display(db).to_string(),
+ Some(it) => it.display(db, edition).to_string(),
+ None => self_ty.display(db, edition).to_string(),
}
}
- Definition::GenericParam(it) => it.display(db).to_string(),
- Definition::Label(it) => it.name(db).display(db).to_string(),
- Definition::ExternCrateDecl(it) => it.display(db).to_string(),
- Definition::BuiltinAttr(it) => format!("#[{}]", it.name(db).display(db)),
- Definition::ToolModule(it) => it.name(db).display(db).to_string(),
- Definition::DeriveHelper(it) => format!("derive_helper {}", it.name(db).display(db)),
+ 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::DeriveHelper(it) => {
+ format!("derive_helper {}", it.name(db).display(db, edition))
+ }
}
}
}
-fn find_std_module(famous_defs: &FamousDefs<'_, '_>, name: &str) -> Option<hir::Module> {
+fn find_std_module(
+ famous_defs: &FamousDefs<'_, '_>,
+ name: &str,
+ edition: Edition,
+) -> Option<hir::Module> {
let db = famous_defs.0.db;
let std_crate = famous_defs.std()?;
let std_root_module = std_crate.root_module();
std_root_module.children(db).find(|module| {
- module.name(db).map_or(false, |module| module.display(db).to_string() == name)
+ module.name(db).map_or(false, |module| module.display(db, edition).to_string() == name)
})
}
@@ -670,7 +683,7 @@ impl NameRefClass {
hir::AssocItem::TypeAlias(it) => Some(it),
_ => None,
})
- .find(|alias| alias.name(sema.db).display_no_db().to_smolstr() == name_ref.text().as_str())
+ .find(|alias| alias.name(sema.db).eq_ident(name_ref.text().as_str()))
{
return Some(NameRefClass::Definition(Definition::TypeAlias(ty)));
}
diff --git a/crates/ide-db/src/famous_defs.rs b/crates/ide-db/src/famous_defs.rs
index 1a16a567f3..ba6e50abf6 100644
--- a/crates/ide-db/src/famous_defs.rs
+++ b/crates/ide-db/src/famous_defs.rs
@@ -2,7 +2,6 @@
use base_db::{CrateOrigin, LangCrateOrigin, SourceDatabase};
use hir::{Crate, Enum, Function, Macro, Module, ScopeDef, Semantics, Trait};
-use syntax::ToSmolStr;
use crate::RootDatabase;
@@ -199,18 +198,14 @@ impl FamousDefs<'_, '_> {
for segment in path {
module = module.children(db).find_map(|child| {
let name = child.name(db)?;
- if name.display_no_db().to_smolstr() == segment {
+ if name.eq_ident(segment) {
Some(child)
} else {
None
}
})?;
}
- let def = module
- .scope(db, None)
- .into_iter()
- .find(|(name, _def)| name.display_no_db().to_smolstr() == trait_)?
- .1;
+ let def = module.scope(db, None).into_iter().find(|(name, _def)| name.eq_ident(trait_))?.1;
Some(def)
}
}
diff --git a/crates/ide-db/src/helpers.rs b/crates/ide-db/src/helpers.rs
index e6638dde5d..63c09af3d6 100644
--- a/crates/ide-db/src/helpers.rs
+++ b/crates/ide-db/src/helpers.rs
@@ -4,7 +4,7 @@ use std::collections::VecDeque;
use base_db::SourceRootDatabase;
use hir::{Crate, DescendPreference, ItemInNs, ModuleDef, Name, Semantics};
-use span::FileId;
+use span::{Edition, FileId};
use syntax::{
ast::{self, make},
AstToken, SyntaxKind, SyntaxToken, ToSmolStr, TokenAtOffset,
@@ -35,7 +35,7 @@ pub fn pick_token<T: AstToken>(mut tokens: TokenAtOffset<SyntaxToken>) -> Option
}
/// Converts the mod path struct into its ast representation.
-pub fn mod_path_to_ast(path: &hir::ModPath) -> ast::Path {
+pub fn mod_path_to_ast(path: &hir::ModPath, edition: Edition) -> ast::Path {
let _p = tracing::info_span!("mod_path_to_ast").entered();
let mut segments = Vec::new();
@@ -50,11 +50,9 @@ pub fn mod_path_to_ast(path: &hir::ModPath) -> ast::Path {
hir::PathKind::Abs => is_abs = true,
}
- segments.extend(
- path.segments().iter().map(|segment| {
- make::path_segment(make::name_ref(&segment.display_no_db().to_smolstr()))
- }),
- );
+ segments.extend(path.segments().iter().map(|segment| {
+ make::path_segment(make::name_ref(&segment.display_no_db(edition).to_smolstr()))
+ }));
make::path_from_segments(segments, is_abs)
}
diff --git a/crates/ide-db/src/imports/import_assets.rs b/crates/ide-db/src/imports/import_assets.rs
index 1c4c15f255..07e1973347 100644
--- a/crates/ide-db/src/imports/import_assets.rs
+++ b/crates/ide-db/src/imports/import_assets.rs
@@ -9,7 +9,7 @@ use itertools::{EitherOrBoth, Itertools};
use rustc_hash::{FxHashMap, FxHashSet};
use syntax::{
ast::{self, make, HasName},
- AstNode, SmolStr, SyntaxNode, ToSmolStr,
+ AstNode, SmolStr, SyntaxNode,
};
use crate::{
@@ -459,7 +459,7 @@ fn find_import_for_segment(
unresolved_first_segment: &str,
) -> Option<ItemInNs> {
let segment_is_name = item_name(db, original_item)
- .map(|name| name.display_no_db().to_smolstr() == unresolved_first_segment)
+ .map(|name| name.eq_ident(unresolved_first_segment))
.unwrap_or(false);
Some(if segment_is_name {
@@ -483,7 +483,7 @@ fn module_with_segment_name(
};
while let Some(module) = current_module {
if let Some(module_name) = module.name(db) {
- if module_name.display_no_db().to_smolstr() == segment_name {
+ if module_name.eq_ident(segment_name) {
return Some(module);
}
}
diff --git a/crates/ide-db/src/path_transform.rs b/crates/ide-db/src/path_transform.rs
index 0afa9163e3..49b3ca290f 100644
--- a/crates/ide-db/src/path_transform.rs
+++ b/crates/ide-db/src/path_transform.rs
@@ -5,6 +5,7 @@ use either::Either;
use hir::{AsAssocItem, HirDisplay, ImportPathConfig, ModuleDef, SemanticsScope};
use itertools::Itertools;
use rustc_hash::FxHashMap;
+use span::Edition;
use syntax::{
ast::{self, make, AstNode, HasGenericArgs},
ted, NodeOrToken, SyntaxNode,
@@ -146,6 +147,7 @@ impl<'a> PathTransform<'a> {
let mut type_substs: FxHashMap<hir::TypeParam, ast::Type> = Default::default();
let mut const_substs: FxHashMap<hir::ConstParam, SyntaxNode> = Default::default();
let mut defaulted_params: Vec<DefaultedParam> = Default::default();
+ let target_edition = target_module.krate().edition(self.source_scope.db);
self.generic_def
.into_iter()
.flat_map(|it| it.type_or_const_params(db))
@@ -190,7 +192,7 @@ impl<'a> PathTransform<'a> {
}
}
(Either::Left(k), None) => {
- if let Some(default) = k.default(db) {
+ if let Some(default) = k.default(db, target_edition) {
if let Some(default) = default.expr() {
const_substs.insert(k, default.syntax().clone_for_update());
defaulted_params.push(Either::Right(k));
@@ -204,7 +206,9 @@ impl<'a> PathTransform<'a> {
.into_iter()
.flat_map(|it| it.lifetime_params(db))
.zip(self.substs.lifetimes.clone())
- .filter_map(|(k, v)| Some((k.name(db).display(db.upcast()).to_string(), v.lifetime()?)))
+ .filter_map(|(k, v)| {
+ Some((k.name(db).display(db.upcast(), target_edition).to_string(), v.lifetime()?))
+ })
.collect();
let ctx = Ctx {
type_substs,
@@ -213,6 +217,7 @@ impl<'a> PathTransform<'a> {
target_module,
source_scope: self.source_scope,
same_self_type: self.target_scope.has_same_self_type(self.source_scope),
+ target_edition,
};
ctx.transform_default_values(defaulted_params);
ctx
@@ -226,6 +231,7 @@ struct Ctx<'a> {
target_module: hir::Module,
source_scope: &'a SemanticsScope<'a>,
same_self_type: bool,
+ target_edition: Edition,
}
fn preorder_rev(item: &SyntaxNode) -> impl Iterator<Item = SyntaxNode> {
@@ -318,7 +324,7 @@ impl Ctx<'_> {
hir::ModuleDef::Trait(trait_ref),
cfg,
)?;
- match make::ty_path(mod_path_to_ast(&found_path)) {
+ match make::ty_path(mod_path_to_ast(&found_path, self.target_edition)) {
ast::Type::PathType(path_ty) => Some(path_ty),
_ => None,
}
@@ -374,7 +380,7 @@ impl Ctx<'_> {
};
let found_path =
self.target_module.find_path(self.source_scope.db.upcast(), def, cfg)?;
- let res = mod_path_to_ast(&found_path).clone_for_update();
+ let res = mod_path_to_ast(&found_path, self.target_edition).clone_for_update();
if let Some(args) = path.segment().and_then(|it| it.generic_arg_list()) {
if let Some(segment) = res.segment() {
let old = segment.get_or_create_generic_arg_list();
@@ -417,7 +423,9 @@ impl Ctx<'_> {
cfg,
)?;
- if let Some(qual) = mod_path_to_ast(&found_path).qualifier() {
+ if let Some(qual) =
+ mod_path_to_ast(&found_path, self.target_edition).qualifier()
+ {
let res = make::path_concat(qual, path_ty.path()?).clone_for_update();
ted::replace(path.syntax(), res.syntax());
return Some(());
diff --git a/crates/ide-db/src/rename.rs b/crates/ide-db/src/rename.rs
index 232f242828..262eefeec0 100644
--- a/crates/ide-db/src/rename.rs
+++ b/crates/ide-db/src/rename.rs
@@ -29,6 +29,7 @@ use span::{Edition, EditionedFileId, FileId, SyntaxContextId};
use stdx::{never, TupleExt};
use syntax::{
ast::{self, HasName},
+ utils::is_raw_identifier,
AstNode, SyntaxKind, TextRange, T,
};
use text_edit::{TextEdit, TextEditBuilder};
@@ -72,6 +73,9 @@ impl Definition {
sema: &Semantics<'_, RootDatabase>,
new_name: &str,
) -> Result<SourceChange> {
+ // We append `r#` if needed.
+ let new_name = new_name.trim_start_matches("r#");
+
// self.krate() returns None if
// self is a built-in attr, built-in type or tool module.
// it is not allowed for these defs to be renamed.
@@ -227,8 +231,7 @@ fn rename_mod(
module: hir::Module,
new_name: &str,
) -> Result<SourceChange> {
- if IdentifierKind::classify(module.krate().edition(sema.db), new_name)? != IdentifierKind::Ident
- {
+ if IdentifierKind::classify(new_name)? != IdentifierKind::Ident {
bail!("Invalid name `{0}`: cannot rename module to {0}", new_name);
}
@@ -240,7 +243,6 @@ fn rename_mod(
let InFile { file_id, value: def_source } = module.definition_source(sema.db);
if let ModuleSource::SourceFile(..) = def_source {
- let new_name = new_name.trim_start_matches("r#");
let anchor = file_id.original_file(sema.db).file_id();
let is_mod_rs = module.is_mod_rs(sema.db);
@@ -289,9 +291,14 @@ fn rename_mod(
.original_file_range_opt(sema.db)
.map(TupleExt::head)
{
+ let new_name = if is_raw_identifier(new_name, file_id.edition()) {
+ format!("r#{new_name}")
+ } else {
+ new_name.to_owned()
+ };
source_change.insert_source_edit(
file_id.file_id(),
- TextEdit::replace(file_range.range, new_name.to_owned()),
+ TextEdit::replace(file_range.range, new_name),
)
};
}
@@ -302,7 +309,10 @@ fn rename_mod(
let def = Definition::Module(module);
let usages = def.usages(sema).all();
let ref_edits = usages.iter().map(|(file_id, references)| {
- (EditionedFileId::file_id(file_id), source_edit_from_references(references, def, new_name))
+ (
+ EditionedFileId::file_id(file_id),
+ source_edit_from_references(references, def, new_name, file_id.edition()),
+ )
});
source_change.extend(ref_edits);
@@ -314,12 +324,7 @@ fn rename_reference(
def: Definition,
new_name: &str,
) -> Result<SourceChange> {
- let ident_kind = IdentifierKind::classify(
- def.krate(sema.db)
- .ok_or_else(|| RenameError("definition has no krate?".into()))?
- .edition(sema.db),
- new_name,
- )?;
+ let ident_kind = IdentifierKind::classify(new_name)?;
if matches!(
def,
@@ -351,7 +356,10 @@ fn rename_reference(
}
let mut source_change = SourceChange::default();
source_change.extend(usages.iter().map(|(file_id, references)| {
- (EditionedFileId::file_id(file_id), source_edit_from_references(references, def, new_name))
+ (
+ EditionedFileId::file_id(file_id),
+ source_edit_from_references(references, def, new_name, file_id.edition()),
+ )
}));
let mut insert_def_edit = |def| {
@@ -367,7 +375,13 @@ pub fn source_edit_from_references(
references: &[FileReference],
def: Definition,
new_name: &str,
+ edition: Edition,
) -> TextEdit {
+ let new_name = if is_raw_identifier(new_name, edition) {
+ format!("r#{new_name}")
+ } else {
+ new_name.to_owned()
+ };
let mut edit = TextEdit::builder();
// macros can cause multiple refs to occur for the same text range, so keep track of what we have edited so far
let mut edited_ranges = Vec::new();
@@ -383,10 +397,10 @@ pub fn source_edit_from_references(
// to make special rewrites like shorthand syntax and such, so just rename the node in
// the macro input
FileReferenceNode::NameRef(name_ref) if name_range == range => {
- source_edit_from_name_ref(&mut edit, name_ref, new_name, def)
+ source_edit_from_name_ref(&mut edit, name_ref, &new_name, def)
}
FileReferenceNode::Name(name) if name_range == range => {
- source_edit_from_name(&mut edit, name, new_name)
+ source_edit_from_name(&mut edit, name, &new_name)
}
_ => false,
};
@@ -394,7 +408,7 @@ pub fn source_edit_from_references(
let (range, new_name) = match name {
FileReferenceNode::Lifetime(_) => (
TextRange::new(range.start() + syntax::TextSize::from(1), range.end()),
- new_name.strip_prefix('\'').unwrap_or(new_name).to_owned(),
+ new_name.strip_prefix('\'').unwrap_or(&new_name).to_owned(),
),
_ => (range, new_name.to_owned()),
};
@@ -522,6 +536,13 @@ fn source_edit_from_def(
def: Definition,
new_name: &str,
) -> Result<(FileId, TextEdit)> {
+ let new_name_edition_aware = |new_name: &str, file_id: EditionedFileId| {
+ if is_raw_identifier(new_name, file_id.edition()) {
+ format!("r#{new_name}")
+ } else {
+ new_name.to_owned()
+ }
+ };
let mut edit = TextEdit::builder();
if let Definition::Local(local) = def {
let mut file_id = None;
@@ -536,7 +557,7 @@ fn source_edit_from_def(
{
Some(FileRange { file_id: file_id2, range }) => {
file_id = Some(file_id2);
- edit.replace(range, new_name.to_owned());
+ edit.replace(range, new_name_edition_aware(new_name, file_id2));
continue;
}
None => {
@@ -550,7 +571,9 @@ fn source_edit_from_def(
// special cases required for renaming fields/locals in Record patterns
if let Some(pat_field) = pat.syntax().parent().and_then(ast::RecordPatField::cast) {
if let Some(name_ref) = pat_field.name_ref() {
- if new_name == name_ref.text() && pat.at_token().is_none() {
+ if new_name == name_ref.text().as_str().trim_start_matches("r#")
+ && pat.at_token().is_none()
+ {
// Foo { field: ref mut local } -> Foo { ref mut field }
// ^^^^^^ delete this
// ^^^^^ replace this with `field`
@@ -566,7 +589,10 @@ fn source_edit_from_def(
// Foo { field: ref mut local @ local 2} -> Foo { field: ref mut new_name @ local2 }
// Foo { field: ref mut local } -> Foo { field: ref mut new_name }
// ^^^^^ replace this with `new_name`
- edit.replace(name_range, new_name.to_owned());
+ edit.replace(
+ name_range,
+ new_name_edition_aware(new_name, source.file_id),
+ );
}
} else {
// Foo { ref mut field } -> Foo { field: ref mut new_name }
@@ -576,10 +602,10 @@ fn source_edit_from_def(
pat.syntax().text_range().start(),
format!("{}: ", pat_field.field_name().unwrap()),
);
- edit.replace(name_range, new_name.to_owned());
+ edit.replace(name_range, new_name_edition_aware(new_name, source.file_id));
}
} else {
- edit.replace(name_range, new_name.to_owned());
+ edit.replace(name_range, new_name_edition_aware(new_name, source.file_id));
}
}
}
@@ -599,7 +625,7 @@ fn source_edit_from_def(
}
_ => (range, new_name.to_owned()),
};
- edit.replace(range, new_name);
+ edit.replace(range, new_name_edition_aware(&new_name, file_id));
Ok((file_id.file_id(), edit.finish()))
}
@@ -611,8 +637,9 @@ pub enum IdentifierKind {
}
impl IdentifierKind {
- pub fn classify(edition: Edition, new_name: &str) -> Result<IdentifierKind> {
- match parser::LexedStr::single_token(edition, new_name) {
+ pub fn classify(new_name: &str) -> Result<IdentifierKind> {
+ let new_name = new_name.trim_start_matches("r#");
+ match parser::LexedStr::single_token(Edition::LATEST, new_name) {
Some(res) => match res {
(SyntaxKind::IDENT, _) => {
if let Some(inner) = new_name.strip_prefix("r#") {
@@ -626,6 +653,7 @@ impl IdentifierKind {
(SyntaxKind::LIFETIME_IDENT, _) if new_name != "'static" && new_name != "'_" => {
Ok(IdentifierKind::Lifetime)
}
+ _ if is_raw_identifier(new_name, Edition::LATEST) => Ok(IdentifierKind::Ident),
(_, Some(syntax_error)) => bail!("Invalid name `{}`: {}", new_name, syntax_error),
(_, None) => bail!("Invalid name `{}`: not an identifier", new_name),
},
diff --git a/crates/ide-db/src/syntax_helpers/insert_whitespace_into_node.rs b/crates/ide-db/src/syntax_helpers/insert_whitespace_into_node.rs
index 6714e411e2..dd4a665e8e 100644
--- a/crates/ide-db/src/syntax_helpers/insert_whitespace_into_node.rs
+++ b/crates/ide-db/src/syntax_helpers/insert_whitespace_into_node.rs
@@ -1,5 +1,4 @@
//! Utilities for formatting macro expanded nodes until we get a proper formatter.
-use span::Edition;
use syntax::{
ast::make,
ted::{self, Position},
@@ -132,6 +131,6 @@ pub fn insert_ws_into(syn: SyntaxNode) -> SyntaxNode {
}
fn is_text(k: SyntaxKind) -> bool {
- // FIXME: Edition
- k.is_keyword(Edition::CURRENT) || k.is_literal() || k == IDENT || k == UNDERSCORE
+ // Consider all keywords in all editions.
+ k.is_any_identifier() || k.is_literal() || k == UNDERSCORE
}
diff --git a/crates/ide-db/src/syntax_helpers/node_ext.rs b/crates/ide-db/src/syntax_helpers/node_ext.rs
index d10a55120a..fa82902a74 100644
--- a/crates/ide-db/src/syntax_helpers/node_ext.rs
+++ b/crates/ide-db/src/syntax_helpers/node_ext.rs
@@ -457,13 +457,15 @@ impl Iterator for TreeWithDepthIterator {
}
/// Parses the input token tree as comma separated plain paths.
-pub fn parse_tt_as_comma_sep_paths(input: ast::TokenTree) -> Option<Vec<ast::Path>> {
+pub fn parse_tt_as_comma_sep_paths(
+ input: ast::TokenTree,
+ edition: Edition,
+) -> Option<Vec<ast::Path>> {
let r_paren = input.r_paren_token();
let tokens =
input.syntax().children_with_tokens().skip(1).map_while(|it| match it.into_token() {
// seeing a keyword means the attribute is unclosed so stop parsing here
- // FIXME: Edition
- Some(tok) if tok.kind().is_keyword(Edition::CURRENT) => None,
+ Some(tok) if tok.kind().is_keyword(edition) => None,
// don't include the right token tree parenthesis if it exists
tok @ Some(_) if tok == r_paren => None,
// only nodes that we can find are other TokenTrees, those are unexpected in this parse though
diff --git a/crates/ide-db/src/traits.rs b/crates/ide-db/src/traits.rs
index 48a585bf33..82aca50d03 100644
--- a/crates/ide-db/src/traits.rs
+++ b/crates/ide-db/src/traits.rs
@@ -34,19 +34,20 @@ pub fn get_missing_assoc_items(
// may share the same name as a function or constant.
let mut impl_fns_consts = FxHashSet::default();
let mut impl_type = FxHashSet::default();
+ let edition = imp.module(sema.db).krate().edition(sema.db);
for item in imp.items(sema.db) {
match item {
hir::AssocItem::Function(it) => {
- impl_fns_consts.insert(it.name(sema.db).display(sema.db).to_string());
+ impl_fns_consts.insert(it.name(sema.db).display(sema.db, edition).to_string());
}
hir::AssocItem::Const(it) => {
if let Some(name) = it.name(sema.db) {
- impl_fns_consts.insert(name.display(sema.db).to_string());
+ impl_fns_consts.insert(name.display(sema.db, edition).to_string());
}
}
hir::AssocItem::TypeAlias(it) => {
- impl_type.insert(it.name(sema.db).display(sema.db).to_string());
+ impl_type.insert(it.name(sema.db).display(sema.db, edition).to_string());
}
}
}
@@ -56,15 +57,14 @@ pub fn get_missing_assoc_items(
.items(sema.db)
.into_iter()
.filter(|i| match i {
- hir::AssocItem::Function(f) => {
- !impl_fns_consts.contains(&f.name(sema.db).display(sema.db).to_string())
- }
+ hir::AssocItem::Function(f) => !impl_fns_consts
+ .contains(&f.name(sema.db).display(sema.db, edition).to_string()),
hir::AssocItem::TypeAlias(t) => {
- !impl_type.contains(&t.name(sema.db).display(sema.db).to_string())
+ !impl_type.contains(&t.name(sema.db).display(sema.db, edition).to_string())
}
hir::AssocItem::Const(c) => c
.name(sema.db)
- .map(|n| !impl_fns_consts.contains(&n.display(sema.db).to_string()))
+ .map(|n| !impl_fns_consts.contains(&n.display(sema.db, edition).to_string()))
.unwrap_or_default(),
})
.collect()
@@ -116,6 +116,7 @@ mod tests {
use expect_test::{expect, Expect};
use hir::FilePosition;
use hir::Semantics;
+ use span::Edition;
use syntax::ast::{self, AstNode};
use test_fixture::ChangeFixture;
@@ -140,7 +141,7 @@ mod tests {
sema.find_node_at_offset_with_descend(file.syntax(), position.offset).unwrap();
let trait_ = crate::traits::resolve_target_trait(&sema, &impl_block);
let actual = match trait_ {
- Some(trait_) => trait_.name(&db).display(&db).to_string(),
+ Some(trait_) => trait_.name(&db).display(&db, Edition::CURRENT).to_string(),
None => String::new(),
};
expect.assert_eq(&actual);
@@ -155,7 +156,7 @@ mod tests {
let items = crate::traits::get_missing_assoc_items(&sema, &impl_block);
let actual = items
.into_iter()
- .map(|item| item.name(&db).unwrap().display(&db).to_string())
+ .map(|item| item.name(&db).unwrap().display(&db, Edition::CURRENT).to_string())
.collect::<Vec<_>>()
.join("\n");
expect.assert_eq(&actual);
diff --git a/crates/ide-db/src/ty_filter.rs b/crates/ide-db/src/ty_filter.rs
index 5b566c5067..515bc418cb 100644
--- a/crates/ide-db/src/ty_filter.rs
+++ b/crates/ide-db/src/ty_filter.rs
@@ -5,10 +5,7 @@
use std::iter;
use hir::Semantics;
-use syntax::{
- ast::{self, make, Pat},
- ToSmolStr,
-};
+use syntax::ast::{self, make, Pat};
use crate::RootDatabase;
@@ -29,7 +26,7 @@ impl TryEnum {
_ => return None,
};
TryEnum::ALL.iter().find_map(|&var| {
- if enum_.name(sema.db).display_no_db().to_smolstr() == var.type_name() {
+ if enum_.name(sema.db).eq_ident(var.type_name()) {
return Some(var);
}
None
diff --git a/crates/ide-db/src/use_trivial_constructor.rs b/crates/ide-db/src/use_trivial_constructor.rs
index 965f432407..c3f0bf3706 100644
--- a/crates/ide-db/src/use_trivial_constructor.rs
+++ b/crates/ide-db/src/use_trivial_constructor.rs
@@ -1,6 +1,7 @@
//! Functionality for generating trivial constructors
use hir::StructKind;
+use span::Edition;
use syntax::{
ast::{make, Expr, Path},
ToSmolStr,
@@ -11,6 +12,7 @@ pub fn use_trivial_constructor(
db: &crate::RootDatabase,
path: Path,
ty: &hir::Type,
+ edition: Edition,
) -> Option<Expr> {
match ty.as_adt() {
Some(hir::Adt::Enum(x)) => {
@@ -19,7 +21,7 @@ pub fn use_trivial_constructor(
let path = make::path_qualified(
path,
make::path_segment(make::name_ref(
- &variant.name(db).display_no_db().to_smolstr(),
+ &variant.name(db).display_no_db(edition).to_smolstr(),
)),
);
diff --git a/crates/ide-diagnostics/src/handlers/expected_function.rs b/crates/ide-diagnostics/src/handlers/expected_function.rs
index 05fb1c29b3..02299197b1 100644
--- a/crates/ide-diagnostics/src/handlers/expected_function.rs
+++ b/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)),
+ format!("expected function, found {}", d.found.display(ctx.sema.db, ctx.edition)),
d.call.map(|it| it.into()),
)
.experimental()
diff --git a/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs b/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs
index 117088ca09..ccb33fed10 100644
--- a/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs
+++ b/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs
@@ -12,7 +12,7 @@ use itertools::Itertools;
use stdx::{format_to, never};
use syntax::{
ast::{self, make},
- SyntaxKind, SyntaxNode,
+ Edition, SyntaxKind, SyntaxNode,
};
use text_edit::TextEdit;
@@ -104,6 +104,7 @@ pub(crate) fn json_in_items(
file_id: EditionedFileId,
node: &SyntaxNode,
config: &DiagnosticsConfig,
+ edition: Edition,
) {
(|| {
if node.kind() == SyntaxKind::ERROR
@@ -156,7 +157,11 @@ pub(crate) fn json_in_items(
config.insert_use.prefix_kind,
cfg,
) {
- insert_use(&scope, mod_path_to_ast(&it), &config.insert_use);
+ insert_use(
+ &scope,
+ mod_path_to_ast(&it, edition),
+ &config.insert_use,
+ );
}
}
}
@@ -168,7 +173,11 @@ pub(crate) fn json_in_items(
config.insert_use.prefix_kind,
cfg,
) {
- insert_use(&scope, mod_path_to_ast(&it), &config.insert_use);
+ insert_use(
+ &scope,
+ mod_path_to_ast(&it, edition),
+ &config.insert_use,
+ );
}
}
}
diff --git a/crates/ide-diagnostics/src/handlers/missing_fields.rs b/crates/ide-diagnostics/src/handlers/missing_fields.rs
index ea7908525a..86c237f7b5 100644
--- a/crates/ide-diagnostics/src/handlers/missing_fields.rs
+++ b/crates/ide-diagnostics/src/handlers/missing_fields.rs
@@ -11,7 +11,7 @@ use stdx::format_to;
use syntax::{
algo,
ast::{self, make},
- AstNode, SyntaxNode, SyntaxNodePtr, ToSmolStr,
+ AstNode, Edition, SyntaxNode, SyntaxNodePtr, ToSmolStr,
};
use text_edit::TextEdit;
@@ -31,7 +31,7 @@ use crate::{fix, Diagnostic, DiagnosticCode, DiagnosticsContext};
pub(crate) fn missing_fields(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Diagnostic {
let mut message = String::from("missing structure fields:\n");
for field in &d.missed_fields {
- format_to!(message, "- {}\n", field.display(ctx.sema.db));
+ format_to!(message, "- {}\n", field.display(ctx.sema.db, ctx.edition));
}
let ptr = InFile::new(
@@ -134,8 +134,9 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option<Vec<Ass
use_trivial_constructor(
ctx.sema.db,
- ide_db::helpers::mod_path_to_ast(&type_path),
+ ide_db::helpers::mod_path_to_ast(&type_path, ctx.edition),
ty,
+ ctx.edition,
)
})();
@@ -146,7 +147,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option<Vec<Ass
}
};
let field = make::record_expr_field(
- make::name_ref(&f.name(ctx.sema.db).display_no_db().to_smolstr()),
+ make::name_ref(&f.name(ctx.sema.db).display_no_db(ctx.edition).to_smolstr()),
field_expr,
);
new_field_list.add_field(field.clone_for_update());
@@ -160,7 +161,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option<Vec<Ass
let new_field_list = old_field_list.clone_for_update();
for (f, _) in missing_fields.iter() {
let field = make::record_pat_field_shorthand(make::name_ref(
- &f.name(ctx.sema.db).display_no_db().to_smolstr(),
+ &f.name(ctx.sema.db).display_no_db(ctx.edition).to_smolstr(),
));
new_field_list.add_field(field.clone_for_update());
}
@@ -169,9 +170,14 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option<Vec<Ass
}
}
-fn make_ty(ty: &hir::Type, db: &dyn HirDatabase, module: hir::Module) -> ast::Type {
+fn make_ty(
+ ty: &hir::Type,
+ db: &dyn HirDatabase,
+ module: hir::Module,
+ edition: Edition,
+) -> ast::Type {
let ty_str = match ty.as_adt() {
- Some(adt) => adt.name(db).display(db.upcast()).to_string(),
+ Some(adt) => adt.name(db).display(db.upcast(), edition).to_string(),
None => {
ty.display_source_code(db, module.into(), false).ok().unwrap_or_else(|| "_".to_owned())
}
@@ -223,13 +229,13 @@ fn get_default_constructor(
let famous_defs = FamousDefs(&ctx.sema, krate);
if has_new_func {
- Some(make::ext::expr_ty_new(&make_ty(ty, ctx.sema.db, module)))
+ Some(make::ext::expr_ty_new(&make_ty(ty, ctx.sema.db, module, ctx.edition)))
} else if ty.as_adt() == famous_defs.core_option_Option()?.ty(ctx.sema.db).as_adt() {
Some(make::ext::option_none())
} else if !ty.is_array()
&& ty.impls_trait(ctx.sema.db, famous_defs.core_default_Default()?, &[])
{
- Some(make::ext::expr_ty_default(&make_ty(ty, ctx.sema.db, module)))
+ Some(make::ext::expr_ty_default(&make_ty(ty, ctx.sema.db, module, ctx.edition)))
} else {
None
}
diff --git a/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs b/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs
index fa9a6577fc..06c6b0f3e4 100644
--- a/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs
+++ b/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)),
+ format!("cannot move `{}` out of reference", d.ty.display(ctx.sema.db, ctx.edition)),
d.span,
)
.experimental() // spans are broken, and I'm not sure how precise we can detect copy types
diff --git a/crates/ide-diagnostics/src/handlers/mutability_errors.rs b/crates/ide-diagnostics/src/handlers/mutability_errors.rs
index 00352266dd..e4b1f3ca95 100644
--- a/crates/ide-diagnostics/src/handlers/mutability_errors.rs
+++ b/crates/ide-diagnostics/src/handlers/mutability_errors.rs
@@ -40,7 +40,7 @@ pub(crate) fn need_mut(ctx: &DiagnosticsContext<'_>, d: &hir::NeedMut) -> Option
DiagnosticCode::RustcHardError("E0384"),
format!(
"cannot mutate immutable variable `{}`",
- d.local.name(ctx.sema.db).display(ctx.sema.db)
+ d.local.name(ctx.sema.db).display(ctx.sema.db, ctx.edition)
),
d.span,
)
diff --git a/crates/ide-diagnostics/src/handlers/private_assoc_item.rs b/crates/ide-diagnostics/src/handlers/private_assoc_item.rs
index f6ed0d7226..fe32c59049 100644
--- a/crates/ide-diagnostics/src/handlers/private_assoc_item.rs
+++ b/crates/ide-diagnostics/src/handlers/private_assoc_item.rs
@@ -12,7 +12,7 @@ pub(crate) fn private_assoc_item(
let name = d
.item
.name(ctx.sema.db)
- .map(|name| format!("`{}` ", name.display(ctx.sema.db)))
+ .map(|name| format!("`{}` ", name.display(ctx.sema.db, ctx.edition)))
.unwrap_or_default();
Diagnostic::new_with_syntax_node_ptr(
ctx,
diff --git a/crates/ide-diagnostics/src/handlers/private_field.rs b/crates/ide-diagnostics/src/handlers/private_field.rs
index e91e64c81b..237a9b8787 100644
--- a/crates/ide-diagnostics/src/handlers/private_field.rs
+++ b/crates/ide-diagnostics/src/handlers/private_field.rs
@@ -10,8 +10,8 @@ pub(crate) fn private_field(ctx: &DiagnosticsContext<'_>, d: &hir::PrivateField)
DiagnosticCode::RustcHardError("E0616"),
format!(
"field `{}` of `{}` is private",
- d.field.name(ctx.sema.db).display(ctx.sema.db),
- d.field.parent_def(ctx.sema.db).name(ctx.sema.db).display(ctx.sema.db)
+ d.field.name(ctx.sema.db).display(ctx.sema.db, ctx.edition),
+ d.field.parent_def(ctx.sema.db).name(ctx.sema.db).display(ctx.sema.db, ctx.edition)
),
d.expr.map(|it| it.into()),
)
diff --git a/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs b/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs
index 58d1b7f31d..a35b67ce98 100644
--- a/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs
+++ b/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs
@@ -17,7 +17,7 @@ pub(crate) fn trait_impl_missing_assoc_item(
hir::AssocItem::Const(_) => "`const ",
hir::AssocItem::TypeAlias(_) => "`type ",
})?;
- f(&name.display(ctx.sema.db))?;
+ f(&name.display(ctx.sema.db, ctx.edition))?;
f(&"`")
});
Diagnostic::new(
diff --git a/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs b/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs
index 6d756484eb..3de51ca4a3 100644
--- a/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs
+++ b/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs
@@ -18,11 +18,11 @@ pub(crate) fn trait_impl_redundant_assoc_item(
) -> Diagnostic {
let db = ctx.sema.db;
let name = d.assoc_item.0.clone();
- let redundant_assoc_item_name = name.display(db);
+ let redundant_assoc_item_name = name.display(db, ctx.edition);
let assoc_item = d.assoc_item.1;
let default_range = d.impl_.syntax_node_ptr().text_range();
- let trait_name = d.trait_.name(db).display_no_db().to_smolstr();
+ let trait_name = d.trait_.name(db).display_no_db(ctx.edition).to_smolstr();
let (redundant_item_name, diagnostic_range, redundant_item_def) = match assoc_item {
hir::AssocItem::Function(id) => {
@@ -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)),
+ format!("\n {};", function.display(db, ctx.edition)),
)
}
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)),
+ format!("\n {};", constant.display(db, ctx.edition)),
)
}
hir::AssocItem::TypeAlias(id) => {
@@ -48,7 +48,7 @@ pub(crate) fn trait_impl_redundant_assoc_item(
type_alias.source(db).map(|it| it.syntax().text_range()).unwrap_or(default_range),
format!(
"\n type {};",
- type_alias.name(ctx.sema.db).display_no_db().to_smolstr()
+ type_alias.name(ctx.sema.db).display_no_db(ctx.edition).to_smolstr()
),
)
}
diff --git a/crates/ide-diagnostics/src/handlers/type_mismatch.rs b/crates/ide-diagnostics/src/handlers/type_mismatch.rs
index 6f5c68d4b5..5cce7c4aed 100644
--- a/crates/ide-diagnostics/src/handlers/type_mismatch.rs
+++ b/crates/ide-diagnostics/src/handlers/type_mismatch.rs
@@ -40,8 +40,12 @@ pub(crate) fn type_mismatch(ctx: &DiagnosticsContext<'_>, d: &hir::TypeMismatch)
DiagnosticCode::RustcHardError("E0308"),
format!(
"expected {}, found {}",
- d.expected.display(ctx.sema.db).with_closure_style(ClosureStyle::ClosureWithId),
- d.actual.display(ctx.sema.db).with_closure_style(ClosureStyle::ClosureWithId),
+ d.expected
+ .display(ctx.sema.db, ctx.edition)
+ .with_closure_style(ClosureStyle::ClosureWithId),
+ d.actual
+ .display(ctx.sema.db, ctx.edition)
+ .with_closure_style(ClosureStyle::ClosureWithId),
),
display_range,
)
@@ -199,8 +203,8 @@ fn str_ref_to_owned(
expr_ptr: &InFile<AstPtr<ast::Expr>>,
acc: &mut Vec<Assist>,
) -> Option<()> {
- let expected = d.expected.display(ctx.sema.db);
- let actual = d.actual.display(ctx.sema.db);
+ let expected = d.expected.display(ctx.sema.db, ctx.edition);
+ let actual = d.actual.display(ctx.sema.db, ctx.edition);
// FIXME do this properly
if expected.to_string() != "String" || actual.to_string() != "&str" {
diff --git a/crates/ide-diagnostics/src/handlers/typed_hole.rs b/crates/ide-diagnostics/src/handlers/typed_hole.rs
index b4a566e318..b5c242e1e9 100644
--- a/crates/ide-diagnostics/src/handlers/typed_hole.rs
+++ b/crates/ide-diagnostics/src/handlers/typed_hole.rs
@@ -26,7 +26,9 @@ pub(crate) fn typed_hole(ctx: &DiagnosticsContext<'_>, d: &hir::TypedHole) -> Di
(
format!(
"invalid `_` expression, expected type `{}`",
- d.expected.display(ctx.sema.db).with_closure_style(ClosureStyle::ClosureWithId),
+ d.expected
+ .display(ctx.sema.db, ctx.edition)
+ .with_closure_style(ClosureStyle::ClosureWithId),
),
fixes(ctx, d),
)
@@ -69,6 +71,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::TypedHole) -> Option<Vec<Assist>
prefer_prelude: ctx.config.prefer_prelude,
prefer_absolute: ctx.config.prefer_absolute,
},
+ ctx.edition,
)
.ok()
})
diff --git a/crates/ide-diagnostics/src/handlers/undeclared_label.rs b/crates/ide-diagnostics/src/handlers/undeclared_label.rs
index 97943b7e8b..6af36fb9e7 100644
--- a/crates/ide-diagnostics/src/handlers/undeclared_label.rs
+++ b/crates/ide-diagnostics/src/handlers/undeclared_label.rs
@@ -9,7 +9,7 @@ pub(crate) fn undeclared_label(
Diagnostic::new_with_syntax_node_ptr(
ctx,
DiagnosticCode::RustcHardError("undeclared-label"),
- format!("use of undeclared label `{}`", name.display(ctx.sema.db)),
+ format!("use of undeclared label `{}`", name.display(ctx.sema.db, ctx.edition)),
d.node.map(|it| it.into()),
)
}
diff --git a/crates/ide-diagnostics/src/handlers/unlinked_file.rs b/crates/ide-diagnostics/src/handlers/unlinked_file.rs
index a1573bab8a..e0822fc5b3 100644
--- a/crates/ide-diagnostics/src/handlers/unlinked_file.rs
+++ b/crates/ide-diagnostics/src/handlers/unlinked_file.rs
@@ -11,7 +11,7 @@ use ide_db::{
use paths::Utf8Component;
use syntax::{
ast::{self, edit::IndentLevel, HasModuleItem, HasName},
- AstNode, TextRange, ToSmolStr,
+ AstNode, TextRange,
};
use text_edit::TextEdit;
@@ -112,8 +112,7 @@ fn fixes(
// shouldn't occur
_ => continue 'crates,
};
- match current.children.iter().find(|(name, _)| name.display_no_db().to_smolstr() == seg)
- {
+ match current.children.iter().find(|(name, _)| name.eq_ident(seg)) {
Some((_, &child)) => current = &crate_def_map[child],
None => continue 'crates,
}
@@ -162,11 +161,7 @@ fn fixes(
// try finding a parent that has an inline tree from here on
let mut current = module;
for s in stack.iter().rev() {
- match module
- .children
- .iter()
- .find(|(name, _)| name.display_no_db().to_smolstr() == s)
- {
+ match module.children.iter().find(|(name, _)| name.eq_ident(s)) {
Some((_, child)) => {
current = &crate_def_map[*child];
}
diff --git a/crates/ide-diagnostics/src/handlers/unreachable_label.rs b/crates/ide-diagnostics/src/handlers/unreachable_label.rs
index 3601041fc7..bdff2417ca 100644
--- a/crates/ide-diagnostics/src/handlers/unreachable_label.rs
+++ b/crates/ide-diagnostics/src/handlers/unreachable_label.rs
@@ -9,7 +9,7 @@ pub(crate) fn unreachable_label(
Diagnostic::new_with_syntax_node_ptr(
ctx,
DiagnosticCode::RustcHardError("E0767"),
- format!("use of unreachable label `{}`", name.display(ctx.sema.db)),
+ format!("use of unreachable label `{}`", name.display(ctx.sema.db, ctx.edition)),
d.node.map(|it| it.into()),
)
}
diff --git a/crates/ide-diagnostics/src/handlers/unresolved_field.rs b/crates/ide-diagnostics/src/handlers/unresolved_field.rs
index eb8eea69f6..76d624c47a 100644
--- a/crates/ide-diagnostics/src/handlers/unresolved_field.rs
+++ b/crates/ide-diagnostics/src/handlers/unresolved_field.rs
@@ -36,8 +36,8 @@ pub(crate) fn unresolved_field(
DiagnosticCode::RustcHardError("E0559"),
format!(
"no field `{}` on type `{}`{method_suffix}",
- d.name.display(ctx.sema.db),
- d.receiver.display(ctx.sema.db)
+ d.name.display(ctx.sema.db, ctx.edition),
+ d.receiver.display(ctx.sema.db, ctx.edition)
),
adjusted_display_range(ctx, d.expr, &|expr| {
Some(
diff --git a/crates/ide-diagnostics/src/handlers/unresolved_macro_call.rs b/crates/ide-diagnostics/src/handlers/unresolved_macro_call.rs
index c8ff54cba3..5b596123e7 100644
--- a/crates/ide-diagnostics/src/handlers/unresolved_macro_call.rs
+++ b/crates/ide-diagnostics/src/handlers/unresolved_macro_call.rs
@@ -13,7 +13,7 @@ pub(crate) fn unresolved_macro_call(
let bang = if d.is_bang { "!" } else { "" };
Diagnostic::new(
DiagnosticCode::RustcHardError("unresolved-macro-call"),
- format!("unresolved macro `{}{bang}`", d.path.display(ctx.sema.db)),
+ format!("unresolved macro `{}{bang}`", d.path.display(ctx.sema.db, ctx.edition)),
display_range,
)
.experimental()
diff --git a/crates/ide-diagnostics/src/handlers/unresolved_method.rs b/crates/ide-diagnostics/src/handlers/unresolved_method.rs
index 387d56b890..c0d038a238 100644
--- a/crates/ide-diagnostics/src/handlers/unresolved_method.rs
+++ b/crates/ide-diagnostics/src/handlers/unresolved_method.rs
@@ -30,8 +30,8 @@ pub(crate) fn unresolved_method(
DiagnosticCode::RustcHardError("E0599"),
format!(
"no method `{}` on type `{}`{suffix}",
- d.name.display(ctx.sema.db),
- d.receiver.display(ctx.sema.db)
+ d.name.display(ctx.sema.db, ctx.edition),
+ d.receiver.display(ctx.sema.db, ctx.edition)
),
adjusted_display_range(ctx, d.expr, &|expr| {
Some(
@@ -154,9 +154,10 @@ fn assoc_func_fix(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedMethodCall) -
};
let mut receiver_type_adt_name =
- receiver_type.as_adt()?.name(db).display_no_db().to_smolstr();
+ receiver_type.as_adt()?.name(db).display_no_db(ctx.edition).to_smolstr();
- let generic_parameters: Vec<SmolStr> = receiver_type.generic_parameters(db).collect();
+ let generic_parameters: Vec<SmolStr> =
+ receiver_type.generic_parameters(db, ctx.edition).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/crates/ide-diagnostics/src/handlers/unused_variables.rs b/crates/ide-diagnostics/src/handlers/unused_variables.rs
index bf19331d9f..c594754bd4 100644
--- a/crates/ide-diagnostics/src/handlers/unused_variables.rs
+++ b/crates/ide-diagnostics/src/handlers/unused_variables.rs
@@ -5,7 +5,7 @@ use ide_db::{
source_change::SourceChange,
FileRange, RootDatabase,
};
-use syntax::TextRange;
+use syntax::{Edition, TextRange};
use text_edit::TextEdit;
use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext};
@@ -42,7 +42,14 @@ pub(crate) fn unused_variables(
ast,
)
.with_fixes(name_range.and_then(|it| {
- fixes(ctx.sema.db, var_name, it.range, diagnostic_range.into(), ast.file_id.is_macro())
+ fixes(
+ ctx.sema.db,
+ var_name,
+ it.range,
+ diagnostic_range.into(),
+ ast.file_id.is_macro(),
+ ctx.edition,
+ )
}))
.experimental(),
)
@@ -54,6 +61,7 @@ fn fixes(
name_range: TextRange,
diagnostic_range: FileRange,
is_in_marco: bool,
+ edition: Edition,
) -> Option<Vec<Assist>> {
if is_in_marco {
return None;
@@ -63,14 +71,14 @@ fn fixes(
id: AssistId("unscore_unused_variable_name", AssistKind::QuickFix),
label: Label::new(format!(
"Rename unused {} to _{}",
- var_name.display(db),
- var_name.display(db)
+ var_name.display(db, edition),
+ var_name.display(db, edition)
)),
group: None,
target: diagnostic_range.range,
source_change: Some(SourceChange::from_text_edit(
diagnostic_range.file_id,
- TextEdit::replace(name_range, format!("_{}", var_name.display(db))),
+ TextEdit::replace(name_range, format!("_{}", var_name.display(db, edition))),
)),
command: None,
}])
diff --git a/crates/ide-diagnostics/src/lib.rs b/crates/ide-diagnostics/src/lib.rs
index a61c5f0cd4..bf320794af 100644
--- a/crates/ide-diagnostics/src/lib.rs
+++ b/crates/ide-diagnostics/src/lib.rs
@@ -90,7 +90,7 @@ use once_cell::sync::Lazy;
use stdx::never;
use syntax::{
ast::{self, AstNode},
- AstPtr, SyntaxNode, SyntaxNodePtr, TextRange,
+ AstPtr, Edition, SyntaxNode, SyntaxNodePtr, TextRange,
};
// FIXME: Make this an enum
@@ -279,6 +279,7 @@ struct DiagnosticsContext<'a> {
config: &'a DiagnosticsConfig,
sema: Semantics<'a, RootDatabase>,
resolve: &'a AssistResolveStrategy,
+ edition: Edition,
}
impl DiagnosticsContext<'_> {
@@ -359,12 +360,19 @@ pub fn semantic_diagnostics(
for node in parse.syntax().descendants() {
handlers::useless_braces::useless_braces(&mut res, file_id, &node);
handlers::field_shorthand::field_shorthand(&mut res, file_id, &node);
- handlers::json_is_not_rust::json_in_items(&sema, &mut res, file_id, &node, config);
+ handlers::json_is_not_rust::json_in_items(
+ &sema,
+ &mut res,
+ file_id,
+ &node,
+ config,
+ file_id.edition(),
+ );
}
let module = sema.file_to_module_def(file_id);
- let ctx = DiagnosticsContext { config, sema, resolve };
+ let ctx = DiagnosticsContext { config, sema, resolve, edition: file_id.edition() };
let mut diags = Vec::new();
match module {
@@ -490,6 +498,7 @@ pub fn semantic_diagnostics(
&mut rustc_stack,
&mut clippy_stack,
&mut diagnostics_of_range,
+ ctx.edition,
);
res.retain(|d| d.severity != Severity::Allow);
@@ -544,6 +553,7 @@ fn handle_lint_attributes(
rustc_stack: &mut FxHashMap<String, Vec<Severity>>,
clippy_stack: &mut FxHashMap<String, Vec<Severity>>,
diagnostics_of_range: &mut FxHashMap<InFile<SyntaxNode>, &mut Diagnostic>,
+ edition: Edition,
) {
let _g = tracing::info_span!("handle_lint_attributes").entered();
let file_id = sema.hir_file_for(root);
@@ -552,9 +562,15 @@ fn handle_lint_attributes(
match ev {
syntax::WalkEvent::Enter(node) => {
for attr in node.children().filter_map(ast::Attr::cast) {
- parse_lint_attribute(attr, rustc_stack, clippy_stack, |stack, severity| {
- stack.push(severity);
- });
+ parse_lint_attribute(
+ attr,
+ rustc_stack,
+ clippy_stack,
+ |stack, severity| {
+ stack.push(severity);
+ },
+ edition,
+ );
}
if let Some(it) =
diagnostics_of_range.get_mut(&InFile { file_id, value: node.clone() })
@@ -591,6 +607,7 @@ fn handle_lint_attributes(
rustc_stack,
clippy_stack,
diagnostics_of_range,
+ edition,
);
for stack in [&mut *rustc_stack, &mut *clippy_stack] {
stack.entry("__RA_EVERY_LINT".to_owned()).or_default().pop();
@@ -605,17 +622,24 @@ fn handle_lint_attributes(
rustc_stack,
clippy_stack,
diagnostics_of_range,
+ edition,
);
}
}
}
syntax::WalkEvent::Leave(node) => {
for attr in node.children().filter_map(ast::Attr::cast) {
- parse_lint_attribute(attr, rustc_stack, clippy_stack, |stack, severity| {
- if stack.pop() != Some(severity) {
- never!("Mismatched serevity in walking lint attributes");
- }
- });
+ parse_lint_attribute(
+ attr,
+ rustc_stack,
+ clippy_stack,
+ |stack, severity| {
+ if stack.pop() != Some(severity) {
+ never!("Mismatched serevity in walking lint attributes");
+ }
+ },
+ edition,
+ );
}
}
}
@@ -627,6 +651,7 @@ fn parse_lint_attribute(
rustc_stack: &mut FxHashMap<String, Vec<Severity>>,
clippy_stack: &mut FxHashMap<String, Vec<Severity>>,
job: impl Fn(&mut Vec<Severity>, Severity),
+ edition: Edition,
) {
let Some((tag, args_tt)) = attr.as_simple_call() else {
return;
@@ -637,7 +662,7 @@ fn parse_lint_attribute(
"forbid" | "deny" => Severity::Error,
_ => return,
};
- for lint in parse_tt_as_comma_sep_paths(args_tt).into_iter().flatten() {
+ for lint in parse_tt_as_comma_sep_paths(args_tt, edition).into_iter().flatten() {
if let Some(lint) = lint.as_single_name_ref() {
job(rustc_stack.entry(lint.to_string()).or_default(), severity);
}
diff --git a/crates/ide-ssr/src/matching.rs b/crates/ide-ssr/src/matching.rs
index 5f6d77c064..6569f0f555 100644
--- a/crates/ide-ssr/src/matching.rs
+++ b/crates/ide-ssr/src/matching.rs
@@ -8,6 +8,7 @@ use crate::{
};
use hir::{FileRange, ImportPathConfig, Semantics};
use ide_db::FxHashMap;
+use parser::Edition;
use std::{cell::Cell, iter::Peekable};
use syntax::{
ast::{self, AstNode, AstToken, HasGenericArgs},
@@ -626,6 +627,11 @@ 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 res = code_type
.autoderef(self.sema.db)
@@ -635,8 +641,8 @@ impl<'db, 'sema> Matcher<'db, 'sema> {
.ok_or_else(|| {
match_error!(
"Pattern type `{}` didn't match code type `{}`",
- pattern_type.display(self.sema.db),
- code_type.display(self.sema.db)
+ pattern_type.display(self.sema.db, edition),
+ code_type.display(self.sema.db, edition)
)
});
res
diff --git a/crates/ide-ssr/src/replacing.rs b/crates/ide-ssr/src/replacing.rs
index b4b83f62da..65756601f6 100644
--- a/crates/ide-ssr/src/replacing.rs
+++ b/crates/ide-ssr/src/replacing.rs
@@ -2,6 +2,7 @@
use ide_db::{FxHashMap, FxHashSet};
use itertools::Itertools;
+use parser::Edition;
use syntax::{
ast::{self, AstNode, AstToken},
SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, TextRange, TextSize,
@@ -33,7 +34,7 @@ fn matches_to_edit_at_offset(
for m in &matches.matches {
edit_builder.replace(
m.range.range.checked_sub(relative_start).unwrap(),
- render_replace(db, m, file_src, rules),
+ render_replace(db, m, file_src, rules, m.range.file_id.edition()),
);
}
edit_builder.finish()
@@ -54,6 +55,7 @@ struct ReplacementRenderer<'a> {
// is parsed, placeholders don't get split. e.g. if a template of `$a.to_string()` results in `1
// + 2.to_string()` then the placeholder value `1 + 2` was split and needs parenthesis.
placeholder_tokens_requiring_parenthesis: FxHashSet<SyntaxToken>,
+ edition: Edition,
}
fn render_replace(
@@ -61,6 +63,7 @@ fn render_replace(
match_info: &Match,
file_src: &str,
rules: &[ResolvedRule],
+ edition: Edition,
) -> String {
let rule = &rules[match_info.rule_index];
let template = rule
@@ -76,6 +79,7 @@ fn render_replace(
out: String::new(),
placeholder_tokens_requiring_parenthesis: FxHashSet::default(),
placeholder_tokens_by_range: FxHashMap::default(),
+ edition,
};
renderer.render_node(&template.node);
renderer.maybe_rerender_with_extra_parenthesis(&template.node);
@@ -105,7 +109,7 @@ impl ReplacementRenderer<'_> {
fn render_node(&mut self, node: &SyntaxNode) {
if let Some(mod_path) = self.match_info.rendered_template_paths.get(node) {
- self.out.push_str(&mod_path.display(self.db).to_string());
+ self.out.push_str(&mod_path.display(self.db, self.edition).to_string());
// Emit everything except for the segment's name-ref, since we already effectively
// emitted that as part of `mod_path`.
if let Some(path) = ast::Path::cast(node.clone()) {
diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs
index e9e5240897..cad0d06eea 100644
--- a/crates/ide/src/doc_links.rs
+++ b/crates/ide/src/doc_links.rs
@@ -413,7 +413,8 @@ fn rewrite_url_link(db: &RootDatabase, def: Definition, target: &str) -> Option<
fn mod_path_of_def(db: &RootDatabase, def: Definition) -> Option<String> {
def.canonical_module_path(db).map(|it| {
let mut path = String::new();
- it.flat_map(|it| it.name(db)).for_each(|name| format_to!(path, "{}/", name.display(db)));
+ it.flat_map(|it| it.name(db))
+ .for_each(|name| format_to!(path, "{}/", name.unescaped().display(db)));
path
})
}
@@ -588,9 +589,11 @@ fn filename_and_frag_for_def(
let res = match def {
Definition::Adt(adt) => match adt {
- Adt::Struct(s) => format!("struct.{}.html", s.name(db).display(db.upcast())),
- Adt::Enum(e) => format!("enum.{}.html", e.name(db).display(db.upcast())),
- Adt::Union(u) => format!("union.{}.html", u.name(db).display(db.upcast())),
+ Adt::Struct(s) => {
+ format!("struct.{}.html", s.name(db).unescaped().display(db.upcast()))
+ }
+ Adt::Enum(e) => format!("enum.{}.html", e.name(db).unescaped().display(db.upcast())),
+ Adt::Union(u) => format!("union.{}.html", u.name(db).unescaped().display(db.upcast())),
},
Definition::Module(m) => match m.name(db) {
// `#[doc(keyword = "...")]` is internal used only by rust compiler
@@ -599,34 +602,48 @@ fn filename_and_frag_for_def(
Some(kw) => {
format!("keyword.{}.html", kw)
}
- None => format!("{}/index.html", name.display(db.upcast())),
+ None => format!("{}/index.html", name.unescaped().display(db.upcast())),
}
}
None => String::from("index.html"),
},
- Definition::Trait(t) => format!("trait.{}.html", t.name(db).display(db.upcast())),
- Definition::TraitAlias(t) => format!("traitalias.{}.html", t.name(db).display(db.upcast())),
- Definition::TypeAlias(t) => format!("type.{}.html", t.name(db).display(db.upcast())),
- Definition::BuiltinType(t) => format!("primitive.{}.html", t.name().display(db.upcast())),
- Definition::Function(f) => format!("fn.{}.html", f.name(db).display(db.upcast())),
+ Definition::Trait(t) => {
+ format!("trait.{}.html", t.name(db).unescaped().display(db.upcast()))
+ }
+ Definition::TraitAlias(t) => {
+ format!("traitalias.{}.html", t.name(db).unescaped().display(db.upcast()))
+ }
+ Definition::TypeAlias(t) => {
+ format!("type.{}.html", t.name(db).unescaped().display(db.upcast()))
+ }
+ Definition::BuiltinType(t) => {
+ format!("primitive.{}.html", t.name().unescaped().display(db.upcast()))
+ }
+ Definition::Function(f) => {
+ format!("fn.{}.html", f.name(db).unescaped().display(db.upcast()))
+ }
Definition::Variant(ev) => {
format!(
"enum.{}.html#variant.{}",
- ev.parent_enum(db).name(db).display(db.upcast()),
- ev.name(db).display(db.upcast())
+ ev.parent_enum(db).name(db).unescaped().display(db.upcast()),
+ ev.name(db).unescaped().display(db.upcast())
)
}
- Definition::Const(c) => format!("const.{}.html", c.name(db)?.display(db.upcast())),
- Definition::Static(s) => format!("static.{}.html", s.name(db).display(db.upcast())),
+ Definition::Const(c) => {
+ format!("const.{}.html", c.name(db)?.unescaped().display(db.upcast()))
+ }
+ Definition::Static(s) => {
+ format!("static.{}.html", s.name(db).unescaped().display(db.upcast()))
+ }
Definition::Macro(mac) => match mac.kind(db) {
hir::MacroKind::Declarative
| hir::MacroKind::BuiltIn
| hir::MacroKind::Attr
| hir::MacroKind::ProcMacro => {
- format!("macro.{}.html", mac.name(db).display(db.upcast()))
+ format!("macro.{}.html", mac.name(db).unescaped().display(db.upcast()))
}
hir::MacroKind::Derive => {
- format!("derive.{}.html", mac.name(db).display(db.upcast()))
+ format!("derive.{}.html", mac.name(db).unescaped().display(db.upcast()))
}
},
Definition::Field(field) => {
@@ -639,7 +656,7 @@ fn filename_and_frag_for_def(
return Some((
def,
file,
- Some(format!("structfield.{}", field.name(db).display(db.upcast()))),
+ Some(format!("structfield.{}", field.name(db).unescaped().display(db.upcast()))),
));
}
Definition::SelfType(impl_) => {
@@ -649,7 +666,7 @@ fn filename_and_frag_for_def(
return Some((adt, file, Some(String::from("impl"))));
}
Definition::ExternCrateDecl(it) => {
- format!("{}/index.html", it.name(db).display(db.upcast()))
+ format!("{}/index.html", it.name(db).unescaped().display(db.upcast()))
}
Definition::Local(_)
| Definition::GenericParam(_)
@@ -679,14 +696,16 @@ fn get_assoc_item_fragment(db: &dyn HirDatabase, assoc_item: hir::AssocItem) ->
// Rustdoc makes this decision based on whether a method 'has defaultness'.
// Currently this is only the case for provided trait methods.
if is_trait_method && !function.has_body(db) {
- format!("tymethod.{}", function.name(db).display(db.upcast()))
+ format!("tymethod.{}", function.name(db).unescaped().display(db.upcast()))
} else {
- format!("method.{}", function.name(db).display(db.upcast()))
+ format!("method.{}", function.name(db).unescaped().display(db.upcast()))
}
}
AssocItem::Const(constant) => {
- format!("associatedconstant.{}", constant.name(db)?.display(db.upcast()))
+ format!("associatedconstant.{}", constant.name(db)?.unescaped().display(db.upcast()))
+ }
+ AssocItem::TypeAlias(ty) => {
+ format!("associatedtype.{}", ty.name(db).unescaped().display(db.upcast()))
}
- AssocItem::TypeAlias(ty) => format!("associatedtype.{}", ty.name(db).display(db.upcast())),
})
}
diff --git a/crates/ide/src/expand_macro.rs b/crates/ide/src/expand_macro.rs
index c8fe45c9cf..9788c01544 100644
--- a/crates/ide/src/expand_macro.rs
+++ b/crates/ide/src/expand_macro.rs
@@ -3,6 +3,7 @@ use ide_db::{
helpers::pick_best_token, syntax_helpers::insert_whitespace_into_node::insert_ws_into, FileId,
RootDatabase,
};
+use span::Edition;
use syntax::{ast, ted, AstNode, NodeOrToken, SyntaxKind, SyntaxNode, T};
use crate::FilePosition;
@@ -83,7 +84,14 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option<
if let Some(item) = ast::Item::cast(node.clone()) {
if let Some(def) = sema.resolve_attr_macro_call(&item) {
break (
- def.name(db).display(db).to_string(),
+ def.name(db)
+ .display(
+ db,
+ sema.attach_first_edition(position.file_id)
+ .map(|it| it.edition())
+ .unwrap_or(Edition::CURRENT),
+ )
+ .to_string(),
expand_macro_recur(&sema, &item)?,
SyntaxKind::MACRO_ITEMS,
);
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs
index b1d2b34ea4..6a6fbcb9a6 100644
--- a/crates/ide/src/goto_definition.rs
+++ b/crates/ide/src/goto_definition.rs
@@ -44,6 +44,8 @@ pub(crate) fn goto_definition(
) -> Option<RangeInfo<Vec<NavigationTarget>>> {
let sema = &Semantics::new(db);
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 original_token = pick_best_token(file.token_at_offset(offset), |kind| match kind {
IDENT
| INT_NUMBER
@@ -55,7 +57,7 @@ pub(crate) fn goto_definition(
| COMMENT => 4,
// index and prefix ops
T!['['] | T![']'] | T![?] | T![*] | T![-] | T![!] => 3,
- kind if kind.is_keyword(Edition::CURRENT) => 2,
+ kind if kind.is_keyword(edition) => 2,
T!['('] | T![')'] => 2,
kind if kind.is_trivia() => 0,
_ => 1,
diff --git a/crates/ide/src/highlight_related.rs b/crates/ide/src/highlight_related.rs
index 946dca85d4..a88261df10 100644
--- a/crates/ide/src/highlight_related.rs
+++ b/crates/ide/src/highlight_related.rs
@@ -11,7 +11,7 @@ use ide_db::{
},
FxHashMap, FxHashSet, RootDatabase,
};
-use span::{Edition, EditionedFileId};
+use span::EditionedFileId;
use syntax::{
ast::{self, HasLoopBody},
match_ast, AstNode,
@@ -65,7 +65,7 @@ pub(crate) fn highlight_related(
let token = pick_best_token(syntax.token_at_offset(offset), |kind| match kind {
T![?] => 4, // prefer `?` when the cursor is sandwiched like in `await$0?`
T![->] => 4,
- kind if kind.is_keyword(Edition::CURRENT) => 3,
+ kind if kind.is_keyword(file_id.edition()) => 3,
IDENT | INT_NUMBER => 2,
T![|] => 1,
_ => 0,
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index 75f8ac2d2b..6c646cf4ee 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -67,7 +67,11 @@ pub enum HoverAction {
}
impl HoverAction {
- fn goto_type_from_targets(db: &RootDatabase, targets: Vec<hir::ModuleDef>) -> Option<Self> {
+ fn goto_type_from_targets(
+ db: &RootDatabase,
+ targets: Vec<hir::ModuleDef>,
+ edition: Edition,
+ ) -> Option<Self> {
let targets = targets
.into_iter()
.filter_map(|it| {
@@ -75,7 +79,8 @@ impl HoverAction {
mod_path: render::path(
db,
it.module(db)?,
- it.name(db).map(|name| name.display(db).to_string()),
+ it.name(db).map(|name| name.display(db, edition).to_string()),
+ edition,
),
nav: it.try_to_nav(db)?.call_site(),
})
@@ -111,10 +116,12 @@ pub(crate) fn hover(
) -> Option<RangeInfo<HoverResult>> {
let sema = &hir::Semantics::new(db);
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 mut res = if range.is_empty() {
- hover_simple(sema, FilePosition { file_id, offset: range.start() }, file, config)
+ hover_simple(sema, FilePosition { file_id, offset: range.start() }, file, config, edition)
} else {
- hover_ranged(sema, frange, file, config)
+ hover_ranged(sema, frange, file, config, edition)
}?;
if let HoverDocFormat::PlainText = config.format {
@@ -129,6 +136,7 @@ fn hover_simple(
FilePosition { file_id, offset }: FilePosition,
file: SyntaxNode,
config: &HoverConfig,
+ edition: Edition,
) -> Option<RangeInfo<HoverResult>> {
let original_token = pick_best_token(file.token_at_offset(offset), |kind| match kind {
IDENT
@@ -141,7 +149,7 @@ fn hover_simple(
| T![_] => 4,
// index and prefix ops and closure pipe
T!['['] | T![']'] | T![?] | T![*] | T![-] | T![!] | T![|] => 3,
- kind if kind.is_keyword(Edition::CURRENT) => 2,
+ kind if kind.is_keyword(edition) => 2,
T!['('] | T![')'] => 2,
kind if kind.is_trivia() => 0,
_ => 1,
@@ -150,7 +158,7 @@ fn hover_simple(
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, &node, None, config);
+ let res = hover_for_definition(sema, file_id, def, &node, None, config, edition);
Some(RangeInfo::new(range, res))
});
}
@@ -165,6 +173,7 @@ fn hover_simple(
&original_token.parent()?,
None,
config,
+ edition,
);
return Some(RangeInfo::new(range, res));
}
@@ -240,7 +249,7 @@ fn hover_simple(
.flatten()
.unique_by(|&(def, _, _)| def)
.map(|(def, macro_arm, node)| {
- hover_for_definition(sema, file_id, def, &node, macro_arm, config)
+ hover_for_definition(sema, file_id, def, &node, macro_arm, config, edition)
})
.reduce(|mut acc: HoverResult, HoverResult { markup, actions }| {
acc.actions.extend(actions);
@@ -249,9 +258,9 @@ fn hover_simple(
})
})
// try keywords
- .or_else(|| descended().find_map(|token| render::keyword(sema, config, token)))
+ .or_else(|| descended().find_map(|token| render::keyword(sema, config, token, edition)))
// try _ hovers
- .or_else(|| descended().find_map(|token| render::underscore(sema, config, token)))
+ .or_else(|| descended().find_map(|token| render::underscore(sema, config, token, edition)))
// try rest pattern hover
.or_else(|| {
descended().find_map(|token| {
@@ -266,7 +275,7 @@ fn hover_simple(
let record_pat =
record_pat_field_list.syntax().parent().and_then(ast::RecordPat::cast)?;
- Some(render::struct_rest_pat(sema, config, &record_pat))
+ Some(render::struct_rest_pat(sema, config, &record_pat, edition))
})
})
// try () call hovers
@@ -283,7 +292,7 @@ fn hover_simple(
_ => return None,
}
};
- render::type_info_of(sema, config, &Either::Left(call_expr))
+ render::type_info_of(sema, config, &Either::Left(call_expr), edition)
})
})
// try closure
@@ -293,12 +302,12 @@ fn hover_simple(
return None;
}
let c = token.parent().and_then(|x| x.parent()).and_then(ast::ClosureExpr::cast)?;
- render::closure_expr(sema, config, c)
+ render::closure_expr(sema, config, c, edition)
})
})
// tokens
.or_else(|| {
- render::literal(sema, original_token.clone())
+ render::literal(sema, original_token.clone(), edition)
.map(|markup| HoverResult { markup, actions: vec![] })
});
@@ -313,6 +322,7 @@ fn hover_ranged(
FileRange { range, .. }: FileRange,
file: SyntaxNode,
config: &HoverConfig,
+ edition: Edition,
) -> Option<RangeInfo<HoverResult>> {
// FIXME: make this work in attributes
let expr_or_pat = file
@@ -321,15 +331,17 @@ fn hover_ranged(
.take_while(|it| ast::MacroCall::can_cast(it.kind()) || !ast::Item::can_cast(it.kind()))
.find_map(Either::<ast::Expr, ast::Pat>::cast)?;
let res = match &expr_or_pat {
- Either::Left(ast::Expr::TryExpr(try_expr)) => render::try_expr(sema, config, try_expr),
+ Either::Left(ast::Expr::TryExpr(try_expr)) => {
+ render::try_expr(sema, config, try_expr, edition)
+ }
Either::Left(ast::Expr::PrefixExpr(prefix_expr))
if prefix_expr.op_kind() == Some(ast::UnaryOp::Deref) =>
{
- render::deref_expr(sema, config, prefix_expr)
+ render::deref_expr(sema, config, prefix_expr, edition)
}
_ => None,
};
- let res = res.or_else(|| render::type_info_of(sema, config, &expr_or_pat));
+ let res = res.or_else(|| render::type_info_of(sema, config, &expr_or_pat, edition));
res.map(|it| {
let range = match expr_or_pat {
Either::Left(it) => it.syntax().text_range(),
@@ -347,6 +359,7 @@ pub(crate) fn hover_for_definition(
scope_node: &SyntaxNode,
macro_arm: Option<u32>,
config: &HoverConfig,
+ edition: Edition,
) -> HoverResult {
let famous_defs = match &def {
Definition::BuiltinType(_) => sema.scope(scope_node).map(|it| FamousDefs(sema, it.krate())),
@@ -370,15 +383,22 @@ pub(crate) fn hover_for_definition(
};
let notable_traits = def_ty.map(|ty| notable_traits(db, &ty)).unwrap_or_default();
- let markup =
- render::definition(sema.db, def, famous_defs.as_ref(), &notable_traits, macro_arm, config);
+ let markup = render::definition(
+ sema.db,
+ def,
+ famous_defs.as_ref(),
+ &notable_traits,
+ macro_arm,
+ config,
+ edition,
+ );
HoverResult {
markup: render::process_markup(sema.db, def, &markup, config),
actions: [
show_fn_references_action(sema.db, def),
show_implementations_action(sema.db, def),
runnable_action(sema, def, file_id),
- goto_type_action_for_def(sema.db, def, &notable_traits),
+ goto_type_action_for_def(sema.db, def, &notable_traits, edition),
]
.into_iter()
.flatten()
@@ -470,6 +490,7 @@ fn goto_type_action_for_def(
db: &RootDatabase,
def: Definition,
notable_traits: &[(hir::Trait, Vec<(Option<hir::Type>, hir::Name)>)],
+ edition: Edition,
) -> Option<HoverAction> {
let mut targets: Vec<hir::ModuleDef> = Vec::new();
let mut push_new_def = |item: hir::ModuleDef| {
@@ -500,13 +521,13 @@ fn goto_type_action_for_def(
Definition::GenericParam(hir::GenericParam::ConstParam(it)) => it.ty(db),
Definition::Field(field) => field.ty(db),
Definition::Function(function) => function.ret_type(db),
- _ => return HoverAction::goto_type_from_targets(db, targets),
+ _ => return HoverAction::goto_type_from_targets(db, targets, edition),
};
walk_and_push_ty(db, &ty, &mut push_new_def);
}
- HoverAction::goto_type_from_targets(db, targets)
+ HoverAction::goto_type_from_targets(db, targets, edition)
}
fn walk_and_push_ty(
diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs
index 13b7ba1e2b..3e41b42be4 100644
--- a/crates/ide/src/hover/render.rs
+++ b/crates/ide/src/hover/render.rs
@@ -35,27 +35,30 @@ pub(super) fn type_info_of(
sema: &Semantics<'_, RootDatabase>,
_config: &HoverConfig,
expr_or_pat: &Either<ast::Expr, ast::Pat>,
+ edition: Edition,
) -> Option<HoverResult> {
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)
+ type_info(sema, _config, ty_info, edition)
}
pub(super) fn closure_expr(
sema: &Semantics<'_, RootDatabase>,
config: &HoverConfig,
c: ast::ClosureExpr,
+ edition: Edition,
) -> Option<HoverResult> {
let TypeInfo { original, .. } = sema.type_of_expr(&c.into())?;
- closure_ty(sema, config, &TypeInfo { original, adjusted: None })
+ closure_ty(sema, config, &TypeInfo { original, adjusted: None }, edition)
}
pub(super) fn try_expr(
sema: &Semantics<'_, RootDatabase>,
_config: &HoverConfig,
try_expr: &ast::TryExpr,
+ edition: Edition,
) -> Option<HoverResult> {
let inner_ty = sema.type_of_expr(&try_expr.expr()?)?.original;
let mut ancestors = try_expr.syntax().ancestors();
@@ -118,12 +121,12 @@ pub(super) fn try_expr(
};
walk_and_push_ty(sema.db, &inner_ty, &mut push_new_def);
walk_and_push_ty(sema.db, &body_ty, &mut push_new_def);
- if let Some(actions) = HoverAction::goto_type_from_targets(sema.db, targets) {
+ if let Some(actions) = HoverAction::goto_type_from_targets(sema.db, targets, edition) {
res.actions.push(actions);
}
- let inner_ty = inner_ty.display(sema.db).to_string();
- let body_ty = body_ty.display(sema.db).to_string();
+ let inner_ty = inner_ty.display(sema.db, edition).to_string();
+ let body_ty = body_ty.display(sema.db, edition).to_string();
let ty_len_max = inner_ty.len().max(body_ty.len());
let l = "Propagated as: ".len() - " Type: ".len();
@@ -147,6 +150,7 @@ pub(super) fn deref_expr(
sema: &Semantics<'_, RootDatabase>,
_config: &HoverConfig,
deref_expr: &ast::PrefixExpr,
+ edition: Edition,
) -> Option<HoverResult> {
let inner_ty = sema.type_of_expr(&deref_expr.expr()?)?.original;
let TypeInfo { original, adjusted } =
@@ -164,9 +168,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).to_string();
- let adjusted = adjusted_ty.display(sema.db).to_string();
- let inner = inner_ty.display(sema.db).to_string();
+ 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 type_len = "To type: ".len();
let coerced_len = "Coerced to: ".len();
let deref_len = "Dereferenced from: ".len();
@@ -184,8 +188,8 @@ pub(super) fn deref_expr(
)
.into()
} else {
- let original = original.display(sema.db).to_string();
- let inner = inner_ty.display(sema.db).to_string();
+ let original = original.display(sema.db, edition).to_string();
+ let inner = inner_ty.display(sema.db, edition).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);
@@ -198,7 +202,7 @@ pub(super) fn deref_expr(
)
.into()
};
- if let Some(actions) = HoverAction::goto_type_from_targets(sema.db, targets) {
+ if let Some(actions) = HoverAction::goto_type_from_targets(sema.db, targets, edition) {
res.actions.push(actions);
}
@@ -209,6 +213,7 @@ pub(super) fn underscore(
sema: &Semantics<'_, RootDatabase>,
config: &HoverConfig,
token: &SyntaxToken,
+ edition: Edition,
) -> Option<HoverResult> {
if token.kind() != T![_] {
return None;
@@ -217,8 +222,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))),
- ast::WildcardPat(it) => return type_info_of(sema, config, &Either::Right(ast::Pat::WildcardPat(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),
_ => return None,
}
};
@@ -251,16 +256,18 @@ pub(super) fn keyword(
sema: &Semantics<'_, RootDatabase>,
config: &HoverConfig,
token: &SyntaxToken,
+ edition: Edition,
) -> Option<HoverResult> {
- if !token.kind().is_keyword(Edition::CURRENT) || !config.documentation || !config.keywords {
+ if !token.kind().is_keyword(edition) || !config.documentation || !config.keywords {
return None;
}
let parent = token.parent()?;
let famous_defs = FamousDefs(sema, sema.scope(&parent)?.krate());
- let KeywordHint { description, keyword_mod, actions } = keyword_hints(sema, token, parent);
+ let KeywordHint { description, keyword_mod, actions } =
+ keyword_hints(sema, token, parent, edition);
- let doc_owner = find_std_module(&famous_defs, &keyword_mod)?;
+ let doc_owner = find_std_module(&famous_defs, &keyword_mod, edition)?;
let docs = doc_owner.docs(sema.db)?;
let markup = process_markup(
sema.db,
@@ -278,6 +285,7 @@ pub(super) fn struct_rest_pat(
sema: &Semantics<'_, RootDatabase>,
_config: &HoverConfig,
pattern: &ast::RecordPat,
+ edition: Edition,
) -> HoverResult {
let missing_fields = sema.record_pattern_missing_fields(pattern);
@@ -299,7 +307,7 @@ pub(super) fn struct_rest_pat(
res.markup = {
let mut s = String::from(".., ");
for (f, _) in &missing_fields {
- s += f.display(sema.db).to_string().as_ref();
+ s += f.display(sema.db, edition).to_string().as_ref();
s += ", ";
}
// get rid of trailing comma
@@ -307,7 +315,7 @@ pub(super) fn struct_rest_pat(
Markup::fenced_block(&s)
};
- if let Some(actions) = HoverAction::goto_type_from_targets(sema.db, targets) {
+ if let Some(actions) = HoverAction::goto_type_from_targets(sema.db, targets, edition) {
res.actions.push(actions);
}
res
@@ -366,7 +374,7 @@ pub(super) fn process_markup(
Markup::from(markup)
}
-fn definition_owner_name(db: &RootDatabase, def: &Definition) -> Option<String> {
+fn definition_owner_name(db: &RootDatabase, def: &Definition, edition: Edition) -> Option<String> {
match def {
Definition::Field(f) => Some(f.parent_def(db).name(db)),
Definition::Local(l) => l.parent(db).name(db),
@@ -385,17 +393,22 @@ fn definition_owner_name(db: &RootDatabase, def: &Definition) -> Option<String>
}
}
}
- .map(|name| name.display(db).to_string())
+ .map(|name| name.display(db, edition).to_string())
}
-pub(super) fn path(db: &RootDatabase, module: hir::Module, item_name: Option<String>) -> String {
+pub(super) fn path(
+ db: &RootDatabase,
+ module: hir::Module,
+ item_name: Option<String>,
+ edition: Edition,
+) -> String {
let crate_name =
db.crate_graph()[module.krate().into()].display_name.as_ref().map(|it| it.to_string());
let module_path = module
.path_to_root(db)
.into_iter()
.rev()
- .flat_map(|it| it.name(db).map(|name| name.display(db).to_string()));
+ .flat_map(|it| it.name(db).map(|name| name.display(db, edition).to_string()));
crate_name.into_iter().chain(module_path).chain(item_name).join("::")
}
@@ -406,39 +419,42 @@ pub(super) fn definition(
notable_traits: &[(Trait, Vec<(Option<Type>, Name)>)],
macro_arm: Option<u32>,
config: &HoverConfig,
+ edition: Edition,
) -> Markup {
- let mod_path = definition_mod_path(db, &def);
+ let mod_path = definition_mod_path(db, &def, edition);
let label = match def {
Definition::Trait(trait_) => {
- trait_.display_limited(db, config.max_trait_assoc_items_count).to_string()
+ trait_.display_limited(db, config.max_trait_assoc_items_count, edition).to_string()
}
Definition::Adt(adt @ (Adt::Struct(_) | Adt::Union(_))) => {
- adt.display_limited(db, config.max_fields_count).to_string()
+ adt.display_limited(db, config.max_fields_count, edition).to_string()
}
Definition::Variant(variant) => {
- variant.display_limited(db, config.max_fields_count).to_string()
+ variant.display_limited(db, config.max_fields_count, edition).to_string()
}
Definition::Adt(adt @ Adt::Enum(_)) => {
- adt.display_limited(db, config.max_enum_variants_count).to_string()
+ adt.display_limited(db, config.max_enum_variants_count, edition).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).to_string(),
- None => self_ty.display(db).to_string(),
+ Some(adt) => adt.display_limited(db, config.max_fields_count, edition).to_string(),
+ None => self_ty.display(db, edition).to_string(),
}
}
Definition::Macro(it) => {
- let mut label = it.display(db).to_string();
+ let mut label = it.display(db, edition).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).to_string(),
- _ => def.label(db),
+ Definition::Function(fn_) => {
+ fn_.display_with_container_bounds(db, true, edition).to_string()
+ }
+ _ => def.label(db, edition),
};
- let docs = def.docs(db, famous_defs);
+ let docs = def.docs(db, famous_defs, edition);
let value = (|| match def {
Definition::Variant(it) => {
if !it.parent_enum(db).is_data_carrying(db) {
@@ -453,7 +469,7 @@ pub(super) fn definition(
}
}
Definition::Const(it) => {
- let body = it.render_eval(db);
+ let body = it.render_eval(db, edition);
match body {
Ok(it) => Some(it),
Err(_) => {
@@ -511,7 +527,7 @@ pub(super) fn definition(
};
let mut desc = String::new();
- if let Some(notable_traits) = render_notable_trait_comment(db, notable_traits) {
+ if let Some(notable_traits) = render_notable_trait_comment(db, notable_traits, edition) {
desc.push_str(&notable_traits);
desc.push('\n');
}
@@ -528,7 +544,11 @@ pub(super) fn definition(
markup(docs.map(Into::into), desc, mod_path)
}
-pub(super) fn literal(sema: &Semantics<'_, RootDatabase>, token: SyntaxToken) -> Option<Markup> {
+pub(super) fn literal(
+ sema: &Semantics<'_, RootDatabase>,
+ token: SyntaxToken,
+ edition: Edition,
+) -> Option<Markup> {
let lit = token.parent().and_then(ast::Literal::cast)?;
let ty = if let Some(p) = lit.syntax().parent().and_then(ast::Pat::cast) {
sema.type_of_pat(&p)?
@@ -575,7 +595,7 @@ pub(super) fn literal(sema: &Semantics<'_, RootDatabase>, token: SyntaxToken) ->
_ => return None
}
};
- let ty = ty.display(sema.db);
+ let ty = ty.display(sema.db, edition);
let mut s = format!("```rust\n{ty}\n```\n___\n\n");
match value {
@@ -594,6 +614,7 @@ pub(super) fn literal(sema: &Semantics<'_, RootDatabase>, token: SyntaxToken) ->
fn render_notable_trait_comment(
db: &RootDatabase,
notable_traits: &[(Trait, Vec<(Option<Type>, Name)>)],
+ edition: Edition,
) -> Option<String> {
let mut desc = String::new();
let mut needs_impl_header = true;
@@ -603,17 +624,17 @@ fn render_notable_trait_comment(
} else {
", "
});
- format_to!(desc, "{}", trait_.name(db).display(db),);
+ format_to!(desc, "{}", trait_.name(db).display(db, edition));
if !assoc_types.is_empty() {
desc.push('<');
format_to!(
desc,
"{}",
assoc_types.iter().format_with(", ", |(ty, name), f| {
- f(&name.display(db))?;
+ f(&name.display(db, edition))?;
f(&" = ")?;
match ty {
- Some(ty) => f(&ty.display(db)),
+ Some(ty) => f(&ty.display(db, edition)),
None => f(&"?"),
}
})
@@ -628,8 +649,9 @@ fn type_info(
sema: &Semantics<'_, RootDatabase>,
config: &HoverConfig,
ty: TypeInfo,
+ edition: Edition,
) -> Option<HoverResult> {
- if let Some(res) = closure_ty(sema, config, &ty) {
+ if let Some(res) = closure_ty(sema, config, &ty, edition) {
return Some(res);
};
let db = sema.db;
@@ -655,17 +677,17 @@ fn type_info(
} else {
", "
});
- format_to!(desc, "{}", trait_.name(db).display(db),);
+ format_to!(desc, "{}", trait_.name(db).display(db, edition));
if !assoc_types.is_empty() {
desc.push('<');
format_to!(
desc,
"{}",
assoc_types.into_iter().format_with(", ", |(ty, name), f| {
- f(&name.display(db))?;
+ f(&name.display(db, edition))?;
f(&" = ")?;
match ty {
- Some(ty) => f(&ty.display(db)),
+ Some(ty) => f(&ty.display(db, edition)),
None => f(&"?"),
}
})
@@ -679,8 +701,8 @@ fn type_info(
desc
};
- let original = original.display(db).to_string();
- let adjusted = adjusted_ty.display(db).to_string();
+ let original = original.display(db, edition).to_string();
+ let adjusted = adjusted_ty.display(db, edition).to_string();
let static_text_diff_len = "Coerced to: ".len() - "Type: ".len();
format!(
"```text\nType: {:>apad$}\nCoerced to: {:>opad$}\n{notable}```\n",
@@ -691,14 +713,15 @@ fn type_info(
)
.into()
} else {
- let mut desc = match render_notable_trait_comment(db, &notable_traits(db, &original)) {
- Some(desc) => desc + "\n",
- None => String::new(),
- };
- format_to!(desc, "{}", original.display(db));
+ let mut desc =
+ match render_notable_trait_comment(db, &notable_traits(db, &original), edition) {
+ Some(desc) => desc + "\n",
+ None => String::new(),
+ };
+ format_to!(desc, "{}", original.display(db, edition));
Markup::fenced_block(&desc)
};
- if let Some(actions) = HoverAction::goto_type_from_targets(db, targets) {
+ if let Some(actions) = HoverAction::goto_type_from_targets(db, targets, edition) {
res.actions.push(actions);
}
Some(res)
@@ -708,6 +731,7 @@ fn closure_ty(
sema: &Semantics<'_, RootDatabase>,
config: &HoverConfig,
TypeInfo { original, adjusted }: &TypeInfo,
+ edition: Edition,
) -> Option<HoverResult> {
let c = original.as_closure()?;
let mut captures_rendered = c.captured_items(sema.db)
@@ -740,12 +764,12 @@ fn closure_ty(
walk_and_push_ty(sema.db, adjusted_ty, &mut push_new_def);
format!(
"\nCoerced to: {}",
- adjusted_ty.display(sema.db).with_closure_style(hir::ClosureStyle::ImplFn)
+ adjusted_ty.display(sema.db, edition).with_closure_style(hir::ClosureStyle::ImplFn)
)
} else {
String::new()
};
- let mut markup = format!("```rust\n{}", c.display_with_id(sema.db),);
+ let mut markup = format!("```rust\n{}", c.display_with_id(sema.db, edition));
if let Some(layout) =
render_memory_layout(config.memory_layout, || original.layout(sema.db), |_| None, |_| None)
@@ -758,23 +782,23 @@ fn closure_ty(
format_to!(
markup,
"\n{}\n```{adjusted}\n\n## Captures\n{}",
- c.display_with_impl(sema.db),
+ c.display_with_impl(sema.db, edition),
captures_rendered,
);
let mut res = HoverResult::default();
- if let Some(actions) = HoverAction::goto_type_from_targets(sema.db, targets) {
+ if let Some(actions) = HoverAction::goto_type_from_targets(sema.db, targets, edition) {
res.actions.push(actions);
}
res.markup = markup.into();
Some(res)
}
-fn definition_mod_path(db: &RootDatabase, def: &Definition) -> Option<String> {
+fn definition_mod_path(db: &RootDatabase, def: &Definition, edition: Edition) -> Option<String> {
if matches!(def, Definition::GenericParam(_) | Definition::Local(_) | Definition::Label(_)) {
return None;
}
- def.module(db).map(|module| path(db, module, definition_owner_name(db, def)))
+ def.module(db).map(|module| path(db, module, definition_owner_name(db, def, edition), edition))
}
fn markup(docs: Option<String>, desc: String, mod_path: Option<String>) -> Markup {
@@ -793,12 +817,16 @@ fn markup(docs: Option<String>, desc: String, mod_path: Option<String>) -> Marku
buf.into()
}
-fn find_std_module(famous_defs: &FamousDefs<'_, '_>, name: &str) -> Option<hir::Module> {
+fn find_std_module(
+ famous_defs: &FamousDefs<'_, '_>,
+ name: &str,
+ edition: Edition,
+) -> Option<hir::Module> {
let db = famous_defs.0.db;
let std_crate = famous_defs.std()?;
let std_root_module = std_crate.root_module();
std_root_module.children(db).find(|module| {
- module.name(db).map_or(false, |module| module.display(db).to_string() == name)
+ module.name(db).map_or(false, |module| module.display(db, edition).to_string() == name)
})
}
@@ -889,6 +917,7 @@ fn keyword_hints(
sema: &Semantics<'_, RootDatabase>,
token: &SyntaxToken,
parent: syntax::SyntaxNode,
+ edition: Edition,
) -> KeywordHint {
match token.kind() {
T![await] | T![loop] | T![match] | T![unsafe] | T![as] | T![try] | T![if] | T![else] => {
@@ -906,12 +935,12 @@ 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));
+ let description = format!("{}: {}", token.text(), ty.display(sema.db, edition));
KeywordHint {
description,
keyword_mod,
- actions: HoverAction::goto_type_from_targets(sema.db, targets)
+ actions: HoverAction::goto_type_from_targets(sema.db, targets, edition)
.into_iter()
.collect(),
}
diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs
index 18f0aeba29..8b60e562d7 100644
--- a/crates/ide/src/hover/tests.rs
+++ b/crates/ide/src/hover/tests.rs
@@ -8630,3 +8630,75 @@ fn main() {
"#]],
);
}
+
+#[test]
+fn raw_keyword_different_editions() {
+ check(
+ r#"
+//- /lib1.rs crate:with_edition_2015 edition:2015
+pub fn dyn() {}
+
+//- /lib2.rs crate:with_edition_2018 edition:2018 deps:with_edition_2015 new_source_root:local
+fn foo() {
+ with_edition_2015::r#dyn$0();
+}
+ "#,
+ expect![[r#"
+ *r#dyn*
+
+ ```rust
+ with_edition_2015
+ ```
+
+ ```rust
+ pub fn r#dyn()
+ ```
+ "#]],
+ );
+
+ check(
+ r#"
+//- /lib1.rs crate:with_edition_2018 edition:2018
+pub fn r#dyn() {}
+
+//- /lib2.rs crate:with_edition_2015 edition:2015 deps:with_edition_2018 new_source_root:local
+fn foo() {
+ with_edition_2018::dyn$0();
+}
+ "#,
+ expect![[r#"
+ *dyn*
+
+ ```rust
+ with_edition_2018
+ ```
+
+ ```rust
+ pub fn dyn()
+ ```
+ "#]],
+ );
+
+ check(
+ r#"
+//- /lib1.rs crate:escaping_needlessly edition:2015
+pub fn r#dyn() {}
+
+//- /lib2.rs crate:dependent edition:2015 deps:escaping_needlessly new_source_root:local
+fn foo() {
+ escaping_needlessly::dyn$0();
+}
+ "#,
+ expect![[r#"
+ *dyn*
+
+ ```rust
+ escaping_needlessly
+ ```
+
+ ```rust
+ pub fn dyn()
+ ```
+ "#]],
+ );
+}
diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs
index 0a8d272757..6a5d5e26a4 100644
--- a/crates/ide/src/inlay_hints.rs
+++ b/crates/ide/src/inlay_hints.rs
@@ -11,7 +11,7 @@ use hir::{
use ide_db::{famous_defs::FamousDefs, FileRange, RootDatabase};
use itertools::Itertools;
use smallvec::{smallvec, SmallVec};
-use span::EditionedFileId;
+use span::{Edition, EditionedFileId};
use stdx::never;
use syntax::{
ast::{self, AstNode},
@@ -372,6 +372,7 @@ fn label_of_ty(
famous_defs @ FamousDefs(sema, _): &FamousDefs<'_, '_>,
config: &InlayHintsConfig,
ty: &hir::Type,
+ edition: Edition,
) -> Option<InlayHintLabel> {
fn rec(
sema: &Semantics<'_, RootDatabase>,
@@ -380,6 +381,7 @@ fn label_of_ty(
ty: &hir::Type,
label_builder: &mut InlayHintLabelBuilder<'_>,
config: &InlayHintsConfig,
+ edition: Edition,
) -> Result<(), HirDisplayError> {
let iter_item_type = hint_iterator(sema, famous_defs, ty);
match iter_item_type {
@@ -410,12 +412,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)?;
+ rec(sema, famous_defs, max_length, &ty, label_builder, config, edition)?;
label_builder.write_str(LABEL_END)?;
Ok(())
}
None => ty
- .display_truncated(sema.db, max_length)
+ .display_truncated(sema.db, max_length, edition)
.with_closure_style(config.closure_style)
.write_to(label_builder),
}
@@ -427,7 +429,7 @@ fn label_of_ty(
location: None,
result: InlayHintLabel::default(),
};
- let _ = rec(sema, famous_defs, config.max_length, ty, &mut label_builder, config);
+ let _ = rec(sema, famous_defs, config.max_length, ty, &mut label_builder, config, edition);
let r = label_builder.finish();
Some(r)
}
@@ -569,7 +571,7 @@ fn hints(
match node {
ast::Expr(expr) => {
chaining::hints(hints, famous_defs, config, file_id, &expr);
- adjustment::hints(hints, sema, config, &expr);
+ adjustment::hints(hints, sema, config, file_id, &expr);
match expr {
ast::Expr::CallExpr(it) => param_name::hints(hints, sema, config, ast::Expr::from(it)),
ast::Expr::MethodCallExpr(it) => {
@@ -600,7 +602,7 @@ fn hints(
// FIXME: record impl lifetimes so they aren't being reused in assoc item lifetime inlay hints
ast::Item::Impl(_) => None,
ast::Item::Fn(it) => {
- implicit_drop::hints(hints, sema, config, &it);
+ implicit_drop::hints(hints, sema, config, file_id, &it);
fn_lifetime_fn::hints(hints, config, it)
},
// static type elisions
diff --git a/crates/ide/src/inlay_hints/adjustment.rs b/crates/ide/src/inlay_hints/adjustment.rs
index 7932d8efbc..756198d0c0 100644
--- a/crates/ide/src/inlay_hints/adjustment.rs
+++ b/crates/ide/src/inlay_hints/adjustment.rs
@@ -10,6 +10,7 @@ use hir::{
};
use ide_db::RootDatabase;
+use span::EditionedFileId;
use stdx::never;
use syntax::{
ast::{self, make, AstNode},
@@ -25,6 +26,7 @@ pub(super) fn hints(
acc: &mut Vec<InlayHint>,
sema: &Semantics<'_, RootDatabase>,
config: &InlayHintsConfig,
+ file_id: EditionedFileId,
expr: &ast::Expr,
) -> Option<()> {
if config.adjustment_hints_hide_outside_unsafe && !sema.is_inside_unsafe(expr) {
@@ -141,8 +143,8 @@ pub(super) fn hints(
if postfix { format!(".{}", text.trim_end()) } else { text.to_owned() },
Some(InlayTooltip::Markdown(format!(
"`{}` → `{}` ({coercion} coercion)",
- source.display(sema.db),
- target.display(sema.db),
+ source.display(sema.db, file_id.edition()),
+ target.display(sema.db, file_id.edition()),
))),
None,
);
diff --git a/crates/ide/src/inlay_hints/bind_pat.rs b/crates/ide/src/inlay_hints/bind_pat.rs
index 7310852b8e..d67afe14d7 100644
--- a/crates/ide/src/inlay_hints/bind_pat.rs
+++ b/crates/ide/src/inlay_hints/bind_pat.rs
@@ -22,7 +22,7 @@ pub(super) fn hints(
acc: &mut Vec<InlayHint>,
famous_defs @ FamousDefs(sema, _): &FamousDefs<'_, '_>,
config: &InlayHintsConfig,
- _file_id: EditionedFileId,
+ file_id: EditionedFileId,
pat: &ast::IdentPat,
) -> Option<()> {
if !config.type_hints {
@@ -67,7 +67,7 @@ pub(super) fn hints(
return None;
}
- let mut label = label_of_ty(famous_defs, config, &ty)?;
+ let mut label = label_of_ty(famous_defs, config, &ty, file_id.edition())?;
if config.hide_named_constructor_hints
&& is_named_constructor(sema, pat, &label.to_string()).is_some()
diff --git a/crates/ide/src/inlay_hints/chaining.rs b/crates/ide/src/inlay_hints/chaining.rs
index 4e15213b8b..35f4d46e18 100644
--- a/crates/ide/src/inlay_hints/chaining.rs
+++ b/crates/ide/src/inlay_hints/chaining.rs
@@ -14,7 +14,7 @@ pub(super) fn hints(
acc: &mut Vec<InlayHint>,
famous_defs @ FamousDefs(sema, _): &FamousDefs<'_, '_>,
config: &InlayHintsConfig,
- _file_id: EditionedFileId,
+ file_id: EditionedFileId,
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)?;
+ let label = label_of_ty(famous_defs, config, &ty, file_id.edition())?;
acc.push(InlayHint {
range: expr.syntax().text_range(),
kind: InlayKind::Chaining,
diff --git a/crates/ide/src/inlay_hints/closing_brace.rs b/crates/ide/src/inlay_hints/closing_brace.rs
index 8f2777f392..d78fd64bdf 100644
--- a/crates/ide/src/inlay_hints/closing_brace.rs
+++ b/crates/ide/src/inlay_hints/closing_brace.rs
@@ -36,8 +36,12 @@ pub(super) fn hints(
let ty = imp.self_ty(sema.db);
let trait_ = imp.trait_(sema.db);
let hint_text = match trait_ {
- Some(tr) => format!("impl {} for {}", tr.name(sema.db).display(sema.db), ty.display_truncated(sema.db, config.max_length)),
- None => format!("impl {}", ty.display_truncated(sema.db, config.max_length)),
+ 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(),
+ )),
+ None => format!("impl {}", ty.display_truncated(sema.db, config.max_length, file_id.edition())),
};
(hint_text, None)
},
diff --git a/crates/ide/src/inlay_hints/closure_ret.rs b/crates/ide/src/inlay_hints/closure_ret.rs
index f6bd7ca064..325c204069 100644
--- a/crates/ide/src/inlay_hints/closure_ret.rs
+++ b/crates/ide/src/inlay_hints/closure_ret.rs
@@ -14,7 +14,7 @@ pub(super) fn hints(
acc: &mut Vec<InlayHint>,
famous_defs @ FamousDefs(sema, _): &FamousDefs<'_, '_>,
config: &InlayHintsConfig,
- _file_id: EditionedFileId,
+ file_id: EditionedFileId,
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)?;
+ let mut label = label_of_ty(famous_defs, config, &ty, file_id.edition())?;
if arrow.is_none() {
label.prepend_str(" -> ");
diff --git a/crates/ide/src/inlay_hints/implicit_drop.rs b/crates/ide/src/inlay_hints/implicit_drop.rs
index 7f901db28d..b4695a2b35 100644
--- a/crates/ide/src/inlay_hints/implicit_drop.rs
+++ b/crates/ide/src/inlay_hints/implicit_drop.rs
@@ -12,6 +12,7 @@ use hir::{
};
use ide_db::{FileRange, RootDatabase};
+use span::EditionedFileId;
use syntax::{
ast::{self, AstNode},
match_ast, ToSmolStr,
@@ -23,6 +24,7 @@ pub(super) fn hints(
acc: &mut Vec<InlayHint>,
sema: &Semantics<'_, RootDatabase>,
config: &InlayHintsConfig,
+ file_id: EditionedFileId,
def: &ast::Fn,
) -> Option<()> {
if !config.implicit_drop_hints {
@@ -100,7 +102,7 @@ pub(super) fn hints(
})
});
let binding = &hir.bindings[*binding];
- let name = binding.name.display_no_db().to_smolstr();
+ let name = binding.name.display_no_db(file_id.edition()).to_smolstr();
if name.starts_with("<ra@") {
continue; // Ignore desugared variables
}
diff --git a/crates/ide/src/inlay_hints/param_name.rs b/crates/ide/src/inlay_hints/param_name.rs
index 70d790efad..0f3142ef3f 100644
--- a/crates/ide/src/inlay_hints/param_name.rs
+++ b/crates/ide/src/inlay_hints/param_name.rs
@@ -121,7 +121,9 @@ fn should_hide_param_name_hint(
}
let fn_name = match callable.kind() {
- hir::CallableKind::Function(it) => Some(it.name(sema.db).display_no_db().to_smolstr()),
+ hir::CallableKind::Function(it) => {
+ Some(it.name(sema.db).unescaped().display_no_db().to_smolstr())
+ }
_ => None,
};
let fn_name = fn_name.as_deref();
diff --git a/crates/ide/src/moniker.rs b/crates/ide/src/moniker.rs
index 1b64bc9260..7b5fd651e3 100644
--- a/crates/ide/src/moniker.rs
+++ b/crates/ide/src/moniker.rs
@@ -249,10 +249,11 @@ pub(crate) fn def_to_moniker(
let module = def.module(db)?;
let krate = module.krate();
+ let edition = krate.edition(db);
let mut description = vec![];
description.extend(module.path_to_root(db).into_iter().filter_map(|x| {
Some(MonikerDescriptor {
- name: x.name(db)?.display(db).to_string(),
+ name: x.name(db)?.display(db, edition).to_string(),
desc: def_to_kind(db, x.into()).into(),
})
}));
@@ -265,7 +266,7 @@ pub(crate) fn def_to_moniker(
// Because different traits can have functions with the same name,
// we have to include the trait name as part of the moniker for uniqueness.
description.push(MonikerDescriptor {
- name: trait_.name(db).display(db).to_string(),
+ name: trait_.name(db).display(db, edition).to_string(),
desc: def_to_kind(db, trait_.into()).into(),
});
}
@@ -274,14 +275,14 @@ pub(crate) fn def_to_moniker(
// we add both the struct name and the trait name to the path
if let Some(adt) = impl_.self_ty(db).as_adt() {
description.push(MonikerDescriptor {
- name: adt.name(db).display(db).to_string(),
+ name: adt.name(db).display(db, edition).to_string(),
desc: def_to_kind(db, adt.into()).into(),
});
}
if let Some(trait_) = impl_.trait_(db) {
description.push(MonikerDescriptor {
- name: trait_.name(db).display(db).to_string(),
+ name: trait_.name(db).display(db, edition).to_string(),
desc: def_to_kind(db, trait_.into()).into(),
});
}
@@ -291,7 +292,7 @@ pub(crate) fn def_to_moniker(
if let Definition::Field(it) = def {
description.push(MonikerDescriptor {
- name: it.parent_def(db).name(db).display(db).to_string(),
+ name: it.parent_def(db).name(db).display(db, edition).to_string(),
desc: def_to_kind(db, it.parent_def(db).into()).into(),
});
}
@@ -303,7 +304,7 @@ pub(crate) fn def_to_moniker(
let parent_name = parent.name(db);
if let Some(name) = parent_name {
description.push(MonikerDescriptor {
- name: name.display(db).to_string(),
+ name: name.display(db, edition).to_string(),
desc: def_to_kind(db, parent).into(),
});
}
@@ -326,53 +327,53 @@ pub(crate) fn def_to_moniker(
return None;
}
- MonikerDescriptor { name: local.name(db).display(db).to_string(), desc }
+ MonikerDescriptor { name: local.name(db).display(db, edition).to_string(), desc }
}
Definition::Macro(m) => {
- MonikerDescriptor { name: m.name(db).display(db).to_string(), desc }
+ MonikerDescriptor { name: m.name(db).display(db, edition).to_string(), desc }
}
Definition::Function(f) => {
- MonikerDescriptor { name: f.name(db).display(db).to_string(), desc }
+ MonikerDescriptor { name: f.name(db).display(db, edition).to_string(), desc }
}
Definition::Variant(v) => {
- MonikerDescriptor { name: v.name(db).display(db).to_string(), desc }
+ MonikerDescriptor { name: v.name(db).display(db, edition).to_string(), desc }
}
Definition::Const(c) => {
- MonikerDescriptor { name: c.name(db)?.display(db).to_string(), desc }
+ MonikerDescriptor { name: c.name(db)?.display(db, edition).to_string(), desc }
}
Definition::Trait(trait_) => {
- MonikerDescriptor { name: trait_.name(db).display(db).to_string(), desc }
+ MonikerDescriptor { name: trait_.name(db).display(db, edition).to_string(), desc }
}
Definition::TraitAlias(ta) => {
- MonikerDescriptor { name: ta.name(db).display(db).to_string(), desc }
+ MonikerDescriptor { name: ta.name(db).display(db, edition).to_string(), desc }
}
Definition::TypeAlias(ta) => {
- MonikerDescriptor { name: ta.name(db).display(db).to_string(), desc }
+ MonikerDescriptor { name: ta.name(db).display(db, edition).to_string(), desc }
}
Definition::Module(m) => {
- MonikerDescriptor { name: m.name(db)?.display(db).to_string(), desc }
+ MonikerDescriptor { name: m.name(db)?.display(db, edition).to_string(), desc }
}
Definition::BuiltinType(b) => {
- MonikerDescriptor { name: b.name().display(db).to_string(), desc }
+ MonikerDescriptor { name: b.name().display(db, edition).to_string(), desc }
}
Definition::SelfType(imp) => MonikerDescriptor {
- name: imp.self_ty(db).as_adt()?.name(db).display(db).to_string(),
+ name: imp.self_ty(db).as_adt()?.name(db).display(db, edition).to_string(),
desc,
},
Definition::Field(it) => {
- MonikerDescriptor { name: it.name(db).display(db).to_string(), desc }
+ MonikerDescriptor { name: it.name(db).display(db, edition).to_string(), desc }
}
Definition::TupleField(it) => {
- MonikerDescriptor { name: it.name().display(db).to_string(), desc }
+ MonikerDescriptor { name: it.name().display(db, edition).to_string(), desc }
}
Definition::Adt(adt) => {
- MonikerDescriptor { name: adt.name(db).display(db).to_string(), desc }
+ MonikerDescriptor { name: adt.name(db).display(db, edition).to_string(), desc }
}
Definition::Static(s) => {
- MonikerDescriptor { name: s.name(db).display(db).to_string(), desc }
+ MonikerDescriptor { name: s.name(db).display(db, edition).to_string(), desc }
}
Definition::ExternCrateDecl(m) => {
- MonikerDescriptor { name: m.name(db).display(db).to_string(), desc }
+ MonikerDescriptor { name: m.name(db).display(db, edition).to_string(), desc }
}
};
diff --git a/crates/ide/src/navigation_target.rs b/crates/ide/src/navigation_target.rs
index 066141d36f..9ace9fda62 100644
--- a/crates/ide/src/navigation_target.rs
+++ b/crates/ide/src/navigation_target.rs
@@ -5,14 +5,15 @@ use std::fmt;
use arrayvec::ArrayVec;
use either::Either;
use hir::{
- db::ExpandDatabase, symbols::FileSymbol, AssocItem, FieldSource, HasContainer, HasSource,
- HirDisplay, HirFileId, InFile, LocalSource, ModuleSource,
+ db::ExpandDatabase, symbols::FileSymbol, AssocItem, FieldSource, HasContainer, HasCrate,
+ HasSource, HirDisplay, HirFileId, HirFileIdExt, InFile, LocalSource, ModuleSource,
};
use ide_db::{
defs::Definition,
documentation::{Documentation, HasDocs},
FileId, FileRange, RootDatabase, SymbolKind,
};
+use span::Edition;
use stdx::never;
use syntax::{
ast::{self, HasName},
@@ -97,7 +98,9 @@ impl NavigationTarget {
db: &RootDatabase,
module: hir::Module,
) -> UpmappingResult<NavigationTarget> {
- let name = module.name(db).map(|it| it.display_no_db().to_smolstr()).unwrap_or_default();
+ let edition = module.krate().edition(db);
+ let name =
+ module.name(db).map(|it| it.display_no_db(edition).to_smolstr()).unwrap_or_default();
match module.declaration_source(db) {
Some(InFile { value, file_id }) => {
orig_range_with_focus(db, file_id, value.syntax(), value.name()).map(
@@ -110,7 +113,7 @@ impl NavigationTarget {
SymbolKind::Module,
);
res.docs = module.docs(db);
- res.description = Some(module.display(db).to_string());
+ res.description = Some(module.display(db, edition).to_string());
res
},
)
@@ -175,6 +178,8 @@ impl NavigationTarget {
impl TryToNav for FileSymbol {
fn try_to_nav(&self, db: &RootDatabase) -> Option<UpmappingResult<NavigationTarget>> {
+ let edition =
+ self.def.module(db).map(|it| it.krate().edition(db)).unwrap_or(Edition::CURRENT);
Some(
orig_range_with_focus_r(
db,
@@ -185,27 +190,26 @@ impl TryToNav for FileSymbol {
.map(|(FileRange { file_id, range: full_range }, focus_range)| {
NavigationTarget {
file_id,
- name: self
- .is_alias
- .then(|| self.def.name(db))
- .flatten()
- .map_or_else(|| self.name.clone(), |it| it.display_no_db().to_smolstr()),
+ name: self.is_alias.then(|| self.def.name(db)).flatten().map_or_else(
+ || self.name.clone(),
+ |it| it.display_no_db(edition).to_smolstr(),
+ ),
alias: self.is_alias.then(|| self.name.clone()),
kind: Some(hir::ModuleDefId::from(self.def).into()),
full_range,
focus_range,
container_name: self.container_name.clone(),
description: match self.def {
- hir::ModuleDef::Module(it) => Some(it.display(db).to_string()),
- hir::ModuleDef::Function(it) => Some(it.display(db).to_string()),
- hir::ModuleDef::Adt(it) => Some(it.display(db).to_string()),
- hir::ModuleDef::Variant(it) => Some(it.display(db).to_string()),
- hir::ModuleDef::Const(it) => Some(it.display(db).to_string()),
- hir::ModuleDef::Static(it) => Some(it.display(db).to_string()),
- hir::ModuleDef::Trait(it) => Some(it.display(db).to_string()),
- hir::ModuleDef::TraitAlias(it) => Some(it.display(db).to_string()),
- hir::ModuleDef::TypeAlias(it) => Some(it.display(db).to_string()),
- hir::ModuleDef::Macro(it) => Some(it.display(db).to_string()),
+ 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::BuiltinType(_) => None,
},
docs: None,
@@ -271,11 +275,13 @@ pub(crate) trait ToNavFromAst: Sized {
}
}
-fn container_name(db: &RootDatabase, t: impl HasContainer) -> Option<SmolStr> {
+fn container_name(db: &RootDatabase, t: impl HasContainer, edition: Edition) -> Option<SmolStr> {
match t.container(db) {
- hir::ItemContainer::Trait(it) => Some(it.name(db).display_no_db().to_smolstr()),
+ hir::ItemContainer::Trait(it) => Some(it.name(db).display_no_db(edition).to_smolstr()),
// FIXME: Handle owners of blocks correctly here
- hir::ItemContainer::Module(it) => it.name(db).map(|name| name.display_no_db().to_smolstr()),
+ hir::ItemContainer::Module(it) => {
+ it.name(db).map(|name| name.display_no_db(edition).to_smolstr())
+ }
_ => None,
}
}
@@ -283,32 +289,32 @@ fn container_name(db: &RootDatabase, t: impl HasContainer) -> Option<SmolStr> {
impl ToNavFromAst for hir::Function {
const KIND: SymbolKind = SymbolKind::Function;
fn container_name(self, db: &RootDatabase) -> Option<SmolStr> {
- container_name(db, self)
+ container_name(db, self, self.krate(db).edition(db))
}
}
impl ToNavFromAst for hir::Const {
const KIND: SymbolKind = SymbolKind::Const;
fn container_name(self, db: &RootDatabase) -> Option<SmolStr> {
- container_name(db, self)
+ container_name(db, self, self.krate(db).edition(db))
}
}
impl ToNavFromAst for hir::Static {
const KIND: SymbolKind = SymbolKind::Static;
fn container_name(self, db: &RootDatabase) -> Option<SmolStr> {
- container_name(db, self)
+ container_name(db, self, self.krate(db).edition(db))
}
}
impl ToNavFromAst for hir::Struct {
const KIND: SymbolKind = SymbolKind::Struct;
fn container_name(self, db: &RootDatabase) -> Option<SmolStr> {
- container_name(db, self)
+ container_name(db, self, self.krate(db).edition(db))
}
}
impl ToNavFromAst for hir::Enum {
const KIND: SymbolKind = SymbolKind::Enum;
fn container_name(self, db: &RootDatabase) -> Option<SmolStr> {
- container_name(db, self)
+ container_name(db, self, self.krate(db).edition(db))
}
}
impl ToNavFromAst for hir::Variant {
@@ -317,25 +323,25 @@ impl ToNavFromAst for hir::Variant {
impl ToNavFromAst for hir::Union {
const KIND: SymbolKind = SymbolKind::Union;
fn container_name(self, db: &RootDatabase) -> Option<SmolStr> {
- container_name(db, self)
+ container_name(db, self, self.krate(db).edition(db))
}
}
impl ToNavFromAst for hir::TypeAlias {
const KIND: SymbolKind = SymbolKind::TypeAlias;
fn container_name(self, db: &RootDatabase) -> Option<SmolStr> {
- container_name(db, self)
+ container_name(db, self, self.krate(db).edition(db))
}
}
impl ToNavFromAst for hir::Trait {
const KIND: SymbolKind = SymbolKind::Trait;
fn container_name(self, db: &RootDatabase) -> Option<SmolStr> {
- container_name(db, self)
+ container_name(db, self, self.krate(db).edition(db))
}
}
impl ToNavFromAst for hir::TraitAlias {
const KIND: SymbolKind = SymbolKind::TraitAlias;
fn container_name(self, db: &RootDatabase) -> Option<SmolStr> {
- container_name(db, self)
+ container_name(db, self, self.krate(db).edition(db))
}
}
@@ -346,6 +352,7 @@ where
{
fn try_to_nav(&self, db: &RootDatabase) -> Option<UpmappingResult<NavigationTarget>> {
let src = self.source(db)?;
+ let edition = src.file_id.original_file(db).edition();
Some(
NavigationTarget::from_named(
db,
@@ -354,7 +361,7 @@ where
)
.map(|mut res| {
res.docs = self.docs(db);
- res.description = Some(self.display(db).to_string());
+ res.description = Some(self.display(db, edition).to_string());
res.container_name = self.container_name(db);
res
}),
@@ -365,8 +372,10 @@ where
impl ToNav for hir::Module {
fn to_nav(&self, db: &RootDatabase) -> UpmappingResult<NavigationTarget> {
let InFile { file_id, value } = self.definition_source(db);
+ let edition = self.krate(db).edition(db);
- let name = self.name(db).map(|it| it.display_no_db().to_smolstr()).unwrap_or_default();
+ let name =
+ self.name(db).map(|it| it.display_no_db(edition).to_smolstr()).unwrap_or_default();
let (syntax, focus) = match &value {
ModuleSource::SourceFile(node) => (node.syntax(), None),
ModuleSource::Module(node) => (node.syntax(), node.name()),
@@ -418,6 +427,7 @@ 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);
Some(orig_range_with_focus(db, file_id, value.syntax(), focus).map(
|(FileRange { file_id, range: full_range }, focus_range)| {
@@ -425,7 +435,7 @@ impl TryToNav for hir::ExternCrateDecl {
file_id,
self.alias_or_name(db)
.unwrap_or_else(|| self.name(db))
- .display_no_db()
+ .display_no_db(edition)
.to_smolstr(),
focus_range,
full_range,
@@ -433,8 +443,8 @@ impl TryToNav for hir::ExternCrateDecl {
);
res.docs = self.docs(db);
- res.description = Some(self.display(db).to_string());
- res.container_name = container_name(db, *self);
+ res.description = Some(self.display(db, edition).to_string());
+ res.container_name = container_name(db, *self, edition);
res
},
))
@@ -444,13 +454,14 @@ impl TryToNav for hir::ExternCrateDecl {
impl TryToNav for hir::Field {
fn try_to_nav(&self, db: &RootDatabase) -> Option<UpmappingResult<NavigationTarget>> {
let src = self.source(db)?;
+ let edition = self.parent_def(db).module(db).krate().edition(db);
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).to_string());
+ res.description = Some(self.display(db, edition).to_string());
res
},
)
@@ -531,10 +542,11 @@ impl ToNav for LocalSource {
Either::Left(bind_pat) => (bind_pat.syntax(), bind_pat.name()),
Either::Right(it) => (it.syntax(), it.name()),
};
+ let edition = self.local.parent(db).module(db).krate().edition(db);
orig_range_with_focus(db, file_id, node, name).map(
|(FileRange { file_id, range: full_range }, focus_range)| {
- let name = local.name(db).display_no_db().to_smolstr();
+ let name = local.name(db).display_no_db(edition).to_smolstr();
let kind = if local.is_self(db) {
SymbolKind::SelfParam
} else if local.is_param(db) {
@@ -567,7 +579,8 @@ impl ToNav for hir::Local {
impl TryToNav for hir::Label {
fn try_to_nav(&self, db: &RootDatabase) -> Option<UpmappingResult<NavigationTarget>> {
let InFile { file_id, value } = self.source(db)?;
- let name = self.name(db).display_no_db().to_smolstr();
+ // Labels can't be keywords, so no escaping needed.
+ let name = self.name(db).display_no_db(Edition::Edition2015).to_smolstr();
Some(orig_range_with_focus(db, file_id, value.syntax(), value.lifetime()).map(
|(FileRange { file_id, range: full_range }, focus_range)| NavigationTarget {
@@ -588,7 +601,8 @@ impl TryToNav for hir::Label {
impl TryToNav for hir::TypeParam {
fn try_to_nav(&self, db: &RootDatabase) -> Option<UpmappingResult<NavigationTarget>> {
let InFile { file_id, value } = self.merge().source(db)?;
- let name = self.name(db).display_no_db().to_smolstr();
+ let edition = self.module(db).krate().edition(db);
+ let name = self.name(db).display_no_db(edition).to_smolstr();
let value = match value {
Either::Left(ast::TypeOrConstParam::Type(x)) => Either::Left(x),
@@ -630,7 +644,8 @@ impl TryToNav for hir::TypeOrConstParam {
impl TryToNav for hir::LifetimeParam {
fn try_to_nav(&self, db: &RootDatabase) -> Option<UpmappingResult<NavigationTarget>> {
let InFile { file_id, value } = self.source(db)?;
- let name = self.name(db).display_no_db().to_smolstr();
+ // Lifetimes cannot be keywords, so not escaping needed.
+ let name = self.name(db).display_no_db(Edition::Edition2015).to_smolstr();
Some(orig_range(db, file_id, value.syntax()).map(
|(FileRange { file_id, range: full_range }, focus_range)| NavigationTarget {
@@ -651,7 +666,8 @@ impl TryToNav for hir::LifetimeParam {
impl TryToNav for hir::ConstParam {
fn try_to_nav(&self, db: &RootDatabase) -> Option<UpmappingResult<NavigationTarget>> {
let InFile { file_id, value } = self.merge().source(db)?;
- let name = self.name(db).display_no_db().to_smolstr();
+ let edition = self.module(db).krate().edition(db);
+ let name = self.name(db).display_no_db(edition).to_smolstr();
let value = match value {
Either::Left(ast::TypeOrConstParam::Const(x)) => x,
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs
index aef162bf0a..3e3d5ef6e6 100644
--- a/crates/ide/src/references.rs
+++ b/crates/ide/src/references.rs
@@ -306,8 +306,9 @@ fn handle_control_flow_keywords(
FilePosition { file_id, offset }: FilePosition,
) -> Option<ReferenceSearchResult> {
let file = sema.parse_guess_edition(file_id);
- let token =
- file.syntax().token_at_offset(offset).find(|t| t.kind().is_keyword(Edition::CURRENT))?;
+ let edition =
+ sema.attach_first_edition(file_id).map(|it| it.edition()).unwrap_or(Edition::CURRENT);
+ let token = file.syntax().token_at_offset(offset).find(|t| t.kind().is_keyword(edition))?;
let references = match token.kind() {
T![fn] | T![return] | T![try] => highlight_related::highlight_exit_points(sema, token),
diff --git a/crates/ide/src/rename.rs b/crates/ide/src/rename.rs
index ed0e3d89dd..42b7472c64 100644
--- a/crates/ide/src/rename.rs
+++ b/crates/ide/src/rename.rs
@@ -6,19 +6,14 @@
use hir::{AsAssocItem, HirFileIdExt, InFile, Semantics};
use ide_db::{
- base_db::SourceDatabase,
defs::{Definition, NameClass, NameRefClass},
rename::{bail, format_err, source_edit_from_references, IdentifierKind},
source_change::SourceChangeBuilder,
FileId, FileRange, RootDatabase,
};
use itertools::Itertools;
-use span::Edition;
use stdx::{always, never};
-use syntax::{
- ast, utils::is_raw_identifier, AstNode, SmolStr, SyntaxKind, SyntaxNode, TextRange, TextSize,
- ToSmolStr,
-};
+use syntax::{ast, AstNode, SyntaxKind, SyntaxNode, TextRange, TextSize};
use text_edit::TextEdit;
@@ -103,7 +98,7 @@ pub(crate) fn rename(
// FIXME: This can use the `ide_db::rename_reference` (or def.rename) method once we can
// properly find "direct" usages/references.
.map(|(.., def)| {
- match IdentifierKind::classify(Edition::CURRENT_FIXME, new_name)? {
+ match IdentifierKind::classify(new_name)? {
IdentifierKind::Ident => (),
IdentifierKind::Lifetime => {
bail!("Cannot alias reference to a lifetime identifier")
@@ -125,7 +120,10 @@ pub(crate) fn rename(
let mut source_change = SourceChange::default();
source_change.extend(usages.references.get_mut(&file_id).iter().map(|refs| {
- (position.file_id, source_edit_from_references(refs, def, new_name))
+ (
+ position.file_id,
+ source_edit_from_references(refs, def, new_name, file_id.edition()),
+ )
}));
Ok(source_change)
@@ -163,12 +161,7 @@ pub(crate) fn will_rename_file(
let sema = Semantics::new(db);
let module = sema.file_to_module_def(file_id)?;
let def = Definition::Module(module);
- let mut change =
- if is_raw_identifier(new_name_stem, db.crate_graph()[module.krate().into()].edition) {
- def.rename(&sema, &SmolStr::from_iter(["r#", new_name_stem])).ok()?
- } else {
- def.rename(&sema, new_name_stem).ok()?
- };
+ let mut change = def.rename(&sema, new_name_stem).ok()?;
change.file_system_edits.clear();
Some(change)
}
@@ -272,7 +265,7 @@ fn find_definitions(
// if the name differs from the definitions name it has to be an alias
if def
.name(sema.db)
- .map_or(false, |it| it.display_no_db().to_smolstr() != name_ref.text().as_str())
+ .map_or(false, |it| !it.eq_ident(name_ref.text().as_str()))
{
Err(format_err!("Renaming aliases is currently unsupported"))
} else {
@@ -379,7 +372,7 @@ fn rename_to_self(
let usages = def.usages(sema).all();
let mut source_change = SourceChange::default();
source_change.extend(usages.iter().map(|(file_id, references)| {
- (file_id.into(), source_edit_from_references(references, def, "self"))
+ (file_id.into(), source_edit_from_references(references, def, "self", file_id.edition()))
}));
source_change.insert_source_edit(
file_id.original_file(sema.db),
@@ -400,7 +393,7 @@ fn rename_self_to_param(
return Ok(SourceChange::default());
}
- let identifier_kind = IdentifierKind::classify(Edition::CURRENT_FIXME, new_name)?;
+ let identifier_kind = IdentifierKind::classify(new_name)?;
let InFile { file_id, value: self_param } =
sema.source(self_param).ok_or_else(|| format_err!("cannot find function source"))?;
@@ -415,7 +408,7 @@ fn rename_self_to_param(
let mut source_change = SourceChange::default();
source_change.insert_source_edit(file_id.original_file(sema.db), edit);
source_change.extend(usages.iter().map(|(file_id, references)| {
- (file_id.into(), source_edit_from_references(references, def, new_name))
+ (file_id.into(), source_edit_from_references(references, def, new_name, file_id.edition()))
}));
Ok(source_change)
}
@@ -636,9 +629,9 @@ impl Foo {
#[test]
fn test_rename_to_invalid_identifier3() {
check(
- "let",
+ "super",
r#"fn main() { let i$0 = 1; }"#,
- "error: Invalid name `let`: not an identifier",
+ "error: Invalid name `super`: not an identifier",
);
}
@@ -687,11 +680,7 @@ impl Foo {
#[test]
fn test_rename_mod_invalid_raw_ident() {
- check(
- "r#self",
- r#"mod foo$0 {}"#,
- "error: Invalid name: `self` cannot be a raw identifier",
- );
+ check("r#self", r#"mod foo$0 {}"#, "error: Invalid name `self`: not an identifier");
}
#[test]
@@ -1546,6 +1535,228 @@ pub fn baz() {}
}
#[test]
+ fn test_rename_each_usage_gets_appropriate_rawness() {
+ check_expect(
+ "dyn",
+ r#"
+//- /a.rs crate:a edition:2015
+pub fn foo() {}
+
+//- /b.rs crate:b edition:2018 deps:a new_source_root:local
+fn bar() {
+ a::foo$0();
+}
+ "#,
+ expect![[r#"
+ source_file_edits: [
+ (
+ FileId(
+ 0,
+ ),
+ [
+ Indel {
+ insert: "dyn",
+ delete: 7..10,
+ },
+ ],
+ ),
+ (
+ FileId(
+ 1,
+ ),
+ [
+ Indel {
+ insert: "r#dyn",
+ delete: 18..21,
+ },
+ ],
+ ),
+ ]
+ file_system_edits: []
+ "#]],
+ );
+
+ check_expect(
+ "dyn",
+ r#"
+//- /a.rs crate:a edition:2018
+pub fn foo() {}
+
+//- /b.rs crate:b edition:2015 deps:a new_source_root:local
+fn bar() {
+ a::foo$0();
+}
+ "#,
+ expect![[r#"
+ source_file_edits: [
+ (
+ FileId(
+ 0,
+ ),
+ [
+ Indel {
+ insert: "r#dyn",
+ delete: 7..10,
+ },
+ ],
+ ),
+ (
+ FileId(
+ 1,
+ ),
+ [
+ Indel {
+ insert: "dyn",
+ delete: 18..21,
+ },
+ ],
+ ),
+ ]
+ file_system_edits: []
+ "#]],
+ );
+
+ check_expect(
+ "r#dyn",
+ r#"
+//- /a.rs crate:a edition:2018
+pub fn foo$0() {}
+
+//- /b.rs crate:b edition:2015 deps:a new_source_root:local
+fn bar() {
+ a::foo();
+}
+ "#,
+ expect![[r#"
+ source_file_edits: [
+ (
+ FileId(
+ 0,
+ ),
+ [
+ Indel {
+ insert: "r#dyn",
+ delete: 7..10,
+ },
+ ],
+ ),
+ (
+ FileId(
+ 1,
+ ),
+ [
+ Indel {
+ insert: "dyn",
+ delete: 18..21,
+ },
+ ],
+ ),
+ ]
+ file_system_edits: []
+ "#]],
+ );
+ }
+
+ #[test]
+ fn rename_raw_identifier() {
+ check_expect(
+ "abc",
+ r#"
+//- /a.rs crate:a edition:2015
+pub fn dyn() {}
+
+fn foo() {
+ dyn$0();
+}
+
+//- /b.rs crate:b edition:2018 deps:a new_source_root:local
+fn bar() {
+ a::r#dyn();
+}
+ "#,
+ expect![[r#"
+ source_file_edits: [
+ (
+ FileId(
+ 0,
+ ),
+ [
+ Indel {
+ insert: "abc",
+ delete: 7..10,
+ },
+ Indel {
+ insert: "abc",
+ delete: 32..35,
+ },
+ ],
+ ),
+ (
+ FileId(
+ 1,
+ ),
+ [
+ Indel {
+ insert: "abc",
+ delete: 18..23,
+ },
+ ],
+ ),
+ ]
+ file_system_edits: []
+ "#]],
+ );
+
+ check_expect(
+ "abc",
+ r#"
+//- /a.rs crate:a edition:2018
+pub fn r#dyn() {}
+
+fn foo() {
+ r#dyn$0();
+}
+
+//- /b.rs crate:b edition:2015 deps:a new_source_root:local
+fn bar() {
+ a::dyn();
+}
+ "#,
+ expect![[r#"
+ source_file_edits: [
+ (
+ FileId(
+ 0,
+ ),
+ [
+ Indel {
+ insert: "abc",
+ delete: 7..12,
+ },
+ Indel {
+ insert: "abc",
+ delete: 34..39,
+ },
+ ],
+ ),
+ (
+ FileId(
+ 1,
+ ),
+ [
+ Indel {
+ insert: "abc",
+ delete: 18..21,
+ },
+ ],
+ ),
+ ]
+ file_system_edits: []
+ "#]],
+ );
+ }
+
+ #[test]
fn test_enum_variant_from_module_1() {
cov_mark::check!(rename_non_local);
check(
diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs
index 5d4b8b3643..38dc522789 100644
--- a/crates/ide/src/runnables.rs
+++ b/crates/ide/src/runnables.rs
@@ -3,7 +3,8 @@ use std::fmt;
use ast::HasName;
use cfg::{CfgAtom, CfgExpr};
use hir::{
- db::HirDatabase, sym, AsAssocItem, AttrsWithOwner, HasAttrs, HasSource, HirFileIdExt, Semantics,
+ db::HirDatabase, sym, AsAssocItem, AttrsWithOwner, HasAttrs, HasCrate, HasSource, HirFileIdExt,
+ Semantics,
};
use ide_assists::utils::{has_test_related_attribute, test_related_attribute_syn};
use ide_db::{
@@ -14,7 +15,7 @@ use ide_db::{
FilePosition, FxHashMap, FxHashSet, RootDatabase, SymbolKind,
};
use itertools::Itertools;
-use span::TextSize;
+use span::{Edition, TextSize};
use stdx::{always, format_to};
use syntax::{
ast::{self, AstNode},
@@ -321,6 +322,7 @@ pub(crate) fn runnable_fn(
sema: &Semantics<'_, RootDatabase>,
def: hir::Function,
) -> Option<Runnable> {
+ let edition = def.krate(sema.db).edition(sema.db);
let under_cfg_test = has_cfg_test(def.module(sema.db).attrs(sema.db));
let kind = if !under_cfg_test && def.is_main(sema.db) {
RunnableKind::Bin
@@ -328,11 +330,11 @@ pub(crate) fn runnable_fn(
let test_id = || {
let canonical_path = {
let def: hir::ModuleDef = def.into();
- def.canonical_path(sema.db)
+ def.canonical_path(sema.db, edition)
};
canonical_path
.map(TestId::Path)
- .unwrap_or(TestId::Name(def.name(sema.db).display_no_db().to_smolstr()))
+ .unwrap_or(TestId::Name(def.name(sema.db).display_no_db(edition).to_smolstr()))
};
if def.is_test(sema.db) {
@@ -367,8 +369,11 @@ pub(crate) fn runnable_mod(
.path_to_root(sema.db)
.into_iter()
.rev()
- .filter_map(|it| it.name(sema.db))
- .map(|it| it.display(sema.db).to_string())
+ .filter_map(|module| {
+ module.name(sema.db).map(|mod_name| {
+ mod_name.display(sema.db, module.krate().edition(sema.db)).to_string()
+ })
+ })
.join("::");
let attrs = def.attrs(sema.db);
@@ -381,6 +386,7 @@ pub(crate) fn runnable_impl(
sema: &Semantics<'_, RootDatabase>,
def: &hir::Impl,
) -> Option<Runnable> {
+ let edition = def.module(sema.db).krate().edition(sema.db);
let attrs = def.attrs(sema.db);
if !has_runnable_doc_test(&attrs) {
return None;
@@ -389,13 +395,13 @@ 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).peekable();
+ let mut ty_args = ty.generic_parameters(sema.db, edition).peekable();
let params = if ty_args.peek().is_some() {
format!("<{}>", ty_args.format_with(",", |ty, cb| cb(&ty)))
} else {
String::new()
};
- let mut test_id = format!("{}{params}", adt_name.display(sema.db));
+ let mut test_id = format!("{}{params}", adt_name.display(sema.db, edition));
test_id.retain(|c| c != ' ');
let test_id = TestId::Path(test_id);
@@ -419,8 +425,11 @@ fn runnable_mod_outline_definition(
.path_to_root(sema.db)
.into_iter()
.rev()
- .filter_map(|it| it.name(sema.db))
- .map(|it| it.display(sema.db).to_string())
+ .filter_map(|module| {
+ module.name(sema.db).map(|mod_name| {
+ mod_name.display(sema.db, module.krate().edition(sema.db)).to_string()
+ })
+ })
.join("::");
let attrs = def.attrs(sema.db);
@@ -452,6 +461,7 @@ fn module_def_doctest(db: &RootDatabase, def: Definition) -> Option<Runnable> {
Definition::SelfType(it) => it.attrs(db),
_ => return None,
};
+ let edition = def.krate(db).map(|it| it.edition(db)).unwrap_or(Edition::CURRENT);
if !has_runnable_doc_test(&attrs) {
return None;
}
@@ -460,29 +470,29 @@ fn module_def_doctest(db: &RootDatabase, def: Definition) -> Option<Runnable> {
let mut path = String::new();
def.canonical_module_path(db)?
.flat_map(|it| it.name(db))
- .for_each(|name| format_to!(path, "{}::", name.display(db)));
+ .for_each(|name| format_to!(path, "{}::", name.display(db, edition)));
// This probably belongs to canonical_path?
if let Some(assoc_item) = def.as_assoc_item(db) {
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).peekable();
- format_to!(path, "{}", name.display(db));
+ let mut ty_args = ty.generic_parameters(db, edition).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)));
}
- format_to!(path, "::{}", def_name.display(db));
+ format_to!(path, "::{}", def_name.display(db, edition));
path.retain(|c| c != ' ');
return Some(path);
}
}
}
- format_to!(path, "{}", def_name.display(db));
+ format_to!(path, "{}", def_name.display(db, edition));
Some(path)
})();
- let test_id =
- path.map_or_else(|| TestId::Name(def_name.display_no_db().to_smolstr()), TestId::Path);
+ let test_id = path
+ .map_or_else(|| TestId::Name(def_name.display_no_db(edition).to_smolstr()), TestId::Path);
let mut nav = match def {
Definition::Module(def) => NavigationTarget::from_module_to_decl(db, def),
diff --git a/crates/ide/src/signature_help.rs b/crates/ide/src/signature_help.rs
index b6c9e2f636..9d3b8c6ebd 100644
--- a/crates/ide/src/signature_help.rs
+++ b/crates/ide/src/signature_help.rs
@@ -13,6 +13,7 @@ use ide_db::{
documentation::{Documentation, HasDocs},
FilePosition, FxIndexMap,
};
+use span::Edition;
use stdx::format_to;
use syntax::{
algo,
@@ -82,6 +83,8 @@ pub(crate) fn signature_help(
// this prevents us from leaving the CallExpression
.and_then(|tok| algo::skip_trivia_token(tok, Direction::Prev))?;
let token = sema.descend_into_macros_single(DescendPreference::None, token);
+ let edition =
+ sema.attach_first_edition(file_id).map(|it| it.edition()).unwrap_or(Edition::CURRENT);
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);
+ return signature_help_for_call(&sema, arg_list, token, edition);
},
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);
+ return signature_help_for_generics(&sema, garg_list, token, edition);
},
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);
+ return signature_help_for_record_lit(&sema, record, token, edition);
},
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);
+ return signature_help_for_record_pat(&sema, record, token, edition);
},
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);
+ return signature_help_for_tuple_struct_pat(&sema, tuple_pat, token, edition);
},
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);
+ return signature_help_for_tuple_pat(&sema, tuple_pat, token, edition);
},
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);
+ return signature_help_for_tuple_expr(&sema, tuple_expr, token, edition);
},
_ => (),
}
@@ -157,6 +160,7 @@ fn signature_help_for_call(
sema: &Semantics<'_, RootDatabase>,
arg_list: ast::ArgList,
token: SyntaxToken,
+ edition: Edition,
) -> Option<SignatureHelp> {
// Find the calling expression and its NameRef
let mut nodes = arg_list.syntax().ancestors().skip(1);
@@ -181,7 +185,7 @@ fn signature_help_for_call(
match callable.kind() {
hir::CallableKind::Function(func) => {
res.doc = func.docs(db);
- format_to!(res.signature, "fn {}", func.name(db).display(db));
+ format_to!(res.signature, "fn {}", func.name(db).display(db, edition));
fn_params = Some(match callable.receiver_param(db) {
Some(_self) => func.params_without_self(db),
None => func.assoc_fn_params(db),
@@ -189,15 +193,15 @@ fn signature_help_for_call(
}
hir::CallableKind::TupleStruct(strukt) => {
res.doc = strukt.docs(db);
- format_to!(res.signature, "struct {}", strukt.name(db).display(db));
+ format_to!(res.signature, "struct {}", strukt.name(db).display(db, edition));
}
hir::CallableKind::TupleEnumVariant(variant) => {
res.doc = variant.docs(db);
format_to!(
res.signature,
"enum {}::{}",
- variant.parent_enum(db).name(db).display(db),
- variant.name(db).display(db)
+ variant.parent_enum(db).name(db).display(db, edition),
+ variant.name(db).display(db, edition)
);
}
hir::CallableKind::Closure(closure) => {
@@ -210,7 +214,7 @@ fn signature_help_for_call(
Some(adt) => format_to!(
res.signature,
"<{} as {fn_trait}>::{}",
- adt.name(db).display(db),
+ adt.name(db).display(db, edition),
fn_trait.function_name()
),
None => format_to!(res.signature, "impl {fn_trait}"),
@@ -220,7 +224,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))
+ format_to!(res.signature, "{}", self_param.display(db, edition))
}
let mut buf = String::new();
for (idx, p) in callable.params().into_iter().enumerate() {
@@ -240,8 +244,10 @@ fn signature_help_for_call(
// This is overly conservative: we do not substitute known type vars
// (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)),
- _ => format_to!(buf, "{}", p.ty().display(db)),
+ (true, Some(fn_params)) => {
+ format_to!(buf, "{}", fn_params[idx].ty().display(db, edition))
+ }
+ _ => format_to!(buf, "{}", p.ty().display(db, edition)),
}
res.push_call_param(&buf);
}
@@ -250,7 +256,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));
+ format_to!(res.signature, " -> {}", ret_type.display(db, edition));
}
};
match callable.kind() {
@@ -270,6 +276,7 @@ fn signature_help_for_generics(
sema: &Semantics<'_, RootDatabase>,
arg_list: ast::GenericArgList,
token: SyntaxToken,
+ edition: Edition,
) -> Option<SignatureHelp> {
let (generics_def, mut active_parameter, first_arg_is_non_lifetime, variant) =
generic_def_for_node(sema, &arg_list, &token)?;
@@ -284,11 +291,11 @@ fn signature_help_for_generics(
match generics_def {
hir::GenericDef::Function(it) => {
res.doc = it.docs(db);
- format_to!(res.signature, "fn {}", it.name(db).display(db));
+ format_to!(res.signature, "fn {}", it.name(db).display(db, edition));
}
hir::GenericDef::Adt(hir::Adt::Enum(it)) => {
res.doc = it.docs(db);
- format_to!(res.signature, "enum {}", it.name(db).display(db));
+ format_to!(res.signature, "enum {}", it.name(db).display(db, edition));
if let Some(variant) = variant {
// In paths, generics of an enum can be specified *after* one of its variants.
// eg. `None::<u8>`
@@ -298,23 +305,23 @@ fn signature_help_for_generics(
}
hir::GenericDef::Adt(hir::Adt::Struct(it)) => {
res.doc = it.docs(db);
- format_to!(res.signature, "struct {}", it.name(db).display(db));
+ format_to!(res.signature, "struct {}", it.name(db).display(db, edition));
}
hir::GenericDef::Adt(hir::Adt::Union(it)) => {
res.doc = it.docs(db);
- format_to!(res.signature, "union {}", it.name(db).display(db));
+ format_to!(res.signature, "union {}", it.name(db).display(db, edition));
}
hir::GenericDef::Trait(it) => {
res.doc = it.docs(db);
- format_to!(res.signature, "trait {}", it.name(db).display(db));
+ format_to!(res.signature, "trait {}", it.name(db).display(db, edition));
}
hir::GenericDef::TraitAlias(it) => {
res.doc = it.docs(db);
- format_to!(res.signature, "trait {}", it.name(db).display(db));
+ format_to!(res.signature, "trait {}", it.name(db).display(db, edition));
}
hir::GenericDef::TypeAlias(it) => {
res.doc = it.docs(db);
- format_to!(res.signature, "type {}", it.name(db).display(db));
+ format_to!(res.signature, "type {}", it.name(db).display(db, edition));
}
// These don't have generic args that can be specified
hir::GenericDef::Impl(_) | hir::GenericDef::Const(_) => return None,
@@ -339,11 +346,11 @@ fn signature_help_for_generics(
}
buf.clear();
- format_to!(buf, "{}", param.display(db));
+ format_to!(buf, "{}", param.display(db, edition));
res.push_generic_param(&buf);
}
if let hir::GenericDef::Trait(tr) = generics_def {
- add_assoc_type_bindings(db, &mut res, tr, arg_list);
+ add_assoc_type_bindings(db, &mut res, tr, arg_list, edition);
}
res.signature.push('>');
@@ -355,6 +362,7 @@ fn add_assoc_type_bindings(
res: &mut SignatureHelp,
tr: Trait,
args: ast::GenericArgList,
+ edition: Edition,
) {
if args.syntax().ancestors().find_map(ast::TypeBound::cast).is_none() {
// Assoc type bindings are only valid in type bound position.
@@ -378,7 +386,7 @@ fn add_assoc_type_bindings(
for item in tr.items_with_supertraits(db) {
if let AssocItem::TypeAlias(ty) = item {
- let name = ty.name(db).display_no_db().to_smolstr();
+ let name = ty.name(db).display_no_db(edition).to_smolstr();
if !present_bindings.contains(&*name) {
buf.clear();
format_to!(buf, "{} = …", name);
@@ -392,6 +400,7 @@ fn signature_help_for_record_lit(
sema: &Semantics<'_, RootDatabase>,
record: ast::RecordExpr,
token: SyntaxToken,
+ edition: Edition,
) -> Option<SignatureHelp> {
signature_help_for_record_(
sema,
@@ -403,6 +412,7 @@ fn signature_help_for_record_lit(
.filter_map(|field| sema.resolve_record_field(&field))
.map(|(field, _, ty)| (field, ty)),
token,
+ edition,
)
}
@@ -410,6 +420,7 @@ fn signature_help_for_record_pat(
sema: &Semantics<'_, RootDatabase>,
record: ast::RecordPat,
token: SyntaxToken,
+ edition: Edition,
) -> Option<SignatureHelp> {
signature_help_for_record_(
sema,
@@ -420,6 +431,7 @@ fn signature_help_for_record_pat(
.fields()
.filter_map(|field| sema.resolve_record_pat_field(&field)),
token,
+ edition,
)
}
@@ -427,6 +439,7 @@ fn signature_help_for_tuple_struct_pat(
sema: &Semantics<'_, RootDatabase>,
pat: ast::TupleStructPat,
token: SyntaxToken,
+ edition: Edition,
) -> Option<SignatureHelp> {
let path = pat.path()?;
let path_res = sema.resolve_path(&path)?;
@@ -445,8 +458,8 @@ fn signature_help_for_tuple_struct_pat(
format_to!(
res.signature,
"enum {}::{} (",
- en.name(db).display(db),
- variant.name(db).display(db)
+ en.name(db).display(db, edition),
+ variant.name(db).display(db, edition)
);
variant.fields(db)
} else {
@@ -459,7 +472,7 @@ fn signature_help_for_tuple_struct_pat(
match adt {
hir::Adt::Struct(it) => {
res.doc = it.docs(db);
- format_to!(res.signature, "struct {} (", it.name(db).display(db));
+ format_to!(res.signature, "struct {} (", it.name(db).display(db, edition));
it.fields(db)
}
_ => return None,
@@ -472,6 +485,7 @@ fn signature_help_for_tuple_struct_pat(
token,
pat.fields(),
fields.into_iter().map(|it| it.ty(db)),
+ edition,
))
}
@@ -479,6 +493,7 @@ fn signature_help_for_tuple_pat(
sema: &Semantics<'_, RootDatabase>,
pat: ast::TuplePat,
token: SyntaxToken,
+ edition: Edition,
) -> Option<SignatureHelp> {
let db = sema.db;
let field_pats = pat.fields();
@@ -498,6 +513,7 @@ fn signature_help_for_tuple_pat(
token,
field_pats,
fields.into_iter(),
+ edition,
))
}
@@ -505,6 +521,7 @@ fn signature_help_for_tuple_expr(
sema: &Semantics<'_, RootDatabase>,
expr: ast::TupleExpr,
token: SyntaxToken,
+ edition: Edition,
) -> Option<SignatureHelp> {
let active_parameter = Some(
expr.syntax()
@@ -526,7 +543,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)));
+ format_to!(buf, "{}", ty.display_truncated(db, Some(20), edition));
res.push_call_param(&buf);
buf.clear();
}
@@ -540,6 +557,7 @@ fn signature_help_for_record_(
path: &ast::Path,
fields2: impl Iterator<Item = (hir::Field, hir::Type)>,
token: SyntaxToken,
+ edition: Edition,
) -> Option<SignatureHelp> {
let active_parameter = field_list_children
.filter_map(NodeOrToken::into_token)
@@ -566,8 +584,8 @@ fn signature_help_for_record_(
format_to!(
res.signature,
"enum {}::{} {{ ",
- en.name(db).display(db),
- variant.name(db).display(db)
+ en.name(db).display(db, edition),
+ variant.name(db).display(db, edition)
);
} else {
let adt = match path_res {
@@ -580,12 +598,12 @@ fn signature_help_for_record_(
hir::Adt::Struct(it) => {
fields = it.fields(db);
res.doc = it.docs(db);
- format_to!(res.signature, "struct {} {{ ", it.name(db).display(db));
+ format_to!(res.signature, "struct {} {{ ", it.name(db).display(db, edition));
}
hir::Adt::Union(it) => {
fields = it.fields(db);
res.doc = it.docs(db);
- format_to!(res.signature, "union {} {{ ", it.name(db).display(db));
+ format_to!(res.signature, "union {} {{ ", it.name(db).display(db, edition));
}
_ => return None,
}
@@ -596,7 +614,12 @@ fn signature_help_for_record_(
let mut buf = String::new();
for (field, ty) in fields2 {
let name = field.name(db);
- format_to!(buf, "{}: {}", name.display(db), ty.display_truncated(db, Some(20)));
+ format_to!(
+ buf,
+ "{}: {}",
+ name.display(db, edition),
+ ty.display_truncated(db, Some(20), edition)
+ );
res.push_record_field(&buf);
buf.clear();
@@ -606,7 +629,12 @@ fn signature_help_for_record_(
}
for (name, field) in fields {
let Some(field) = field else { continue };
- format_to!(buf, "{}: {}", name.display(db), field.ty(db).display_truncated(db, Some(20)));
+ format_to!(
+ buf,
+ "{}: {}",
+ name.display(db, edition),
+ field.ty(db).display_truncated(db, Some(20), edition)
+ );
res.push_record_field(&buf);
buf.clear();
}
@@ -621,6 +649,7 @@ fn signature_help_for_tuple_pat_ish(
token: SyntaxToken,
mut field_pats: AstChildren<ast::Pat>,
fields: impl ExactSizeIterator<Item = hir::Type>,
+ edition: Edition,
) -> SignatureHelp {
let rest_pat = field_pats.find(|it| matches!(it, ast::Pat::RestPat(_)));
let is_left_of_rest_pat =
@@ -647,7 +676,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)));
+ format_to!(buf, "{}", ty.display_truncated(db, Some(20), edition));
res.push_call_param(&buf);
buf.clear();
}
diff --git a/crates/ide/src/static_index.rs b/crates/ide/src/static_index.rs
index eaccee08e8..0f8d03c8d5 100644
--- a/crates/ide/src/static_index.rs
+++ b/crates/ide/src/static_index.rs
@@ -10,6 +10,7 @@ use ide_db::{
helpers::get_definition,
FileId, FileRange, FxHashMap, FxHashSet, RootDatabase,
};
+use span::Edition;
use syntax::{AstNode, SyntaxKind::*, SyntaxNode, TextRange, T};
use crate::inlay_hints::InlayFieldsToResolve;
@@ -116,7 +117,11 @@ fn documentation_for_definition(
_ => None,
};
- def.docs(sema.db, famous_defs.as_ref())
+ def.docs(
+ sema.db,
+ famous_defs.as_ref(),
+ def.krate(sema.db).map(|it| it.edition(sema.db)).unwrap_or(Edition::CURRENT),
+ )
}
impl StaticIndex<'_> {
@@ -161,6 +166,8 @@ impl StaticIndex<'_> {
// hovers
let sema = hir::Semantics::new(self.db);
let tokens_or_nodes = 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 tokens = tokens_or_nodes.descendants_with_tokens().filter_map(|it| match it {
syntax::NodeOrToken::Node(_) => None,
syntax::NodeOrToken::Token(it) => Some(it),
@@ -201,17 +208,20 @@ impl StaticIndex<'_> {
&node,
None,
&hover_config,
+ edition,
)),
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() }
}),
references: vec![],
moniker: current_crate.and_then(|cc| def_to_moniker(self.db, def, cc)),
- display_name: def.name(self.db).map(|name| name.display(self.db).to_string()),
+ display_name: def
+ .name(self.db)
+ .map(|name| name.display(self.db, edition).to_string()),
enclosing_moniker: current_crate
.zip(def.enclosing_definition(self.db))
.and_then(|(cc, enclosing_def)| def_to_moniker(self.db, enclosing_def, cc)),
- signature: Some(def.label(self.db)),
+ signature: Some(def.label(self.db, edition)),
kind: def_to_kind(self.db, def),
});
self.def_map.insert(def, it);
diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs
index 2318592005..e082fcdc76 100644
--- a/crates/ide/src/syntax_highlighting.rs
+++ b/crates/ide/src/syntax_highlighting.rs
@@ -501,7 +501,9 @@ fn traverse(
config.syntactic_name_ref_highlighting,
name_like,
),
- NodeOrToken::Token(token) => highlight::token(sema, token).zip(Some(None)),
+ NodeOrToken::Token(token) => {
+ highlight::token(sema, token, file_id.edition()).zip(Some(None))
+ }
};
if let Some((mut highlight, binding_hash)) = element {
if is_unlinked && highlight.tag == HlTag::UnresolvedReference {
diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs
index 70fdc0a1b3..eeba9cf35c 100644
--- a/crates/ide/src/syntax_highlighting/highlight.rs
+++ b/crates/ide/src/syntax_highlighting/highlight.rs
@@ -19,7 +19,11 @@ use crate::{
Highlight, HlMod, HlTag,
};
-pub(super) fn token(sema: &Semantics<'_, RootDatabase>, token: SyntaxToken) -> Option<Highlight> {
+pub(super) fn token(
+ sema: &Semantics<'_, RootDatabase>,
+ token: SyntaxToken,
+ edition: Edition,
+) -> Option<Highlight> {
if let Some(comment) = ast::Comment::cast(token.clone()) {
let h = HlTag::Comment;
return Some(match comment.kind().doc {
@@ -42,7 +46,7 @@ pub(super) fn token(sema: &Semantics<'_, RootDatabase>, token: SyntaxToken) -> O
HlTag::None.into()
}
p if p.is_punct() => punctuation(sema, token, p),
- k if k.is_keyword(Edition::CURRENT) => keyword(sema, token, k)?,
+ k if k.is_keyword(edition) => keyword(sema, token, k)?,
_ => return None,
};
Some(highlight)
diff --git a/crates/ide/src/syntax_highlighting/macro_.rs b/crates/ide/src/syntax_highlighting/macro_.rs
index 460fc4fe14..b441b4cc90 100644
--- a/crates/ide/src/syntax_highlighting/macro_.rs
+++ b/crates/ide/src/syntax_highlighting/macro_.rs
@@ -1,5 +1,4 @@
//! Syntax highlighting for macro_rules!.
-use span::Edition;
use syntax::{SyntaxKind, SyntaxToken, TextRange, T};
use crate::{HlRange, HlTag};
@@ -118,7 +117,7 @@ fn update_macro_state(state: &mut MacroMatcherParseState, tok: &SyntaxToken) {
fn is_metavariable(token: &SyntaxToken) -> Option<TextRange> {
match token.kind() {
- kind if kind == SyntaxKind::IDENT || kind.is_keyword(Edition::CURRENT) => {
+ kind if kind.is_any_identifier() => {
if let Some(_dollar) = token.prev_token().filter(|t| t.kind() == T![$]) {
return Some(token.text_range());
}
diff --git a/crates/ide/src/view_item_tree.rs b/crates/ide/src/view_item_tree.rs
index dae79998dc..a6352b99d4 100644
--- a/crates/ide/src/view_item_tree.rs
+++ b/crates/ide/src/view_item_tree.rs
@@ -16,5 +16,5 @@ pub(crate) fn view_item_tree(db: &RootDatabase, file_id: FileId) -> String {
let file_id = sema
.attach_first_edition(file_id)
.unwrap_or_else(|| EditionedFileId::current_edition(file_id));
- db.file_item_tree(file_id.into()).pretty_print(db)
+ db.file_item_tree(file_id.into()).pretty_print(db, file_id.edition())
}
diff --git a/crates/ide/src/view_memory_layout.rs b/crates/ide/src/view_memory_layout.rs
index df3f2f18b4..830c39e21e 100644
--- a/crates/ide/src/view_memory_layout.rs
+++ b/crates/ide/src/view_memory_layout.rs
@@ -6,6 +6,7 @@ use ide_db::{
helpers::{get_definition, pick_best_token},
RootDatabase,
};
+use span::Edition;
use syntax::{AstNode, SyntaxKind};
use crate::FilePosition;
@@ -85,6 +86,10 @@ pub(crate) fn view_memory_layout(
) -> Option<RecursiveMemoryLayout> {
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 token =
pick_best_token(file.syntax().token_at_offset(position.offset), |kind| match kind {
SyntaxKind::IDENT => 3,
@@ -111,6 +116,7 @@ pub(crate) fn view_memory_layout(
ty: &Type,
layout: &Layout,
parent_idx: usize,
+ edition: Edition,
) {
let mut fields = ty
.fields(db)
@@ -141,7 +147,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).to_string(),
+ typename: child_ty.display(db, edition).to_string(),
size: child_layout.size(),
alignment: child_layout.align(),
offset: match *field {
@@ -157,7 +163,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).to_string(),
+ typename: child_ty.display(db, edition).to_string(),
size: 0,
offset: 0,
alignment: 0,
@@ -170,7 +176,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);
+ read_layout(nodes, db, child_ty, &child_layout, children_start + i, edition);
}
}
}
@@ -188,7 +194,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).to_string();
+ let typename = ty.display(db, edition).to_string();
let mut nodes = vec![MemoryLayoutNode {
item_name,
@@ -200,7 +206,7 @@ pub(crate) fn view_memory_layout(
children_start: -1,
children_len: 0,
}];
- read_layout(&mut nodes, db, &ty, &layout, 0);
+ read_layout(&mut nodes, db, &ty, &layout, 0, edition);
RecursiveMemoryLayout { nodes }
})
diff --git a/crates/parser/src/syntax_kind.rs b/crates/parser/src/syntax_kind.rs
index 3ca6bd4cb1..6a8cca9ccc 100644
--- a/crates/parser/src/syntax_kind.rs
+++ b/crates/parser/src/syntax_kind.rs
@@ -3,6 +3,8 @@
mod generated;
+use crate::Edition;
+
#[allow(unreachable_pub)]
pub use self::generated::SyntaxKind;
@@ -26,4 +28,11 @@ impl SyntaxKind {
pub fn is_trivia(self) -> bool {
matches!(self, SyntaxKind::WHITESPACE | SyntaxKind::COMMENT)
}
+
+ /// Returns true if this is an identifier or a keyword.
+ #[inline]
+ pub fn is_any_identifier(self) -> bool {
+ // Assuming no edition removed keywords...
+ self == SyntaxKind::IDENT || self.is_keyword(Edition::LATEST)
+ }
}
diff --git a/crates/rust-analyzer/src/cli.rs b/crates/rust-analyzer/src/cli.rs
index 0bd6677b66..5eb6ff664f 100644
--- a/crates/rust-analyzer/src/cli.rs
+++ b/crates/rust-analyzer/src/cli.rs
@@ -21,7 +21,7 @@ use std::io::Read;
use anyhow::Result;
use hir::{Module, Name};
use hir_ty::db::HirDatabase;
-use ide::AnalysisHost;
+use ide::{AnalysisHost, Edition};
use itertools::Itertools;
use vfs::Vfs;
@@ -85,6 +85,6 @@ fn full_name_of_item(db: &dyn HirDatabase, module: Module, name: Name) -> String
.rev()
.filter_map(|it| it.name(db))
.chain(Some(name))
- .map(|it| it.display(db.upcast()).to_string())
+ .map(|it| it.display(db.upcast(), Edition::LATEST).to_string())
.join("::")
}
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs
index 06f4ba815d..44e56645ba 100644
--- a/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -17,7 +17,7 @@ use hir_def::{
};
use hir_ty::{Interner, Substitution, TyExt, TypeFlags};
use ide::{
- Analysis, AnalysisHost, AnnotationConfig, DiagnosticsConfig, InlayFieldsToResolve,
+ Analysis, AnalysisHost, AnnotationConfig, DiagnosticsConfig, Edition, InlayFieldsToResolve,
InlayHintsConfig, LineCol, RootDatabase,
};
use ide_db::{
@@ -309,7 +309,7 @@ impl flags::AnalysisStats {
let mut fail = 0;
for &c in consts {
all += 1;
- let Err(error) = c.render_eval(db) else {
+ let Err(error) = c.render_eval(db, Edition::LATEST) else {
continue;
};
if verbosity.is_spammy() {
@@ -442,6 +442,7 @@ impl flags::AnalysisStats {
prefer_prelude: true,
prefer_absolute: false,
},
+ Edition::LATEST,
)
.unwrap();
syntax_hit_found |= trim(&original_text) == trim(&generated);
@@ -563,7 +564,7 @@ impl flags::AnalysisStats {
.rev()
.filter_map(|it| it.name(db))
.chain(Some(body.name(db).unwrap_or_else(Name::missing)))
- .map(|it| it.display(db).to_string())
+ .map(|it| it.display(db, Edition::LATEST).to_string())
.join("::");
println!("Mir body for {full_name} failed due {e:?}");
}
@@ -628,12 +629,14 @@ impl flags::AnalysisStats {
.filter_map(|it| it.name(db))
.rev()
.chain(Some(body_id.name(db).unwrap_or_else(Name::missing)))
- .map(|it| it.display(db).to_string()),
+ .map(|it| it.display(db, Edition::LATEST).to_string()),
)
.join("::")
};
if let Some(only_name) = self.only.as_deref() {
- if name.display(db).to_string() != only_name && full_name() != only_name {
+ if name.display(db, Edition::LATEST).to_string() != only_name
+ && full_name() != only_name
+ {
continue;
}
}
@@ -687,7 +690,10 @@ impl flags::AnalysisStats {
end.col,
));
} else {
- bar.println(format!("{}: Unknown type", name.display(db)));
+ bar.println(format!(
+ "{}: Unknown type",
+ name.display(db, Edition::LATEST)
+ ));
}
}
true
@@ -708,17 +714,20 @@ impl flags::AnalysisStats {
start.col,
end.line + 1,
end.col,
- ty.display(db)
+ ty.display(db, Edition::LATEST)
));
} else {
- bar.println(format!("unknown location: {}", ty.display(db)));
+ bar.println(format!(
+ "unknown location: {}",
+ ty.display(db, Edition::LATEST)
+ ));
}
}
if unknown_or_partial && self.output == Some(OutputFormat::Csv) {
println!(
r#"{},type,"{}""#,
location_csv_expr(db, vfs, &sm(), expr_id),
- ty.display(db)
+ ty.display(db, Edition::LATEST)
);
}
if let Some(mismatch) = inference_result.type_mismatch_for_expr(expr_id) {
@@ -733,15 +742,15 @@ impl flags::AnalysisStats {
start.col,
end.line + 1,
end.col,
- mismatch.expected.display(db),
- mismatch.actual.display(db)
+ mismatch.expected.display(db, Edition::LATEST),
+ mismatch.actual.display(db, Edition::LATEST)
));
} else {
bar.println(format!(
"{}: Expected {}, got {}",
- name.display(db),
- mismatch.expected.display(db),
- mismatch.actual.display(db)
+ name.display(db, Edition::LATEST),
+ mismatch.expected.display(db, Edition::LATEST),
+ mismatch.actual.display(db, Edition::LATEST)
));
}
}
@@ -749,8 +758,8 @@ impl flags::AnalysisStats {
println!(
r#"{},mismatch,"{}","{}""#,
location_csv_expr(db, vfs, &sm(), expr_id),
- mismatch.expected.display(db),
- mismatch.actual.display(db)
+ mismatch.expected.display(db, Edition::LATEST),
+ mismatch.actual.display(db, Edition::LATEST)
);
}
}
@@ -785,7 +794,10 @@ impl flags::AnalysisStats {
end.col,
));
} else {
- bar.println(format!("{}: Unknown type", name.display(db)));
+ bar.println(format!(
+ "{}: Unknown type",
+ name.display(db, Edition::LATEST)
+ ));
}
}
true
@@ -806,17 +818,20 @@ impl flags::AnalysisStats {
start.col,
end.line + 1,
end.col,
- ty.display(db)
+ ty.display(db, Edition::LATEST)
));
} else {
- bar.println(format!("unknown location: {}", ty.display(db)));
+ bar.println(format!(
+ "unknown location: {}",
+ ty.display(db, Edition::LATEST)
+ ));
}
}
if unknown_or_partial && self.output == Some(OutputFormat::Csv) {
println!(
r#"{},type,"{}""#,
location_csv_pat(db, vfs, &sm(), pat_id),
- ty.display(db)
+ ty.display(db, Edition::LATEST)
);
}
if let Some(mismatch) = inference_result.type_mismatch_for_pat(pat_id) {
@@ -830,15 +845,15 @@ impl flags::AnalysisStats {
start.col,
end.line + 1,
end.col,
- mismatch.expected.display(db),
- mismatch.actual.display(db)
+ mismatch.expected.display(db, Edition::LATEST),
+ mismatch.actual.display(db, Edition::LATEST)
));
} else {
bar.println(format!(
"{}: Expected {}, got {}",
- name.display(db),
- mismatch.expected.display(db),
- mismatch.actual.display(db)
+ name.display(db, Edition::LATEST),
+ mismatch.expected.display(db, Edition::LATEST),
+ mismatch.actual.display(db, Edition::LATEST)
));
}
}
@@ -846,8 +861,8 @@ impl flags::AnalysisStats {
println!(
r#"{},mismatch,"{}","{}""#,
location_csv_pat(db, vfs, &sm(), pat_id),
- mismatch.expected.display(db),
- mismatch.actual.display(db)
+ mismatch.expected.display(db, Edition::LATEST),
+ mismatch.actual.display(db, Edition::LATEST)
);
}
}
@@ -923,12 +938,16 @@ impl flags::AnalysisStats {
.filter_map(|it| it.name(db))
.rev()
.chain(Some(body_id.name(db).unwrap_or_else(Name::missing)))
- .map(|it| it.display(db).to_string()),
+ .map(|it| it.display(db, Edition::LATEST).to_string()),
)
.join("::")
};
if let Some(only_name) = self.only.as_deref() {
- if body_id.name(db).unwrap_or_else(Name::missing).display(db).to_string()
+ if body_id
+ .name(db)
+ .unwrap_or_else(Name::missing)
+ .display(db, Edition::LATEST)
+ .to_string()
!= only_name
&& full_name() != only_name
{
diff --git a/crates/syntax-bridge/src/lib.rs b/crates/syntax-bridge/src/lib.rs
index 5153db2372..56e43e82ed 100644
--- a/crates/syntax-bridge/src/lib.rs
+++ b/crates/syntax-bridge/src/lib.rs
@@ -301,14 +301,11 @@ where
};
}
let leaf: tt::Leaf<_> = match kind {
- T![true] | T![false] => make_ident!(),
- IDENT => {
+ k if k.is_any_identifier() => {
let text = token.to_text(conv);
tt::Ident::new(&text, conv.span_for(abs_range)).into()
}
UNDERSCORE => make_ident!(),
- // FIXME: Edition
- k if k.is_keyword(Edition::CURRENT) => make_ident!(),
k if k.is_literal() => {
let text = token.to_text(conv);
let span = conv.span_for(abs_range);
diff --git a/crates/syntax/src/utils.rs b/crates/syntax/src/utils.rs
index 77d49b442e..d1f60f0b71 100644
--- a/crates/syntax/src/utils.rs
+++ b/crates/syntax/src/utils.rs
@@ -2,6 +2,7 @@
use crate::SyntaxKind;
+#[inline]
pub fn is_raw_identifier(name: &str, edition: parser::Edition) -> bool {
let is_keyword = SyntaxKind::from_keyword(name, edition).is_some();
is_keyword && !matches!(name, "self" | "crate" | "super" | "Self")