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.rs | 142 |
1 files changed, 87 insertions, 55 deletions
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 5af8659ca6..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,19 +21,22 @@ use hir_def::{ }; use hir_expand::{ EditionedFileId, ExpandResult, FileRange, HirFileId, InMacroFile, MacroCallId, - attrs::collect_attrs, builtin::{BuiltinFnLikeExpander, EagerExpander}, db::ExpandDatabase, files::{FileRangeWrapper, HirFileRange, InRealFile}, mod_path::{ModPath, PathKind}, name::AsName, }; -use hir_ty::diagnostics::{unsafe_operations, unsafe_operations_for_body}; +use hir_ty::{ + InferenceResult, + diagnostics::{unsafe_operations, unsafe_operations_for_body}, + next_solver::DbInterner, +}; 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, @@ -50,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(()); @@ -382,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()); @@ -402,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 @@ -1194,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) }) @@ -1470,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, @@ -1553,8 +1565,8 @@ impl<'db> SemanticsImpl<'db> { pub fn expr_adjustments(&self, expr: &ast::Expr) -> Option<Vec<Adjustment<'db>>> { let mutability = |m| match m { - hir_ty::Mutability::Not => Mutability::Shared, - hir_ty::Mutability::Mut => Mutability::Mut, + hir_ty::next_solver::Mutability::Not => Mutability::Shared, + hir_ty::next_solver::Mutability::Mut => Mutability::Mut, }; let analyzer = self.analyze(expr.syntax())?; @@ -1565,7 +1577,7 @@ impl<'db> SemanticsImpl<'db> { it.iter() .map(|adjust| { let target = - Type::new_with_resolver(self.db, &analyzer.resolver, adjust.target.clone()); + Type::new_with_resolver(self.db, &analyzer.resolver, adjust.target); let kind = match adjust.kind { hir_ty::Adjust::NeverToAny => Adjust::NeverToAny, hir_ty::Adjust::Deref(Some(hir_ty::OverloadedDeref(m))) => { @@ -1578,9 +1590,9 @@ impl<'db> SemanticsImpl<'db> { hir_ty::Adjust::Borrow(hir_ty::AutoBorrow::RawPtr(m)) => { Adjust::Borrow(AutoBorrow::RawPtr(mutability(m))) } - hir_ty::Adjust::Borrow(hir_ty::AutoBorrow::Ref(_, m)) => { + hir_ty::Adjust::Borrow(hir_ty::AutoBorrow::Ref(m)) => { // FIXME: Handle lifetimes here - Adjust::Borrow(AutoBorrow::Ref(mutability(m))) + Adjust::Borrow(AutoBorrow::Ref(mutability(m.into()))) } hir_ty::Adjust::Pointer(pc) => Adjust::Pointer(pc), }; @@ -1652,11 +1664,15 @@ impl<'db> SemanticsImpl<'db> { func: Function, subst: impl IntoIterator<Item = Type<'db>>, ) -> Option<Function> { - let mut substs = hir_ty::TyBuilder::subst_for_def(self.db, TraitId::from(trait_), None); - for s in subst { - substs = substs.push(s.ty); - } - Some(self.db.lookup_impl_method(env.env, func.into(), substs.build()).0.into()) + 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, _| { + assert!(matches!(id, hir_def::GenericParamId::TypeParamId(_)), "expected a type"); + subst.next().expect("too few subst").ty.into() + }); + assert!(subst.next().is_none(), "too many subst"); + Some(self.db.lookup_impl_method(env.env, func.into(), substs).0.into()) } fn resolve_range_pat(&self, range_pat: &ast::RangePat) -> Option<StructId> { @@ -1762,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); } @@ -1778,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); } @@ -2098,6 +2114,22 @@ impl<'db> SemanticsImpl<'db> { parent = parent_; } } + + pub fn impl_generated_from_derive(&self, impl_: Impl) -> Option<Adt> { + let source = hir_def::src::HasSource::ast_ptr(&impl_.id.loc(self.db), self.db); + let mut file_id = source.file_id; + let adt_ast_id = loop { + let macro_call = file_id.macro_file()?; + match macro_call.loc(self.db).kind { + hir_expand::MacroCallKind::Derive { ast_id, .. } => break ast_id, + hir_expand::MacroCallKind::FnLike { ast_id, .. } => file_id = ast_id.file_id, + hir_expand::MacroCallKind::Attr { ast_id, .. } => file_id = ast_id.file_id, + } + }; + let adt_source = adt_ast_id.to_in_file_node(self.db); + self.cache(adt_source.value.syntax().ancestors().last().unwrap(), adt_source.file_id); + ToDef::to_def(self, adt_source.as_ref()) + } } // FIXME This can't be the best way to do this @@ -2307,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, ) } |