mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 20:42:04 +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
|
@ -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>(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue