mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-13 05:38:46 +00:00
Properly account for editions in names
This PR touches a lot of parts. But the main changes are changing `hir_expand::Name` to be raw edition-dependently and only when necessary (unrelated to how the user originally wrote the identifier), and changing `is_keyword()` and `is_raw_identifier()` to be edition-aware (this was done in #17896, but the FIXMEs were fixed here). It is possible that I missed some cases, but most IDE parts should properly escape (or not escape) identifiers now. The rules of thumb are: - If we show the identifier to the user, its rawness should be determined by the edition of the edited crate. This is nice for IDE features, but really important for changes we insert to the source code. - For tests, I chose `Edition::CURRENT` (so we only have to (maybe) update tests when an edition becomes stable, to avoid churn). - For debugging tools (helper methods and logs), I used `Edition::LATEST`.
This commit is contained in:
parent
91aa3f46b3
commit
9d3368f2c2
179 changed files with 2485 additions and 1250 deletions
|
@ -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(
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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()),
|
||||
},
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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}}")?,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 })
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
@ -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)),
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
|
|
|
@ -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()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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()))
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
},
|
||||
|
|
|
@ -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)))
|
||||
}
|
||||
|
|
|
@ -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)?;
|
||||
|
|
|
@ -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)) => {
|
||||
|
|
|
@ -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:?}"),
|
||||
};
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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))
|
||||
};
|
||||
|
|
|
@ -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()))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>(
|
||||
|
|
|
@ -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()),
|
||||
}
|
||||
|
|
|
@ -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(),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
},
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)?;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
)
|
||||
});
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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| {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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(¶m_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}")),
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()),
|
||||
)
|
||||
})
|
||||
|
|
|
@ -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)))
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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,
|
||||
)
|
||||
},
|
||||
);
|
||||
|
|
|
@ -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)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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(),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
},
|
||||
)
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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}>")
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}),
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue