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.rs290
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))
}