Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir/src/source_analyzer.rs')
| -rw-r--r-- | crates/hir/src/source_analyzer.rs | 360 |
1 files changed, 177 insertions, 183 deletions
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index 0b554a9d4e..15eab14b88 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -7,17 +7,10 @@ //! purely for "IDE needs". use std::iter::{self, once}; -use crate::{ - Adt, AssocItem, BindingMode, BuiltinAttr, BuiltinType, Callable, Const, DeriveHelper, Field, - Function, GenericSubstitution, Local, Macro, ModuleDef, Static, Struct, ToolModule, Trait, - TraitAlias, TupleField, Type, TypeAlias, Variant, - db::HirDatabase, - semantics::{PathResolution, PathResolutionPerNs}, -}; use either::Either; use hir_def::{ AdtId, AssocItemId, CallableDefId, ConstId, DefWithBodyId, FieldId, FunctionId, GenericDefId, - ItemContainerId, LocalFieldId, Lookup, ModuleDefId, StructId, TraitId, VariantId, + LocalFieldId, ModuleDefId, StructId, TraitId, VariantId, expr_store::{ Body, BodySourceMap, ExpressionStore, ExpressionStoreSourceMap, HygieneId, lower::ExprCollector, @@ -36,18 +29,24 @@ use hir_expand::{ name::{AsName, Name}, }; use hir_ty::{ - Adjustment, AliasTy, InferenceResult, Interner, LifetimeElisionKind, ProjectionTy, - Substitution, ToChalk, TraitEnvironment, Ty, TyExt, TyKind, TyLoweringContext, + Adjustment, InferenceResult, LifetimeElisionKind, TraitEnvironment, TyLoweringContext, diagnostics::{ InsideUnsafeBlock, record_literal_missing_fields, record_pattern_missing_fields, unsafe_operations, }, - from_assoc_type_id, lang_items::lang_items_for_bin_op, method_resolution, + next_solver::{ + DbInterner, ErrorGuaranteed, GenericArgs, Ty, TyKind, TypingMode, infer::DbInternerInferExt, + }, + traits::structurally_normalize_ty, }; use intern::sym; use itertools::Itertools; +use rustc_type_ir::{ + AliasTyKind, + inherent::{AdtDef, IntoKind, Ty as _}, +}; use smallvec::SmallVec; use stdx::never; use syntax::{ @@ -56,22 +55,30 @@ use syntax::{ }; use triomphe::Arc; +use crate::{ + Adt, AssocItem, BindingMode, BuiltinAttr, BuiltinType, Callable, Const, DeriveHelper, Field, + Function, GenericSubstitution, Local, Macro, ModuleDef, Static, Struct, ToolModule, Trait, + TupleField, Type, TypeAlias, Variant, + db::HirDatabase, + semantics::{PathResolution, PathResolutionPerNs}, +}; + /// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of /// original source files. It should not be used inside the HIR itself. #[derive(Debug)] pub(crate) struct SourceAnalyzer<'db> { pub(crate) file_id: HirFileId, pub(crate) resolver: Resolver<'db>, - pub(crate) body_or_sig: Option<BodyOrSig>, + pub(crate) body_or_sig: Option<BodyOrSig<'db>>, } #[derive(Debug)] -pub(crate) enum BodyOrSig { +pub(crate) enum BodyOrSig<'db> { Body { def: DefWithBodyId, body: Arc<Body>, source_map: Arc<BodySourceMap>, - infer: Option<Arc<InferenceResult>>, + infer: Option<Arc<InferenceResult<'db>>>, }, // To be folded into body once it is considered one VariantFields { @@ -111,7 +118,7 @@ impl<'db> SourceAnalyzer<'db> { def: DefWithBodyId, node @ InFile { file_id, .. }: InFile<&SyntaxNode>, offset: Option<TextSize>, - infer: Option<Arc<InferenceResult>>, + infer: Option<Arc<InferenceResult<'db>>>, ) -> SourceAnalyzer<'db> { let (body, source_map) = db.body_with_source_map(def); let scopes = db.expr_scopes(def); @@ -177,7 +184,9 @@ impl<'db> SourceAnalyzer<'db> { } // FIXME: Remove this - fn body_(&self) -> Option<(DefWithBodyId, &Body, &BodySourceMap, Option<&InferenceResult>)> { + fn body_( + &self, + ) -> Option<(DefWithBodyId, &Body, &BodySourceMap, Option<&InferenceResult<'db>>)> { self.body_or_sig.as_ref().and_then(|it| match it { BodyOrSig::Body { def, body, source_map, infer } => { Some((*def, &**body, &**source_map, infer.as_deref())) @@ -186,7 +195,7 @@ impl<'db> SourceAnalyzer<'db> { }) } - fn infer(&self) -> Option<&InferenceResult> { + fn infer(&self) -> Option<&InferenceResult<'db>> { self.body_or_sig.as_ref().and_then(|it| match it { BodyOrSig::Sig { .. } => None, BodyOrSig::VariantFields { .. } => None, @@ -218,7 +227,7 @@ impl<'db> SourceAnalyzer<'db> { }) } - fn trait_environment(&self, db: &'db dyn HirDatabase) -> Arc<TraitEnvironment> { + fn trait_environment(&self, db: &'db dyn HirDatabase) -> Arc<TraitEnvironment<'db>> { self.body_().map(|(def, ..)| def).map_or_else( || TraitEnvironment::empty(self.resolver.krate()), |def| db.trait_environment_for_body(def), @@ -245,7 +254,7 @@ impl<'db> SourceAnalyzer<'db> { if let Pat::Bind { id, .. } = self.store()?[pat_id.as_pat()?] { Some(id) } else { None } } - pub(crate) fn expr_adjustments(&self, expr: &ast::Expr) -> Option<&[Adjustment]> { + pub(crate) fn expr_adjustments(&self, expr: &ast::Expr) -> Option<&[Adjustment<'db>]> { // It is safe to omit destructuring assignments here because they have no adjustments (neither // expressions nor patterns). let expr_id = self.expr_id(expr.clone())?.as_expr()?; @@ -283,9 +292,9 @@ impl<'db> SourceAnalyzer<'db> { let coerced = expr_id .as_expr() .and_then(|expr_id| infer.expr_adjustment(expr_id)) - .and_then(|adjusts| adjusts.last().map(|adjust| adjust.target.clone())); - let ty = infer[expr_id].clone(); - let mk_ty = |ty| Type::new_with_resolver(db, &self.resolver, ty); + .and_then(|adjusts| adjusts.last().map(|adjust| adjust.target)); + let ty = infer[expr_id]; + let mk_ty = |ty: Ty<'db>| Type::new_with_resolver(db, &self.resolver, ty); Some((mk_ty(ty), coerced.map(mk_ty))) } @@ -306,8 +315,8 @@ impl<'db> SourceAnalyzer<'db> { } }; - let ty = infer[expr_or_pat_id].clone(); - let mk_ty = |ty| Type::new_with_resolver(db, &self.resolver, ty); + let ty = infer[expr_or_pat_id]; + let mk_ty = |ty: Ty<'db>| Type::new_with_resolver(db, &self.resolver, ty); Some((mk_ty(ty), coerced.map(mk_ty))) } @@ -318,8 +327,8 @@ impl<'db> SourceAnalyzer<'db> { ) -> Option<Type<'db>> { let binding_id = self.binding_id_of_pat(pat)?; let infer = self.infer()?; - let ty = infer[binding_id].clone(); - let mk_ty = |ty| Type::new_with_resolver(db, &self.resolver, ty); + let ty = infer[binding_id]; + let mk_ty = |ty: Ty<'db>| Type::new_with_resolver(db, &self.resolver, ty); Some(mk_ty(ty)) } @@ -329,7 +338,7 @@ impl<'db> SourceAnalyzer<'db> { _param: &ast::SelfParam, ) -> Option<Type<'db>> { let binding = self.body()?.self_param?; - let ty = self.infer()?[binding].clone(); + let ty = self.infer()?[binding]; Some(Type::new_with_resolver(db, &self.resolver, ty)) } @@ -342,8 +351,10 @@ impl<'db> SourceAnalyzer<'db> { let infer = self.infer()?; infer.binding_mode(id.as_pat()?).map(|bm| match bm { hir_ty::BindingMode::Move => BindingMode::Move, - hir_ty::BindingMode::Ref(hir_ty::Mutability::Mut) => BindingMode::Ref(Mutability::Mut), - hir_ty::BindingMode::Ref(hir_ty::Mutability::Not) => { + hir_ty::BindingMode::Ref(hir_ty::next_solver::Mutability::Mut) => { + BindingMode::Ref(Mutability::Mut) + } + hir_ty::BindingMode::Ref(hir_ty::next_solver::Mutability::Not) => { BindingMode::Ref(Mutability::Shared) } }) @@ -359,7 +370,7 @@ impl<'db> SourceAnalyzer<'db> { infer .pat_adjustment(pat_id.as_pat()?)? .iter() - .map(|ty| Type::new_with_resolver(db, &self.resolver, ty.clone())) + .map(|ty| Type::new_with_resolver(db, &self.resolver, *ty)) .collect(), ) } @@ -370,8 +381,9 @@ impl<'db> SourceAnalyzer<'db> { call: &ast::MethodCallExpr, ) -> Option<Callable<'db>> { let expr_id = self.expr_id(call.clone().into())?.as_expr()?; - let (func, substs) = self.infer()?.method_resolution(expr_id)?; - let ty = db.value_ty(func.into())?.substitute(Interner, &substs); + let (func, args) = self.infer()?.method_resolution(expr_id)?; + let interner = DbInterner::new_with(db, None, None); + let ty = db.value_ty(func.into())?.instantiate(interner, args); let ty = Type::new_with_resolver(db, &self.resolver, ty); let mut res = ty.as_callable(db)?; res.is_bound_method = true; @@ -436,17 +448,13 @@ impl<'db> SourceAnalyzer<'db> { fn field_subst( &self, field_expr: ExprId, - infer: &InferenceResult, + infer: &InferenceResult<'db>, db: &'db dyn HirDatabase, ) -> Option<GenericSubstitution<'db>> { let body = self.store()?; if let Expr::Field { expr: object_expr, name: _ } = body[field_expr] { let (adt, subst) = infer.type_of_expr_with_adjust(object_expr)?.as_adt()?; - return Some(GenericSubstitution::new( - adt.into(), - subst.clone(), - self.trait_environment(db), - )); + return Some(GenericSubstitution::new(adt.into(), subst, self.trait_environment(db))); } None } @@ -529,7 +537,7 @@ impl<'db> SourceAnalyzer<'db> { db: &'db dyn HirDatabase, await_expr: &ast::AwaitExpr, ) -> Option<FunctionId> { - let mut ty = self.ty_of_expr(await_expr.expr()?)?.clone(); + let mut ty = self.ty_of_expr(await_expr.expr()?)?; let into_future_trait = self .resolver @@ -537,7 +545,7 @@ impl<'db> SourceAnalyzer<'db> { .map(Trait::from); if let Some(into_future_trait) = into_future_trait { - let type_ = Type::new_with_resolver(db, &self.resolver, ty.clone()); + let type_ = Type::new_with_resolver(db, &self.resolver, ty); if type_.impls_trait(db, into_future_trait, &[]) { let items = into_future_trait.items(db); let into_future_type = items.into_iter().find_map(|item| match item { @@ -553,11 +561,11 @@ impl<'db> SourceAnalyzer<'db> { } } - let future_trait = LangItem::Future.resolve_trait(db, self.resolver.krate())?; let poll_fn = LangItem::FuturePoll.resolve_function(db, self.resolver.krate())?; // HACK: subst for `poll()` coincides with that for `Future` because `poll()` itself // doesn't have any generic parameters, so we skip building another subst for `poll()`. - let substs = hir_ty::TyBuilder::subst_for_def(db, future_trait, None).push(ty).build(); + let interner = DbInterner::new_with(db, None, None); + let substs = GenericArgs::new_from_iter(interner, [ty.into()]); Some(self.resolve_impl_method_or_trait_def(db, poll_fn, substs)) } @@ -566,7 +574,7 @@ impl<'db> SourceAnalyzer<'db> { db: &'db dyn HirDatabase, prefix_expr: &ast::PrefixExpr, ) -> Option<FunctionId> { - let (op_trait, op_fn) = match prefix_expr.op_kind()? { + let (_op_trait, op_fn) = match prefix_expr.op_kind()? { ast::UnaryOp::Deref => { // This can be either `Deref::deref` or `DerefMut::deref_mut`. // Since deref kind is inferenced and stored in `InferenceResult.method_resolution`, @@ -596,9 +604,10 @@ impl<'db> SourceAnalyzer<'db> { let ty = self.ty_of_expr(prefix_expr.expr()?)?; + let interner = DbInterner::new_with(db, None, None); // HACK: subst for all methods coincides with that for their trait because the methods // don't have any generic parameters, so we skip building another subst for the methods. - let substs = hir_ty::TyBuilder::subst_for_def(db, op_trait, None).push(ty.clone()).build(); + let substs = GenericArgs::new_from_iter(interner, [ty.into()]); Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs)) } @@ -611,27 +620,25 @@ impl<'db> SourceAnalyzer<'db> { let base_ty = self.ty_of_expr(index_expr.base()?)?; let index_ty = self.ty_of_expr(index_expr.index()?)?; - let (index_trait, index_fn) = + let (_index_trait, index_fn) = self.lang_trait_fn(db, LangItem::Index, &Name::new_symbol_root(sym::index))?; - let (op_trait, op_fn) = self + let op_fn = self .infer() .and_then(|infer| { let expr = self.expr_id(index_expr.clone().into())?.as_expr()?; let (func, _) = infer.method_resolution(expr)?; - let (index_mut_trait, index_mut_fn) = self.lang_trait_fn( + let (_index_mut_trait, index_mut_fn) = self.lang_trait_fn( db, LangItem::IndexMut, &Name::new_symbol_root(sym::index_mut), )?; - if func == index_mut_fn { Some((index_mut_trait, index_mut_fn)) } else { None } + if func == index_mut_fn { Some(index_mut_fn) } else { None } }) - .unwrap_or((index_trait, index_fn)); + .unwrap_or(index_fn); // HACK: subst for all methods coincides with that for their trait because the methods // don't have any generic parameters, so we skip building another subst for the methods. - let substs = hir_ty::TyBuilder::subst_for_def(db, op_trait, None) - .push(base_ty.clone()) - .push(index_ty.clone()) - .build(); + let interner = DbInterner::new_with(db, None, None); + let substs = GenericArgs::new_from_iter(interner, [base_ty.into(), index_ty.into()]); Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs)) } @@ -644,14 +651,12 @@ impl<'db> SourceAnalyzer<'db> { let lhs = self.ty_of_expr(binop_expr.lhs()?)?; let rhs = self.ty_of_expr(binop_expr.rhs()?)?; - let (op_trait, op_fn) = lang_items_for_bin_op(op) + let (_op_trait, op_fn) = lang_items_for_bin_op(op) .and_then(|(name, lang_item)| self.lang_trait_fn(db, lang_item, &name))?; // HACK: subst for `index()` coincides with that for `Index` because `index()` itself // doesn't have any generic parameters, so we skip building another subst for `index()`. - let substs = hir_ty::TyBuilder::subst_for_def(db, op_trait, None) - .push(lhs.clone()) - .push(rhs.clone()) - .build(); + let interner = DbInterner::new_with(db, None, None); + let substs = GenericArgs::new_from_iter(interner, [lhs.into(), rhs.into()]); Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs)) } @@ -664,13 +669,10 @@ impl<'db> SourceAnalyzer<'db> { let ty = self.ty_of_expr(try_expr.expr()?)?; let op_fn = LangItem::TryTraitBranch.resolve_function(db, self.resolver.krate())?; - let op_trait = match op_fn.lookup(db).container { - ItemContainerId::TraitId(id) => id, - _ => return None, - }; // HACK: subst for `branch()` coincides with that for `Try` because `branch()` itself // doesn't have any generic parameters, so we skip building another subst for `branch()`. - let substs = hir_ty::TyBuilder::subst_for_def(db, op_trait, None).push(ty.clone()).build(); + let interner = DbInterner::new_with(db, None, None); + let substs = GenericArgs::new_from_iter(interner, [ty.into()]); Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs)) } @@ -683,6 +685,7 @@ impl<'db> SourceAnalyzer<'db> { let record_expr = ast::RecordExpr::cast(field.syntax().parent().and_then(|p| p.parent())?)?; let expr = ast::Expr::from(record_expr); let expr_id = self.store_sm()?.node_expr(InFile::new(self.file_id, &expr))?; + let interner = DbInterner::new_with(db, None, None); let ast_name = field.field_name()?; let local_name = ast_name.as_name(); @@ -709,13 +712,12 @@ impl<'db> SourceAnalyzer<'db> { let variant = self.infer()?.variant_resolution_for_expr_or_pat(expr_id)?; let variant_data = variant.fields(db); let field = FieldId { parent: variant, local_id: variant_data.field(&local_name)? }; - let field_ty = - db.field_types(variant).get(field.local_id)?.clone().substitute(Interner, subst); + let field_ty = (*db.field_types(variant).get(field.local_id)?).instantiate(interner, subst); Some(( field.into(), local, Type::new_with_resolver(db, &self.resolver, field_ty), - GenericSubstitution::new(adt.into(), subst.clone(), self.trait_environment(db)), + GenericSubstitution::new(adt.into(), subst, self.trait_environment(db)), )) } @@ -724,6 +726,7 @@ impl<'db> SourceAnalyzer<'db> { db: &'db dyn HirDatabase, field: &ast::RecordPatField, ) -> Option<(Field, Type<'db>, GenericSubstitution<'db>)> { + let interner = DbInterner::new_with(db, None, None); let field_name = field.field_name()?.as_name(); let record_pat = ast::RecordPat::cast(field.syntax().parent().and_then(|p| p.parent())?)?; let pat_id = self.pat_id(&record_pat.into())?; @@ -731,12 +734,11 @@ impl<'db> SourceAnalyzer<'db> { let variant_data = variant.fields(db); let field = FieldId { parent: variant, local_id: variant_data.field(&field_name)? }; let (adt, subst) = self.infer()?[pat_id.as_pat()?].as_adt()?; - let field_ty = - db.field_types(variant).get(field.local_id)?.clone().substitute(Interner, subst); + let field_ty = (*db.field_types(variant).get(field.local_id)?).instantiate(interner, subst); Some(( field.into(), Type::new_with_resolver(db, &self.resolver, field_ty), - GenericSubstitution::new(adt.into(), subst.clone(), self.trait_environment(db)), + GenericSubstitution::new(adt.into(), subst, self.trait_environment(db)), )) } @@ -785,43 +787,40 @@ impl<'db> SourceAnalyzer<'db> { let container = self.type_of_type(db, &container)?; let trait_env = container.env; + + let interner = DbInterner::new_with(db, Some(trait_env.krate), trait_env.block); + let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis); + let mut container = Either::Right(container.ty); for field_name in offset_of_expr.fields() { - if let Some( - TyKind::Alias(AliasTy::Projection(ProjectionTy { associated_ty_id, substitution })) - | TyKind::AssociatedType(associated_ty_id, substitution), - ) = container.as_ref().right().map(|it| it.kind(Interner)) - { - let projection = ProjectionTy { - associated_ty_id: *associated_ty_id, - substitution: substitution.clone(), - }; - container = Either::Right(db.normalize_projection(projection, trait_env.clone())); + if let Either::Right(container) = &mut container { + *container = structurally_normalize_ty(&infcx, *container, trait_env.clone()); } - let handle_variants = |variant: VariantId, subst: &Substitution, container: &mut _| { - let fields = variant.fields(db); - let field = fields.field(&field_name.as_name())?; - let field_types = db.field_types(variant); - *container = Either::Right(field_types[field].clone().substitute(Interner, subst)); - let generic_def = match variant { - VariantId::EnumVariantId(it) => it.loc(db).parent.into(), - VariantId::StructId(it) => it.into(), - VariantId::UnionId(it) => it.into(), + let handle_variants = + |variant: VariantId, subst: GenericArgs<'db>, container: &mut _| { + let fields = variant.fields(db); + let field = fields.field(&field_name.as_name())?; + let field_types = db.field_types(variant); + *container = Either::Right(field_types[field].instantiate(interner, subst)); + let generic_def = match variant { + VariantId::EnumVariantId(it) => it.loc(db).parent.into(), + VariantId::StructId(it) => it.into(), + VariantId::UnionId(it) => it.into(), + }; + Some(( + Either::Right(Field { parent: variant.into(), id: field }), + generic_def, + subst, + )) }; - Some(( - Either::Right(Field { parent: variant.into(), id: field }), - generic_def, - subst.clone(), - )) - }; - let temp_ty = TyKind::Error.intern(Interner); + let temp_ty = Ty::new_error(interner, ErrorGuaranteed); let (field_def, generic_def, subst) = - match std::mem::replace(&mut container, Either::Right(temp_ty.clone())) { + match std::mem::replace(&mut container, Either::Right(temp_ty)) { Either::Left((variant_id, subst)) => { - handle_variants(VariantId::from(variant_id), &subst, &mut container)? + handle_variants(VariantId::from(variant_id), subst, &mut container)? } - Either::Right(container_ty) => match container_ty.kind(Interner) { - TyKind::Adt(adt_id, subst) => match adt_id.0 { + Either::Right(container_ty) => match container_ty.kind() { + TyKind::Adt(adt_def, subst) => match adt_def.def_id().0 { AdtId::StructId(id) => { handle_variants(id.into(), subst, &mut container)? } @@ -831,8 +830,8 @@ impl<'db> SourceAnalyzer<'db> { AdtId::EnumId(id) => { let variants = id.enum_variants(db); let variant = variants.variant(&field_name.as_name())?; - container = Either::Left((variant, subst.clone())); - (Either::Left(Variant { id: variant }), id.into(), subst.clone()) + container = Either::Left((variant, subst)); + (Either::Left(Variant { id: variant }), id.into(), subst) } }, _ => return None, @@ -873,12 +872,10 @@ impl<'db> SourceAnalyzer<'db> { (assoc, subst) } Some(func_ty) => { - if let TyKind::FnDef(_fn_def, subs) = func_ty.kind(Interner) { + if let TyKind::FnDef(_fn_def, subs) = func_ty.kind() { let (fn_, subst) = self .resolve_impl_method_or_trait_def_with_subst( - db, - f_in_trait, - subs.clone(), + db, f_in_trait, subs, ); let subst = GenericSubstitution::new( fn_.into(), @@ -995,11 +992,11 @@ impl<'db> SourceAnalyzer<'db> { // Case where path is a qualifier of a use tree, e.g. foo::bar::{Baz, Qux} where we are // trying to resolve foo::bar. - if let Some(use_tree) = parent().and_then(ast::UseTree::cast) { - if use_tree.coloncolon_token().is_some() { - return resolve_hir_path_qualifier(db, &self.resolver, &hir_path, &store) - .map(|it| (it, None)); - } + if let Some(use_tree) = parent().and_then(ast::UseTree::cast) + && use_tree.coloncolon_token().is_some() + { + return resolve_hir_path_qualifier(db, &self.resolver, &hir_path, &store) + .map(|it| (it, None)); } let meta_path = path @@ -1035,24 +1032,19 @@ impl<'db> SourceAnalyzer<'db> { // } // ``` Some(it) if matches!(it, PathResolution::Def(ModuleDef::BuiltinType(_))) => { - if let Some(mod_path) = hir_path.mod_path() { - if let Some(ModuleDefId::ModuleId(id)) = + if let Some(mod_path) = hir_path.mod_path() + && let Some(ModuleDefId::ModuleId(id)) = self.resolver.resolve_module_path_in_items(db, mod_path).take_types() + { + let parent_hir_name = parent_hir_path.segments().get(1).map(|it| it.name); + let module = crate::Module { id }; + if module + .scope(db, None) + .into_iter() + .any(|(name, _)| Some(&name) == parent_hir_name) { - let parent_hir_name = - parent_hir_path.segments().get(1).map(|it| it.name); - let module = crate::Module { id }; - if module - .scope(db, None) - .into_iter() - .any(|(name, _)| Some(&name) == parent_hir_name) - { - return Some(( - PathResolution::Def(ModuleDef::Module(module)), - None, - )); - }; - } + return Some((PathResolution::Def(ModuleDef::Module(module)), None)); + }; } Some((it, None)) } @@ -1066,8 +1058,7 @@ impl<'db> SourceAnalyzer<'db> { // in this case we have to check for inert/builtin attributes and tools and prioritize // resolution of attributes over other namespaces if let Some(name_ref) = path.as_single_name_ref() { - let builtin = - BuiltinAttr::by_name(db, self.resolver.krate().into(), &name_ref.text()); + let builtin = BuiltinAttr::builtin(&name_ref.text()); if builtin.is_some() { return builtin.map(|it| (PathResolution::BuiltinAttr(it), None)); } @@ -1151,33 +1142,35 @@ impl<'db> SourceAnalyzer<'db> { self.infer()?.type_of_expr_or_pat(expr_id)? } else if let Some(pat) = ast::Pat::cast(parent) { let pat_id = self.pat_id(&pat)?; - &self.infer()?[pat_id] + self.infer()?[pat_id] } else { return None; }; let env = self.trait_environment(db); - let (subst, expected_resolution) = match ty.kind(Interner) { - TyKind::Adt(adt_id, subst) => ( - GenericSubstitution::new(adt_id.0.into(), subst.clone(), env), - PathResolution::Def(ModuleDef::Adt(adt_id.0.into())), - ), - TyKind::AssociatedType(assoc_id, subst) => { - let assoc_id = from_assoc_type_id(*assoc_id); + let (subst, expected_resolution) = match ty.kind() { + TyKind::Adt(adt_def, subst) => { + let adt_id = adt_def.def_id().0; ( - GenericSubstitution::new(assoc_id.into(), subst.clone(), env), + GenericSubstitution::new(adt_id.into(), subst, env), + PathResolution::Def(ModuleDef::Adt(adt_id.into())), + ) + } + TyKind::Alias(AliasTyKind::Projection, alias) => { + let assoc_id = alias.def_id.expect_type_alias(); + ( + GenericSubstitution::new(assoc_id.into(), alias.args, env), PathResolution::Def(ModuleDef::TypeAlias(assoc_id.into())), ) } TyKind::FnDef(fn_id, subst) => { - let fn_id = ToChalk::from_chalk(db, *fn_id); - let generic_def_id = match fn_id { + let generic_def_id = match fn_id.0 { CallableDefId::StructId(id) => id.into(), CallableDefId::FunctionId(id) => id.into(), CallableDefId::EnumVariantId(_) => return None, }; ( - GenericSubstitution::new(generic_def_id, subst.clone(), env), - PathResolution::Def(ModuleDefId::from(fn_id).into()), + GenericSubstitution::new(generic_def_id, subst, env), + PathResolution::Def(ModuleDefId::from(fn_id.0).into()), ) } _ => return None, @@ -1255,17 +1248,18 @@ impl<'db> SourceAnalyzer<'db> { fn missing_fields( &self, db: &'db dyn HirDatabase, - substs: &Substitution, + substs: GenericArgs<'db>, variant: VariantId, missing_fields: Vec<LocalFieldId>, ) -> Vec<(Field, Type<'db>)> { + let interner = DbInterner::new_with(db, None, None); let field_types = db.field_types(variant); missing_fields .into_iter() .map(|local_id| { let field = FieldId { parent: variant, local_id }; - let ty = field_types[local_id].clone().substitute(Interner, substs); + let ty = field_types[local_id].instantiate(interner, substs); (field.into(), Type::new_with_resolver_inner(db, &self.resolver, ty)) }) .collect() @@ -1282,22 +1276,22 @@ impl<'db> SourceAnalyzer<'db> { db: &'db dyn HirDatabase, macro_expr: InFile<&ast::MacroExpr>, ) -> bool { - if let Some((def, body, sm, Some(infer))) = self.body_() { - if let Some(expanded_expr) = sm.macro_expansion_expr(macro_expr) { - let mut is_unsafe = false; - let mut walk_expr = |expr_id| { - unsafe_operations(db, infer, def, body, expr_id, &mut |inside_unsafe_block| { - is_unsafe |= inside_unsafe_block == InsideUnsafeBlock::No - }) - }; - match expanded_expr { - ExprOrPatId::ExprId(expanded_expr) => walk_expr(expanded_expr), - ExprOrPatId::PatId(expanded_pat) => { - body.walk_exprs_in_pat(expanded_pat, &mut walk_expr) - } + if let Some((def, body, sm, Some(infer))) = self.body_() + && let Some(expanded_expr) = sm.macro_expansion_expr(macro_expr) + { + let mut is_unsafe = false; + let mut walk_expr = |expr_id| { + unsafe_operations(db, infer, def, body, expr_id, &mut |_, inside_unsafe_block| { + is_unsafe |= inside_unsafe_block == InsideUnsafeBlock::No + }) + }; + match expanded_expr { + ExprOrPatId::ExprId(expanded_expr) => walk_expr(expanded_expr), + ExprOrPatId::PatId(expanded_pat) => { + body.walk_exprs_in_pat(expanded_pat, &mut walk_expr) } - return is_unsafe; } + return is_unsafe; } false } @@ -1378,7 +1372,7 @@ impl<'db> SourceAnalyzer<'db> { &self, db: &'db dyn HirDatabase, func: FunctionId, - substs: Substitution, + substs: GenericArgs<'db>, ) -> FunctionId { self.resolve_impl_method_or_trait_def_with_subst(db, func, substs).0 } @@ -1387,8 +1381,8 @@ impl<'db> SourceAnalyzer<'db> { &self, db: &'db dyn HirDatabase, func: FunctionId, - substs: Substitution, - ) -> (FunctionId, Substitution) { + substs: GenericArgs<'db>, + ) -> (FunctionId, GenericArgs<'db>) { let owner = match self.resolver.body_owner() { Some(it) => it, None => return (func, substs), @@ -1401,14 +1395,16 @@ impl<'db> SourceAnalyzer<'db> { &self, db: &'db dyn HirDatabase, const_id: ConstId, - subs: Substitution, - ) -> (ConstId, Substitution) { + subs: GenericArgs<'db>, + ) -> (ConstId, GenericArgs<'db>) { let owner = match self.resolver.body_owner() { Some(it) => it, None => return (const_id, subs), }; let env = db.trait_environment_for_body(owner); - method_resolution::lookup_impl_const(db, env, const_id, subs) + let interner = DbInterner::new_with(db, Some(env.krate), env.block); + let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis); + method_resolution::lookup_impl_const(&infcx, env, const_id, subs) } fn lang_trait_fn( @@ -1422,7 +1418,7 @@ impl<'db> SourceAnalyzer<'db> { Some((trait_id, fn_id)) } - fn ty_of_expr(&self, expr: ast::Expr) -> Option<&Ty> { + fn ty_of_expr(&self, expr: ast::Expr) -> Option<Ty<'db>> { self.infer()?.type_of_expr_or_pat(self.expr_id(expr)?) } } @@ -1575,12 +1571,11 @@ fn resolve_hir_path_( // If we are in a TypeNs for a Trait, and we have an unresolved name, try to resolve it as a type // within the trait's associated types. - if let (Some(unresolved), &TypeNs::TraitId(trait_id)) = (&unresolved, &ty) { - if let Some(type_alias_id) = + if let (Some(unresolved), &TypeNs::TraitId(trait_id)) = (&unresolved, &ty) + && let Some(type_alias_id) = trait_id.trait_items(db).associated_type_by_name(unresolved.name) - { - return Some(PathResolution::Def(ModuleDefId::from(type_alias_id).into())); - } + { + return Some(PathResolution::Def(ModuleDefId::from(type_alias_id).into())); } let res = match ty { @@ -1593,19 +1588,20 @@ fn resolve_hir_path_( TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()), TypeNs::BuiltinType(it) => PathResolution::Def(BuiltinType::from(it).into()), TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()), - TypeNs::TraitAliasId(it) => PathResolution::Def(TraitAlias::from(it).into()), TypeNs::ModuleId(it) => PathResolution::Def(ModuleDef::Module(it.into())), }; match unresolved { Some(unresolved) => resolver .generic_def() .and_then(|def| { - hir_ty::associated_type_shorthand_candidates( - db, - def, - res.in_type_ns()?, - |name, id| (name == unresolved.name).then_some(id), - ) + hir_ty::attach_db(db, || { + hir_ty::associated_type_shorthand_candidates( + db, + def, + res.in_type_ns()?, + |name, _| name == unresolved.name, + ) + }) }) .map(TypeAlias::from) .map(Into::into) @@ -1726,12 +1722,11 @@ fn resolve_hir_path_qualifier( // If we are in a TypeNs for a Trait, and we have an unresolved name, try to resolve it as a type // within the trait's associated types. - if let (Some(unresolved), &TypeNs::TraitId(trait_id)) = (&unresolved, &ty) { - if let Some(type_alias_id) = + if let (Some(unresolved), &TypeNs::TraitId(trait_id)) = (&unresolved, &ty) + && let Some(type_alias_id) = trait_id.trait_items(db).associated_type_by_name(unresolved.name) - { - return Some(PathResolution::Def(ModuleDefId::from(type_alias_id).into())); - } + { + return Some(PathResolution::Def(ModuleDefId::from(type_alias_id).into())); } let res = match ty { @@ -1744,7 +1739,6 @@ fn resolve_hir_path_qualifier( TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()), TypeNs::BuiltinType(it) => PathResolution::Def(BuiltinType::from(it).into()), TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()), - TypeNs::TraitAliasId(it) => PathResolution::Def(TraitAlias::from(it).into()), TypeNs::ModuleId(it) => PathResolution::Def(ModuleDef::Module(it.into())), }; match unresolved { @@ -1755,7 +1749,7 @@ fn resolve_hir_path_qualifier( db, def, res.in_type_ns()?, - |name, id| (name == unresolved.name).then_some(id), + |name, _| name == unresolved.name, ) }) .map(TypeAlias::from) |