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 | 290 |
1 files changed, 164 insertions, 126 deletions
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index f994ed26ca..bf123e13f9 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -18,10 +18,10 @@ use hir_def::{ scope::{ExprScopes, ScopeId}, }, hir::{BindingId, Expr, ExprId, ExprOrPatId, Pat}, - lang_item::LangItem, + lang_item::LangItems, nameres::MacroSubNs, resolver::{HasResolver, Resolver, TypeNs, ValueNs, resolver_for_scope}, - type_ref::{Mutability, TypeRefId}, + type_ref::{Mutability, TypeRef, TypeRefId}, }; use hir_expand::{ HirFileId, InFile, @@ -29,15 +29,16 @@ use hir_expand::{ name::{AsName, Name}, }; use hir_ty::{ - Adjustment, InferenceResult, LifetimeElisionKind, TraitEnvironment, TyLoweringContext, + Adjustment, InferenceResult, LifetimeElisionKind, ParamEnvAndCrate, TyLoweringContext, diagnostics::{ InsideUnsafeBlock, record_literal_missing_fields, record_pattern_missing_fields, unsafe_operations, }, lang_items::lang_items_for_bin_op, - method_resolution, + method_resolution::{self, CandidateId}, next_solver::{ - DbInterner, ErrorGuaranteed, GenericArgs, Ty, TyKind, TypingMode, infer::DbInternerInferExt, + DbInterner, ErrorGuaranteed, GenericArgs, ParamEnv, Ty, TyKind, TypingMode, + infer::DbInternerInferExt, }, traits::structurally_normalize_ty, }; @@ -56,9 +57,9 @@ 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, + Adt, AnyFunctionId, 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}, }; @@ -78,7 +79,7 @@ pub(crate) enum BodyOrSig<'db> { def: DefWithBodyId, body: Arc<Body>, source_map: Arc<BodySourceMap>, - infer: Option<Arc<InferenceResult<'db>>>, + infer: Option<&'db InferenceResult>, }, // To be folded into body once it is considered one VariantFields { @@ -101,7 +102,7 @@ impl<'db> SourceAnalyzer<'db> { node: InFile<&SyntaxNode>, offset: Option<TextSize>, ) -> SourceAnalyzer<'db> { - Self::new_for_body_(db, def, node, offset, Some(db.infer(def))) + Self::new_for_body_(db, def, node, offset, Some(InferenceResult::for_body(db, def))) } pub(crate) fn new_for_body_no_infer( @@ -118,7 +119,7 @@ impl<'db> SourceAnalyzer<'db> { def: DefWithBodyId, node @ InFile { file_id, .. }: InFile<&SyntaxNode>, offset: Option<TextSize>, - infer: Option<Arc<InferenceResult<'db>>>, + infer: Option<&'db InferenceResult>, ) -> SourceAnalyzer<'db> { let (body, source_map) = db.body_with_source_map(def); let scopes = db.expr_scopes(def); @@ -184,9 +185,7 @@ impl<'db> SourceAnalyzer<'db> { } // FIXME: Remove this - fn body_( - &self, - ) -> Option<(DefWithBodyId, &Body, &BodySourceMap, Option<&InferenceResult<'db>>)> { + fn body_(&self) -> Option<(DefWithBodyId, &Body, &BodySourceMap, Option<&InferenceResult>)> { 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())) @@ -195,7 +194,7 @@ impl<'db> SourceAnalyzer<'db> { }) } - fn infer(&self) -> Option<&InferenceResult<'db>> { + fn infer(&self) -> Option<&InferenceResult> { self.body_or_sig.as_ref().and_then(|it| match it { BodyOrSig::Sig { .. } => None, BodyOrSig::VariantFields { .. } => None, @@ -227,14 +226,19 @@ impl<'db> SourceAnalyzer<'db> { }) } - 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), + fn param_and<'a>(&self, param_env: ParamEnv<'a>) -> ParamEnvAndCrate<'a> { + ParamEnvAndCrate { param_env, krate: self.resolver.krate() } + } + + fn trait_environment(&self, db: &'db dyn HirDatabase) -> ParamEnvAndCrate<'db> { + self.param_and( + self.body_() + .map(|(def, ..)| def) + .map_or_else(ParamEnv::empty, |def| db.trait_environment_for_body(def)), ) } - fn expr_id(&self, expr: ast::Expr) -> Option<ExprOrPatId> { + pub(crate) fn expr_id(&self, expr: ast::Expr) -> Option<ExprOrPatId> { let src = InFile { file_id: self.file_id, value: expr }; self.store_sm()?.node_expr(src.as_ref()) } @@ -254,7 +258,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<'db>]> { + pub(crate) fn expr_adjustments(&self, expr: &ast::Expr) -> Option<&[Adjustment]> { // 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()?; @@ -267,8 +271,11 @@ impl<'db> SourceAnalyzer<'db> { db: &'db dyn HirDatabase, ty: &ast::Type, ) -> Option<Type<'db>> { + let interner = DbInterner::new_no_crate(db); + let type_ref = self.type_id(ty)?; - let ty = TyLoweringContext::new( + + let mut ty = TyLoweringContext::new( db, &self.resolver, self.store()?, @@ -279,6 +286,31 @@ impl<'db> SourceAnalyzer<'db> { LifetimeElisionKind::Infer, ) .lower_ty(type_ref); + + // Try and substitute unknown types using InferenceResult + if let Some(infer) = self.infer() + && let Some(store) = self.store() + { + let mut inferred_types = vec![]; + TypeRef::walk(type_ref, store, &mut |type_ref_id, type_ref| { + if matches!(type_ref, TypeRef::Placeholder) { + inferred_types.push(infer.type_of_type_placeholder(type_ref_id)); + } + }); + let mut inferred_types = inferred_types.into_iter(); + + let substituted_ty = hir_ty::next_solver::fold::fold_tys(interner, ty, |ty| { + if ty.is_ty_error() { inferred_types.next().flatten().unwrap_or(ty) } else { ty } + }); + + // Only used the result if the placeholder and unknown type counts matched + let success = + inferred_types.next().is_none() && !substituted_ty.references_non_lt_error(); + if success { + ty = substituted_ty; + } + } + Some(Type::new_with_resolver(db, &self.resolver, ty)) } @@ -292,8 +324,8 @@ 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)); - let ty = infer[expr_id]; + .and_then(|adjusts| adjusts.last().map(|adjust| adjust.target.as_ref())); + let ty = infer.expr_or_pat_ty(expr_id); let mk_ty = |ty: Ty<'db>| Type::new_with_resolver(db, &self.resolver, ty); Some((mk_ty(ty), coerced.map(mk_ty))) } @@ -308,14 +340,15 @@ impl<'db> SourceAnalyzer<'db> { let coerced = match expr_or_pat_id { ExprOrPatId::ExprId(idx) => infer .expr_adjustment(idx) - .and_then(|adjusts| adjusts.last().cloned()) - .map(|adjust| adjust.target), - ExprOrPatId::PatId(idx) => { - infer.pat_adjustment(idx).and_then(|adjusts| adjusts.last().cloned()) - } + .and_then(|adjusts| adjusts.last()) + .map(|adjust| adjust.target.as_ref()), + ExprOrPatId::PatId(idx) => infer + .pat_adjustment(idx) + .and_then(|adjusts| adjusts.last()) + .map(|adjust| adjust.as_ref()), }; - let ty = infer[expr_or_pat_id]; + let ty = infer.expr_or_pat_ty(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))) } @@ -327,7 +360,7 @@ 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]; + let ty = infer.binding_ty(binding_id); let mk_ty = |ty: Ty<'db>| Type::new_with_resolver(db, &self.resolver, ty); Some(mk_ty(ty)) } @@ -338,7 +371,7 @@ impl<'db> SourceAnalyzer<'db> { _param: &ast::SelfParam, ) -> Option<Type<'db>> { let binding = self.body()?.self_param?; - let ty = self.infer()?[binding]; + let ty = self.infer()?.binding_ty(binding); Some(Type::new_with_resolver(db, &self.resolver, ty)) } @@ -370,7 +403,7 @@ impl<'db> SourceAnalyzer<'db> { infer .pat_adjustment(pat_id.as_pat()?)? .iter() - .map(|ty| Type::new_with_resolver(db, &self.resolver, *ty)) + .map(|ty| Type::new_with_resolver(db, &self.resolver, ty.as_ref())) .collect(), ) } @@ -382,7 +415,7 @@ impl<'db> SourceAnalyzer<'db> { ) -> Option<Callable<'db>> { let expr_id = self.expr_id(call.clone().into())?.as_expr()?; let (func, args) = self.infer()?.method_resolution(expr_id)?; - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); 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)?; @@ -398,7 +431,7 @@ impl<'db> SourceAnalyzer<'db> { let expr_id = self.expr_id(call.clone().into())?.as_expr()?; let (f_in_trait, substs) = self.infer()?.method_resolution(expr_id)?; - Some(self.resolve_impl_method_or_trait_def(db, f_in_trait, substs).into()) + Some(self.resolve_impl_method_or_trait_def(db, f_in_trait, substs)) } pub(crate) fn resolve_method_call_fallback( @@ -413,8 +446,8 @@ impl<'db> SourceAnalyzer<'db> { let (fn_, subst) = self.resolve_impl_method_or_trait_def_with_subst(db, f_in_trait, substs); Some(( - Either::Left(fn_.into()), - Some(GenericSubstitution::new(fn_.into(), subst, self.trait_environment(db))), + Either::Left(fn_), + GenericSubstitution::new_from_fn(fn_, subst, self.trait_environment(db)), )) } None => { @@ -448,7 +481,7 @@ impl<'db> SourceAnalyzer<'db> { fn field_subst( &self, field_expr: ExprId, - infer: &InferenceResult<'db>, + infer: &InferenceResult, db: &'db dyn HirDatabase, ) -> Option<GenericSubstitution<'db>> { let body = self.store()?; @@ -486,8 +519,8 @@ impl<'db> SourceAnalyzer<'db> { None => inference_result.method_resolution(expr_id).map(|(f, substs)| { let (f, subst) = self.resolve_impl_method_or_trait_def_with_subst(db, f, substs); ( - Either::Right(f.into()), - Some(GenericSubstitution::new(f.into(), subst, self.trait_environment(db))), + Either::Right(f), + GenericSubstitution::new_from_fn(f, subst, self.trait_environment(db)), ) }), } @@ -536,7 +569,7 @@ impl<'db> SourceAnalyzer<'db> { &self, db: &'db dyn HirDatabase, await_expr: &ast::AwaitExpr, - ) -> Option<FunctionId> { + ) -> Option<Function> { let mut ty = self.ty_of_expr(await_expr.expr()?)?; let into_future_trait = self @@ -561,11 +594,10 @@ impl<'db> SourceAnalyzer<'db> { } } - let poll_fn = LangItem::FuturePoll.resolve_function(db, self.resolver.krate())?; + let poll_fn = self.lang_items(db).FuturePoll?; // 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 interner = DbInterner::new_with(db, None, None); - let substs = GenericArgs::new_from_iter(interner, [ty.into()]); + let substs = GenericArgs::new_from_slice(&[ty.into()]); Some(self.resolve_impl_method_or_trait_def(db, poll_fn, substs)) } @@ -573,21 +605,24 @@ impl<'db> SourceAnalyzer<'db> { &self, db: &'db dyn HirDatabase, prefix_expr: &ast::PrefixExpr, - ) -> Option<FunctionId> { + ) -> Option<Function> { 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`, // use that result to find out which one it is. - let (deref_trait, deref) = - self.lang_trait_fn(db, LangItem::Deref, &Name::new_symbol_root(sym::deref))?; + let (deref_trait, deref) = self.lang_trait_fn( + db, + self.lang_items(db).Deref, + &Name::new_symbol_root(sym::deref), + )?; self.infer() .and_then(|infer| { let expr = self.expr_id(prefix_expr.clone().into())?.as_expr()?; let (func, _) = infer.method_resolution(expr)?; let (deref_mut_trait, deref_mut) = self.lang_trait_fn( db, - LangItem::DerefMut, + self.lang_items(db).DerefMut, &Name::new_symbol_root(sym::deref_mut), )?; if func == deref_mut { Some((deref_mut_trait, deref_mut)) } else { None } @@ -595,19 +630,18 @@ impl<'db> SourceAnalyzer<'db> { .unwrap_or((deref_trait, deref)) } ast::UnaryOp::Not => { - self.lang_trait_fn(db, LangItem::Not, &Name::new_symbol_root(sym::not))? + self.lang_trait_fn(db, self.lang_items(db).Not, &Name::new_symbol_root(sym::not))? } ast::UnaryOp::Neg => { - self.lang_trait_fn(db, LangItem::Neg, &Name::new_symbol_root(sym::neg))? + self.lang_trait_fn(db, self.lang_items(db).Neg, &Name::new_symbol_root(sym::neg))? } }; 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 = GenericArgs::new_from_iter(interner, [ty.into()]); + let substs = GenericArgs::new_from_slice(&[ty.into()]); Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs)) } @@ -616,12 +650,12 @@ impl<'db> SourceAnalyzer<'db> { &self, db: &'db dyn HirDatabase, index_expr: &ast::IndexExpr, - ) -> Option<FunctionId> { + ) -> Option<Function> { 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) = - self.lang_trait_fn(db, LangItem::Index, &Name::new_symbol_root(sym::index))?; + self.lang_trait_fn(db, self.lang_items(db).Index, &Name::new_symbol_root(sym::index))?; let op_fn = self .infer() .and_then(|infer| { @@ -629,7 +663,7 @@ impl<'db> SourceAnalyzer<'db> { let (func, _) = infer.method_resolution(expr)?; let (_index_mut_trait, index_mut_fn) = self.lang_trait_fn( db, - LangItem::IndexMut, + self.lang_items(db).IndexMut, &Name::new_symbol_root(sym::index_mut), )?; if func == index_mut_fn { Some(index_mut_fn) } else { None } @@ -637,8 +671,7 @@ impl<'db> SourceAnalyzer<'db> { .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 interner = DbInterner::new_with(db, None, None); - let substs = GenericArgs::new_from_iter(interner, [base_ty.into(), index_ty.into()]); + let substs = GenericArgs::new_from_slice(&[base_ty.into(), index_ty.into()]); Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs)) } @@ -646,17 +679,18 @@ impl<'db> SourceAnalyzer<'db> { &self, db: &'db dyn HirDatabase, binop_expr: &ast::BinExpr, - ) -> Option<FunctionId> { + ) -> Option<Function> { let op = binop_expr.op_kind()?; 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) - .and_then(|(name, lang_item)| self.lang_trait_fn(db, lang_item, &name))?; + let (_op_trait, op_fn) = + lang_items_for_bin_op(self.lang_items(db), op).and_then(|(name, lang_item)| { + self.lang_trait_fn(db, lang_item, &Name::new_symbol_root(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 interner = DbInterner::new_with(db, None, None); - let substs = GenericArgs::new_from_iter(interner, [lhs.into(), rhs.into()]); + let substs = GenericArgs::new_from_slice(&[lhs.into(), rhs.into()]); Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs)) } @@ -665,14 +699,13 @@ impl<'db> SourceAnalyzer<'db> { &self, db: &'db dyn HirDatabase, try_expr: &ast::TryExpr, - ) -> Option<FunctionId> { + ) -> Option<Function> { let ty = self.ty_of_expr(try_expr.expr()?)?; - let op_fn = LangItem::TryTraitBranch.resolve_function(db, self.resolver.krate())?; + let op_fn = self.lang_items(db).TryTraitBranch?; // 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 interner = DbInterner::new_with(db, None, None); - let substs = GenericArgs::new_from_iter(interner, [ty.into()]); + let substs = GenericArgs::new_from_slice(&[ty.into()]); Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs)) } @@ -685,7 +718,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 interner = DbInterner::new_no_crate(db); let ast_name = field.field_name()?; let local_name = ast_name.as_name(); @@ -712,7 +745,8 @@ 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)?).instantiate(interner, subst); + let field_ty = + (*db.field_types(variant).get(field.local_id)?).get().instantiate(interner, subst); Some(( field.into(), local, @@ -726,15 +760,16 @@ 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 interner = DbInterner::new_no_crate(db); 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())?; let variant = self.infer()?.variant_resolution_for_pat(pat_id.as_pat()?)?; 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)?).instantiate(interner, subst); + let (adt, subst) = self.infer()?.pat_ty(pat_id.as_pat()?).as_adt()?; + let field_ty = + (*db.field_types(variant).get(field.local_id)?).get().instantiate(interner, subst); Some(( field.into(), Type::new_with_resolver(db, &self.resolver, field_ty), @@ -788,31 +823,32 @@ impl<'db> SourceAnalyzer<'db> { let trait_env = container.env; - let interner = DbInterner::new_with(db, Some(trait_env.krate), trait_env.block); + let interner = DbInterner::new_with(db, trait_env.krate); 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 Either::Right(container) = &mut container { - *container = structurally_normalize_ty(&infcx, *container, trait_env.clone()); + *container = structurally_normalize_ty(&infcx, *container, trait_env.param_env); } - 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, - )) + 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].get().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, + )) + }; let temp_ty = Ty::new_error(interner, ErrorGuaranteed); let (field_def, generic_def, subst) = match std::mem::replace(&mut container, Either::Right(temp_ty)) { @@ -861,7 +897,7 @@ impl<'db> SourceAnalyzer<'db> { let expr_id = self.expr_id(path_expr.into())?; if let Some((assoc, subs)) = infer.assoc_resolutions_for_expr_or_pat(expr_id) { let (assoc, subst) = match assoc { - AssocItemId::FunctionId(f_in_trait) => { + CandidateId::FunctionId(f_in_trait) => { match infer.type_of_expr_or_pat(expr_id) { None => { let subst = GenericSubstitution::new( @@ -869,7 +905,7 @@ impl<'db> SourceAnalyzer<'db> { subs, self.trait_environment(db), ); - (assoc, subst) + (AssocItem::Function(f_in_trait.into()), Some(subst)) } Some(func_ty) => { if let TyKind::FnDef(_fn_def, subs) = func_ty.kind() { @@ -877,24 +913,24 @@ impl<'db> SourceAnalyzer<'db> { .resolve_impl_method_or_trait_def_with_subst( db, f_in_trait, subs, ); - let subst = GenericSubstitution::new( - fn_.into(), + let subst = GenericSubstitution::new_from_fn( + fn_, subst, self.trait_environment(db), ); - (fn_.into(), subst) + (AssocItem::Function(fn_), subst) } else { let subst = GenericSubstitution::new( f_in_trait.into(), subs, self.trait_environment(db), ); - (assoc, subst) + (AssocItem::Function(f_in_trait.into()), Some(subst)) } } } } - AssocItemId::ConstId(const_id) => { + CandidateId::ConstId(const_id) => { let (konst, subst) = self.resolve_impl_const_or_trait_def_with_subst(db, const_id, subs); let subst = GenericSubstitution::new( @@ -902,19 +938,11 @@ impl<'db> SourceAnalyzer<'db> { subst, self.trait_environment(db), ); - (konst.into(), subst) + (AssocItem::Const(konst.into()), Some(subst)) } - AssocItemId::TypeAliasId(type_alias) => ( - assoc, - GenericSubstitution::new( - type_alias.into(), - subs, - self.trait_environment(db), - ), - ), }; - return Some((PathResolution::Def(AssocItem::from(assoc).into()), Some(subst))); + return Some((PathResolution::Def(assoc.into()), subst)); } if let Some(VariantId::EnumVariantId(variant)) = infer.variant_resolution_for_expr_or_pat(expr_id) @@ -927,7 +955,7 @@ impl<'db> SourceAnalyzer<'db> { if let Some((assoc, subs)) = infer.assoc_resolutions_for_expr_or_pat(expr_or_pat_id) { let (assoc, subst) = match assoc { - AssocItemId::ConstId(const_id) => { + CandidateId::ConstId(const_id) => { let (konst, subst) = self.resolve_impl_const_or_trait_def_with_subst(db, const_id, subs); let subst = GenericSubstitution::new( @@ -935,12 +963,12 @@ impl<'db> SourceAnalyzer<'db> { subst, self.trait_environment(db), ); - (konst.into(), subst) + (AssocItemId::from(konst), subst) } - assoc => ( - assoc, + CandidateId::FunctionId(function_id) => ( + function_id.into(), GenericSubstitution::new( - assoc.into(), + function_id.into(), subs, self.trait_environment(db), ), @@ -1142,7 +1170,7 @@ 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()?.expr_or_pat_ty(pat_id) } else { return None; }; @@ -1214,7 +1242,7 @@ impl<'db> SourceAnalyzer<'db> { let infer = self.infer()?; let expr_id = self.expr_id(literal.clone().into())?; - let substs = infer[expr_id].as_adt()?.1; + let substs = infer.expr_or_pat_ty(expr_id).as_adt()?.1; let (variant, missing_fields, _exhaustive) = match expr_id { ExprOrPatId::ExprId(expr_id) => { @@ -1237,7 +1265,7 @@ impl<'db> SourceAnalyzer<'db> { let infer = self.infer()?; let pat_id = self.pat_id(&pattern.clone().into())?.as_pat()?; - let substs = infer[pat_id].as_adt()?.1; + let substs = infer.pat_ty(pat_id).as_adt()?.1; let (variant, missing_fields, _exhaustive) = record_pattern_missing_fields(db, infer, pat_id, &body[pat_id])?; @@ -1252,14 +1280,14 @@ impl<'db> SourceAnalyzer<'db> { variant: VariantId, missing_fields: Vec<LocalFieldId>, ) -> Vec<(Field, Type<'db>)> { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); 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].instantiate(interner, substs); + let ty = field_types[local_id].get().instantiate(interner, substs); (field.into(), Type::new_with_resolver_inner(db, &self.resolver, ty)) }) .collect() @@ -1373,7 +1401,7 @@ impl<'db> SourceAnalyzer<'db> { db: &'db dyn HirDatabase, func: FunctionId, substs: GenericArgs<'db>, - ) -> FunctionId { + ) -> Function { self.resolve_impl_method_or_trait_def_with_subst(db, func, substs).0 } @@ -1382,13 +1410,19 @@ impl<'db> SourceAnalyzer<'db> { db: &'db dyn HirDatabase, func: FunctionId, substs: GenericArgs<'db>, - ) -> (FunctionId, GenericArgs<'db>) { + ) -> (Function, GenericArgs<'db>) { let owner = match self.resolver.body_owner() { Some(it) => it, - None => return (func, substs), + None => return (func.into(), substs), }; - let env = db.trait_environment_for_body(owner); - db.lookup_impl_method(env, func, substs) + let env = self.param_and(db.trait_environment_for_body(owner)); + let (func, args) = db.lookup_impl_method(env, func, substs); + match func { + Either::Left(func) => (func.into(), args), + Either::Right((impl_, method)) => { + (Function { id: AnyFunctionId::BuiltinDeriveImplMethod { method, impl_ } }, args) + } + } } fn resolve_impl_const_or_trait_def_with_subst( @@ -1401,19 +1435,23 @@ impl<'db> SourceAnalyzer<'db> { Some(it) => it, None => return (const_id, subs), }; - let env = db.trait_environment_for_body(owner); - let interner = DbInterner::new_with(db, Some(env.krate), env.block); + let env = self.param_and(db.trait_environment_for_body(owner)); + let interner = DbInterner::new_with(db, env.krate); let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis); - method_resolution::lookup_impl_const(&infcx, env, const_id, subs) + method_resolution::lookup_impl_const(&infcx, env.param_env, const_id, subs) + } + + fn lang_items<'a>(&self, db: &'a dyn HirDatabase) -> &'a LangItems { + hir_def::lang_item::lang_items(db, self.resolver.krate()) } fn lang_trait_fn( &self, db: &'db dyn HirDatabase, - lang_trait: LangItem, + lang_trait: Option<TraitId>, method_name: &Name, ) -> Option<(TraitId, FunctionId)> { - let trait_id = lang_trait.resolve_trait(db, self.resolver.krate())?; + let trait_id = lang_trait?; let fn_id = trait_id.trait_items(db).method_by_name(method_name)?; Some((trait_id, fn_id)) } |