Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir/src/semantics.rs')
-rw-r--r--crates/hir/src/semantics.rs99
1 files changed, 54 insertions, 45 deletions
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index 769cfd90b8..82e60bff5e 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -13,7 +13,7 @@ use std::{
use either::Either;
use hir_def::{
DefWithBodyId, FunctionId, MacroId, StructId, TraitId, VariantId,
- expr_store::{Body, ExprOrPatSource, path::Path},
+ expr_store::{Body, ExprOrPatSource, HygieneId, path::Path},
hir::{BindingId, Expr, ExprId, ExprOrPatId, Pat},
nameres::{ModuleOrigin, crate_def_map},
resolver::{self, HasResolver, Resolver, TypeNs},
@@ -21,7 +21,6 @@ use hir_def::{
};
use hir_expand::{
EditionedFileId, ExpandResult, FileRange, HirFileId, InMacroFile, MacroCallId,
- attrs::collect_attrs,
builtin::{BuiltinFnLikeExpander, EagerExpander},
db::ExpandDatabase,
files::{FileRangeWrapper, HirFileRange, InRealFile},
@@ -29,6 +28,7 @@ use hir_expand::{
name::AsName,
};
use hir_ty::{
+ InferenceResult,
diagnostics::{unsafe_operations, unsafe_operations_for_body},
next_solver::DbInterner,
};
@@ -36,7 +36,7 @@ use intern::{Interned, Symbol, sym};
use itertools::Itertools;
use rustc_hash::{FxHashMap, FxHashSet};
use smallvec::{SmallVec, smallvec};
-use span::{Edition, FileId, SyntaxContext};
+use span::{FileId, SyntaxContext};
use stdx::{TupleExt, always};
use syntax::{
AstNode, AstToken, Direction, SyntaxKind, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange,
@@ -53,7 +53,7 @@ use crate::{
TypeAlias, TypeParam, Union, Variant, VariantDef,
db::HirDatabase,
semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx},
- source_analyzer::{SourceAnalyzer, name_hygiene, resolve_hir_path},
+ source_analyzer::{SourceAnalyzer, resolve_hir_path},
};
const CONTINUE_NO_BREAKS: ControlFlow<Infallible, ()> = ControlFlow::Continue(());
@@ -385,18 +385,18 @@ impl<'db> SemanticsImpl<'db> {
}
}
- pub fn attach_first_edition(&self, file: FileId) -> Option<EditionedFileId> {
- Some(EditionedFileId::new(
- self.db,
- file,
- self.file_to_module_defs(file).next()?.krate().edition(self.db),
- ))
+ pub fn attach_first_edition_opt(&self, file: FileId) -> Option<EditionedFileId> {
+ let krate = self.file_to_module_defs(file).next()?.krate();
+ Some(EditionedFileId::new(self.db, file, krate.edition(self.db), krate.id))
+ }
+
+ pub fn attach_first_edition(&self, file: FileId) -> EditionedFileId {
+ self.attach_first_edition_opt(file)
+ .unwrap_or_else(|| EditionedFileId::current_edition_guess_origin(self.db, file))
}
pub fn parse_guess_edition(&self, file_id: FileId) -> ast::SourceFile {
- let file_id = self
- .attach_first_edition(file_id)
- .unwrap_or_else(|| EditionedFileId::new(self.db, file_id, Edition::CURRENT));
+ let file_id = self.attach_first_edition(file_id);
let tree = self.db.parse(file_id).tree();
self.cache(tree.syntax().clone(), file_id.into());
@@ -405,7 +405,7 @@ impl<'db> SemanticsImpl<'db> {
pub fn adjust_edition(&self, file_id: HirFileId) -> HirFileId {
if let Some(editioned_file_id) = file_id.file_id() {
- self.attach_first_edition(editioned_file_id.file_id(self.db))
+ self.attach_first_edition_opt(editioned_file_id.file_id(self.db))
.map_or(file_id, Into::into)
} else {
file_id
@@ -1197,33 +1197,34 @@ impl<'db> SemanticsImpl<'db> {
.zip(Some(item))
})
.map(|(call_id, item)| {
- let attr_id = match db.lookup_intern_macro_call(call_id).kind {
+ let item_range = item.syntax().text_range();
+ let loc = db.lookup_intern_macro_call(call_id);
+ let text_range = match loc.kind {
hir_expand::MacroCallKind::Attr {
- invoc_attr_index, ..
- } => invoc_attr_index.ast_index(),
- _ => 0,
+ censored_attr_ids: attr_ids,
+ ..
+ } => {
+ // FIXME: here, the attribute's text range is used to strip away all
+ // entries from the start of the attribute "list" up the invoking
+ // attribute. But in
+ // ```
+ // mod foo {
+ // #![inner]
+ // }
+ // ```
+ // we don't wanna strip away stuff in the `mod foo {` range, that is
+ // here if the id corresponds to an inner attribute we got strip all
+ // text ranges of the outer ones, and then all of the inner ones up
+ // to the invoking attribute so that the inbetween is ignored.
+ // FIXME: Should cfg_attr be handled differently?
+ let (attr, _, _, _) = attr_ids
+ .invoc_attr()
+ .find_attr_range_with_source(db, loc.krate, &item);
+ let start = attr.syntax().text_range().start();
+ TextRange::new(start, item_range.end())
+ }
+ _ => item_range,
};
- // FIXME: here, the attribute's text range is used to strip away all
- // entries from the start of the attribute "list" up the invoking
- // attribute. But in
- // ```
- // mod foo {
- // #![inner]
- // }
- // ```
- // we don't wanna strip away stuff in the `mod foo {` range, that is
- // here if the id corresponds to an inner attribute we got strip all
- // text ranges of the outer ones, and then all of the inner ones up
- // to the invoking attribute so that the inbetween is ignored.
- let text_range = item.syntax().text_range();
- let start = collect_attrs(&item)
- .nth(attr_id)
- .map(|attr| match attr.1 {
- Either::Left(it) => it.syntax().text_range().start(),
- Either::Right(it) => it.syntax().text_range().start(),
- })
- .unwrap_or_else(|| text_range.start());
- let text_range = TextRange::new(start, text_range.end());
filter_duplicates(tokens, text_range);
process_expansion_for_token(ctx, &mut stack, call_id)
})
@@ -1473,6 +1474,14 @@ impl<'db> SemanticsImpl<'db> {
FileRangeWrapper { file_id: file_id.file_id(self.db), range }
}
+ pub fn diagnostics_display_range_for_range(
+ &self,
+ src: InFile<TextRange>,
+ ) -> FileRangeWrapper<FileId> {
+ let FileRange { file_id, range } = src.original_node_file_range_rooted(self.db);
+ FileRangeWrapper { file_id: file_id.file_id(self.db), range }
+ }
+
fn token_ancestors_with_macros(
&self,
token: SyntaxToken,
@@ -1655,7 +1664,7 @@ impl<'db> SemanticsImpl<'db> {
func: Function,
subst: impl IntoIterator<Item = Type<'db>>,
) -> Option<Function> {
- let interner = DbInterner::new_with(self.db, None, None);
+ let interner = DbInterner::new_no_crate(self.db);
let mut subst = subst.into_iter();
let substs =
hir_ty::next_solver::GenericArgs::for_item(interner, trait_.id.into(), |_, id, _| {
@@ -1769,9 +1778,9 @@ impl<'db> SemanticsImpl<'db> {
pub fn get_unsafe_ops(&self, def: DefWithBody) -> FxHashSet<ExprOrPatSource> {
let def = DefWithBodyId::from(def);
let (body, source_map) = self.db.body_with_source_map(def);
- let infer = self.db.infer(def);
+ let infer = InferenceResult::for_body(self.db, def);
let mut res = FxHashSet::default();
- unsafe_operations_for_body(self.db, &infer, def, &body, &mut |node| {
+ unsafe_operations_for_body(self.db, infer, def, &body, &mut |node| {
if let Ok(node) = source_map.expr_or_pat_syntax(node) {
res.insert(node);
}
@@ -1785,12 +1794,12 @@ impl<'db> SemanticsImpl<'db> {
let Some(def) = self.body_for(block.syntax()) else { return Vec::new() };
let def = def.into();
let (body, source_map) = self.db.body_with_source_map(def);
- let infer = self.db.infer(def);
+ let infer = InferenceResult::for_body(self.db, def);
let Some(ExprOrPatId::ExprId(block)) = source_map.node_expr(block.as_ref()) else {
return Vec::new();
};
let mut res = Vec::default();
- unsafe_operations(self.db, &infer, def, &body, block, &mut |node, _| {
+ unsafe_operations(self.db, infer, def, &body, block, &mut |node, _| {
if let Ok(node) = source_map.expr_or_pat_syntax(node) {
res.push(node);
}
@@ -2330,7 +2339,7 @@ impl<'db> SemanticsScope<'db> {
self.db,
&self.resolver,
&Path::BarePath(Interned::new(ModPath::from_segments(kind, segments))),
- name_hygiene(self.db, InFile::new(self.file_id, ast_path.syntax())),
+ HygieneId::ROOT,
None,
)
}