Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/infer.rs')
-rw-r--r--crates/hir-ty/src/infer.rs108
1 files changed, 85 insertions, 23 deletions
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index 88334b492d..3685ed5696 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -33,7 +33,7 @@ use chalk_ir::{
};
use either::Either;
use hir_def::{
- body::Body,
+ body::{Body, HygieneId},
builtin_type::{BuiltinInt, BuiltinType, BuiltinUint},
data::{ConstData, StaticData},
hir::{BindingAnnotation, BindingId, ExprId, ExprOrPatId, LabelId, PatId},
@@ -41,7 +41,7 @@ use hir_def::{
layout::Integer,
path::{ModPath, Path},
resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs},
- type_ref::{LifetimeRef, TypeRef},
+ type_ref::{LifetimeRef, TypeRefId, TypesMap},
AdtId, AssocItemId, DefWithBodyId, FieldId, FunctionId, ImplId, ItemContainerId, Lookup,
TraitId, TupleFieldId, TupleId, TypeAliasId, VariantId,
};
@@ -228,7 +228,7 @@ pub enum InferenceDiagnostic {
id: ExprOrPatId,
},
UnresolvedIdent {
- expr: ExprId,
+ id: ExprOrPatId,
},
// FIXME: This should be emitted in body lowering
BreakOutsideOfLoop {
@@ -482,12 +482,27 @@ impl InferenceResult {
pub fn variant_resolution_for_pat(&self, id: PatId) -> Option<VariantId> {
self.variant_resolutions.get(&id.into()).copied()
}
+ pub fn variant_resolution_for_expr_or_pat(&self, id: ExprOrPatId) -> Option<VariantId> {
+ match id {
+ ExprOrPatId::ExprId(id) => self.variant_resolution_for_expr(id),
+ ExprOrPatId::PatId(id) => self.variant_resolution_for_pat(id),
+ }
+ }
pub fn assoc_resolutions_for_expr(&self, id: ExprId) -> Option<(AssocItemId, Substitution)> {
self.assoc_resolutions.get(&id.into()).cloned()
}
pub fn assoc_resolutions_for_pat(&self, id: PatId) -> Option<(AssocItemId, Substitution)> {
self.assoc_resolutions.get(&id.into()).cloned()
}
+ pub fn assoc_resolutions_for_expr_or_pat(
+ &self,
+ id: ExprOrPatId,
+ ) -> Option<(AssocItemId, Substitution)> {
+ match id {
+ ExprOrPatId::ExprId(id) => self.assoc_resolutions_for_expr(id),
+ ExprOrPatId::PatId(id) => self.assoc_resolutions_for_pat(id),
+ }
+ }
pub fn type_mismatch_for_expr(&self, expr: ExprId) -> Option<&TypeMismatch> {
self.type_mismatches.get(&expr.into())
}
@@ -506,6 +521,12 @@ impl InferenceResult {
pub fn closure_info(&self, closure: &ClosureId) -> &(Vec<CapturedItem>, FnTrait) {
self.closure_info.get(closure).unwrap()
}
+ pub fn type_of_expr_or_pat(&self, id: ExprOrPatId) -> Option<&Ty> {
+ match id {
+ ExprOrPatId::ExprId(id) => self.type_of_expr.get(id),
+ ExprOrPatId::PatId(id) => self.type_of_pat.get(id),
+ }
+ }
}
impl Index<ExprId> for InferenceResult {
@@ -524,6 +545,14 @@ impl Index<PatId> for InferenceResult {
}
}
+impl Index<ExprOrPatId> for InferenceResult {
+ type Output = Ty;
+
+ fn index(&self, id: ExprOrPatId) -> &Ty {
+ self.type_of_expr_or_pat(id).unwrap_or(&self.standard_types.unknown)
+ }
+}
+
impl Index<BindingId> for InferenceResult {
type Output = Ty;
@@ -561,6 +590,9 @@ pub(crate) struct InferenceContext<'a> {
diverges: Diverges,
breakables: Vec<BreakableContext>,
+ /// Whether we are inside the pattern of a destructuring assignment.
+ inside_assignment: bool,
+
deferred_cast_checks: Vec<CastCheck>,
// fields related to closure capture
@@ -656,6 +688,7 @@ impl<'a> InferenceContext<'a> {
current_closure: None,
deferred_closures: FxHashMap::default(),
closure_dependencies: FxHashMap::default(),
+ inside_assignment: false,
}
}
@@ -825,7 +858,7 @@ impl<'a> InferenceContext<'a> {
}
fn collect_const(&mut self, data: &ConstData) {
- let return_ty = self.make_ty(&data.type_ref);
+ let return_ty = self.make_ty(data.type_ref, &data.types_map);
// Constants might be defining usage sites of TAITs.
self.make_tait_coercion_table(iter::once(&return_ty));
@@ -834,7 +867,7 @@ impl<'a> InferenceContext<'a> {
}
fn collect_static(&mut self, data: &StaticData) {
- let return_ty = self.make_ty(&data.type_ref);
+ let return_ty = self.make_ty(data.type_ref, &data.types_map);
// Statics might be defining usage sites of TAITs.
self.make_tait_coercion_table(iter::once(&return_ty));
@@ -844,11 +877,11 @@ impl<'a> InferenceContext<'a> {
fn collect_fn(&mut self, func: FunctionId) {
let data = self.db.function_data(func);
- let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver, self.owner.into())
- .with_type_param_mode(ParamLoweringMode::Placeholder)
- .with_impl_trait_mode(ImplTraitLoweringMode::Param);
- let mut param_tys =
- data.params.iter().map(|type_ref| ctx.lower_ty(type_ref)).collect::<Vec<_>>();
+ let mut param_tys = self.with_ty_lowering(&data.types_map, |ctx| {
+ ctx.type_param_mode(ParamLoweringMode::Placeholder)
+ .impl_trait_mode(ImplTraitLoweringMode::Param);
+ data.params.iter().map(|&type_ref| ctx.lower_ty(type_ref)).collect::<Vec<_>>()
+ });
// Check if function contains a va_list, if it does then we append it to the parameter types
// that are collected from the function data
if data.is_varargs() {
@@ -883,12 +916,13 @@ impl<'a> InferenceContext<'a> {
tait_candidates.insert(ty);
}
}
- let return_ty = &*data.ret_type;
+ let return_ty = data.ret_type;
- let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver, self.owner.into())
- .with_type_param_mode(ParamLoweringMode::Placeholder)
- .with_impl_trait_mode(ImplTraitLoweringMode::Opaque);
- let return_ty = ctx.lower_ty(return_ty);
+ let return_ty = self.with_ty_lowering(&data.types_map, |ctx| {
+ ctx.type_param_mode(ParamLoweringMode::Placeholder)
+ .impl_trait_mode(ImplTraitLoweringMode::Opaque)
+ .lower_ty(return_ty)
+ });
let return_ty = self.insert_type_vars(return_ty);
let return_ty = if let Some(rpits) = self.db.return_type_impl_traits(func) {
@@ -1022,7 +1056,7 @@ impl<'a> InferenceContext<'a> {
non_assocs: FxHashMap<OpaqueTyId, Ty>,
}
- impl<'a, 'b> TypeVisitor<Interner> for TypeAliasImplTraitCollector<'a, 'b> {
+ impl TypeVisitor<Interner> for TypeAliasImplTraitCollector<'_, '_> {
type BreakTy = ();
fn as_dyn(&mut self) -> &mut dyn TypeVisitor<Interner, BreakTy = Self::BreakTy> {
@@ -1192,20 +1226,43 @@ impl<'a> InferenceContext<'a> {
self.result.diagnostics.push(diagnostic);
}
- fn make_ty(&mut self, type_ref: &TypeRef) -> Ty {
- let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver, self.owner.into());
- let ty = ctx.lower_ty(type_ref);
+ fn with_ty_lowering<R>(
+ &self,
+ types_map: &TypesMap,
+ f: impl FnOnce(&mut crate::lower::TyLoweringContext<'_>) -> R,
+ ) -> R {
+ let mut ctx = crate::lower::TyLoweringContext::new(
+ self.db,
+ &self.resolver,
+ types_map,
+ self.owner.into(),
+ );
+ f(&mut ctx)
+ }
+
+ fn with_body_ty_lowering<R>(
+ &self,
+ f: impl FnOnce(&mut crate::lower::TyLoweringContext<'_>) -> R,
+ ) -> R {
+ self.with_ty_lowering(&self.body.types, f)
+ }
+
+ fn make_ty(&mut self, type_ref: TypeRefId, types_map: &TypesMap) -> Ty {
+ let ty = self.with_ty_lowering(types_map, |ctx| ctx.lower_ty(type_ref));
let ty = self.insert_type_vars(ty);
self.normalize_associated_types_in(ty)
}
+ fn make_body_ty(&mut self, type_ref: TypeRefId) -> Ty {
+ self.make_ty(type_ref, &self.body.types)
+ }
+
fn err_ty(&self) -> Ty {
self.result.standard_types.unknown.clone()
}
fn make_lifetime(&mut self, lifetime_ref: &LifetimeRef) -> Lifetime {
- let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver, self.owner.into());
- let lt = ctx.lower_lifetime(lifetime_ref);
+ let lt = self.with_ty_lowering(TypesMap::EMPTY, |ctx| ctx.lower_lifetime(lifetime_ref));
self.insert_type_vars(lt)
}
@@ -1363,9 +1420,14 @@ impl<'a> InferenceContext<'a> {
Some(path) => path,
None => return (self.err_ty(), None),
};
- let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver, self.owner.into());
+ let ctx = crate::lower::TyLoweringContext::new(
+ self.db,
+ &self.resolver,
+ &self.body.types,
+ self.owner.into(),
+ );
let (resolution, unresolved) = if value_ns {
- match self.resolver.resolve_path_in_value_ns(self.db.upcast(), path) {
+ match self.resolver.resolve_path_in_value_ns(self.db.upcast(), path, HygieneId::ROOT) {
Some(ResolveValueResult::ValueNs(value, _)) => match value {
ValueNs::EnumVariantId(var) => {
let substs = ctx.substs_from_path(path, var.into(), true);