From 6c32bbf3ca5980fb33c1ea28dd1c5a1524ce81cb Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 13 Mar 2021 14:44:51 +0100 Subject: Separate `Ty` and `TyKind` like in Chalk Currently `Ty` just wraps `TyKind`, but this allows us to change most places to already use `intern` / `interned`. --- crates/hir_ty/src/infer/coerce.rs | 38 +++--- crates/hir_ty/src/infer/expr.rs | 235 +++++++++++++++++++++----------------- crates/hir_ty/src/infer/pat.rs | 41 +++---- crates/hir_ty/src/infer/path.rs | 6 +- crates/hir_ty/src/infer/unify.rs | 105 ++++++++++------- 5 files changed, 239 insertions(+), 186 deletions(-) (limited to 'crates/hir_ty/src/infer') diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs index 7e8846f27..36670043a 100644 --- a/crates/hir_ty/src/infer/coerce.rs +++ b/crates/hir_ty/src/infer/coerce.rs @@ -7,7 +7,7 @@ use chalk_ir::{Mutability, TyVariableKind}; use hir_def::lang_item::LangItemTarget; -use crate::{autoderef, traits::Solution, Obligation, Substs, TraitRef, Ty}; +use crate::{autoderef, traits::Solution, Interner, Obligation, Substs, TraitRef, Ty, TyKind}; use super::{InEnvironment, InferenceContext}; @@ -33,7 +33,9 @@ impl<'a> InferenceContext<'a> { } else if self.coerce(ty2, ty1) { ty1.clone() } else { - if let (Ty::FnDef(..), Ty::FnDef(..)) = (ty1, ty2) { + if let (TyKind::FnDef(..), TyKind::FnDef(..)) = + (ty1.interned(&Interner), ty2.interned(&Interner)) + { cov_mark::hit!(coerce_fn_reification); // Special case: two function types. Try to coerce both to // pointers to have a chance at getting a match. See @@ -51,13 +53,13 @@ impl<'a> InferenceContext<'a> { } fn coerce_inner(&mut self, mut from_ty: Ty, to_ty: &Ty) -> bool { - match (&from_ty, to_ty) { + match (from_ty.interned(&Interner), to_ty.interned(&Interner)) { // Never type will make type variable to fallback to Never Type instead of Unknown. - (Ty::Never, Ty::InferenceVar(tv, TyVariableKind::General)) => { + (TyKind::Never, TyKind::InferenceVar(tv, TyVariableKind::General)) => { self.table.type_variable_table.set_diverging(*tv, true); return true; } - (Ty::Never, _) => return true, + (TyKind::Never, _) => return true, // Trivial cases, this should go after `never` check to // avoid infer result type to be never @@ -69,33 +71,33 @@ impl<'a> InferenceContext<'a> { } // Pointer weakening and function to pointer - match (&mut from_ty, to_ty) { + match (&mut from_ty.0, to_ty.interned(&Interner)) { // `*mut T` -> `*const T` // `&mut T` -> `&T` - (Ty::Raw(m1, ..), Ty::Raw(m2 @ Mutability::Not, ..)) - | (Ty::Ref(m1, ..), Ty::Ref(m2 @ Mutability::Not, ..)) => { + (TyKind::Raw(m1, ..), TyKind::Raw(m2 @ Mutability::Not, ..)) + | (TyKind::Ref(m1, ..), TyKind::Ref(m2 @ Mutability::Not, ..)) => { *m1 = *m2; } // `&T` -> `*const T` // `&mut T` -> `*mut T`/`*const T` - (Ty::Ref(.., substs), &Ty::Raw(m2 @ Mutability::Not, ..)) - | (Ty::Ref(Mutability::Mut, substs), &Ty::Raw(m2, ..)) => { - from_ty = Ty::Raw(m2, substs.clone()); + (TyKind::Ref(.., substs), &TyKind::Raw(m2 @ Mutability::Not, ..)) + | (TyKind::Ref(Mutability::Mut, substs), &TyKind::Raw(m2, ..)) => { + from_ty = TyKind::Raw(m2, substs.clone()).intern(&Interner); } // Illegal mutability conversion - (Ty::Raw(Mutability::Not, ..), Ty::Raw(Mutability::Mut, ..)) - | (Ty::Ref(Mutability::Not, ..), Ty::Ref(Mutability::Mut, ..)) => return false, + (TyKind::Raw(Mutability::Not, ..), TyKind::Raw(Mutability::Mut, ..)) + | (TyKind::Ref(Mutability::Not, ..), TyKind::Ref(Mutability::Mut, ..)) => return false, // `{function_type}` -> `fn()` - (Ty::FnDef(..), Ty::Function { .. }) => match from_ty.callable_sig(self.db) { + (TyKind::FnDef(..), TyKind::Function { .. }) => match from_ty.callable_sig(self.db) { None => return false, Some(sig) => { from_ty = Ty::fn_ptr(sig); } }, - (Ty::Closure(.., substs), Ty::Function { .. }) => { + (TyKind::Closure(.., substs), TyKind::Function { .. }) => { from_ty = substs[0].clone(); } @@ -107,9 +109,11 @@ impl<'a> InferenceContext<'a> { } // Auto Deref if cannot coerce - match (&from_ty, to_ty) { + match (from_ty.interned(&Interner), to_ty.interned(&Interner)) { // FIXME: DerefMut - (Ty::Ref(_, st1), Ty::Ref(_, st2)) => self.unify_autoderef_behind_ref(&st1[0], &st2[0]), + (TyKind::Ref(_, st1), TyKind::Ref(_, st2)) => { + self.unify_autoderef_behind_ref(&st1[0], &st2[0]) + } // Otherwise, normal unify _ => self.unify(&from_ty, to_ty), diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 262177ffb..4e77f22fd 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs @@ -20,8 +20,8 @@ use crate::{ primitive::{self, UintTy}, traits::{FnTrait, InEnvironment}, utils::{generics, variant_data, Generics}, - AdtId, Binders, CallableDefId, FnPointer, FnSig, Obligation, OpaqueTyId, Rawness, Scalar, - Substs, TraitRef, Ty, + AdtId, Binders, CallableDefId, FnPointer, FnSig, Interner, Obligation, OpaqueTyId, Rawness, + Scalar, Substs, TraitRef, Ty, TyKind, }; use super::{ @@ -57,7 +57,7 @@ impl<'a> InferenceContext<'a> { // Return actual type when type mismatch. // This is needed for diagnostic when return type mismatch. ty - } else if expected.coercion_target() == &Ty::Unknown { + } else if expected.coercion_target().is_unknown() { ty } else { expected.ty.clone() @@ -84,7 +84,7 @@ impl<'a> InferenceContext<'a> { arg_tys.push(arg); } let parameters = param_builder.build(); - let arg_ty = Ty::Tuple(num_args, parameters); + let arg_ty = TyKind::Tuple(num_args, parameters).intern(&Interner); let substs = Substs::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build(); @@ -116,10 +116,13 @@ impl<'a> InferenceContext<'a> { fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { let body = Arc::clone(&self.body); // avoid borrow checker problem let ty = match &body[tgt_expr] { - Expr::Missing => Ty::Unknown, + Expr::Missing => self.err_ty(), Expr::If { condition, then_branch, else_branch } => { // if let is desugared to match, so this is always simple if - self.infer_expr(*condition, &Expectation::has_type(Ty::Scalar(Scalar::Bool))); + self.infer_expr( + *condition, + &Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(&Interner)), + ); let condition_diverges = mem::replace(&mut self.diverges, Diverges::Maybe); let mut both_arms_diverge = Diverges::Always; @@ -167,14 +170,14 @@ impl<'a> InferenceContext<'a> { Expr::TryBlock { body } => { let _inner = self.infer_expr(*body, expected); // FIXME should be std::result::Result<{inner}, _> - Ty::Unknown + self.err_ty() } Expr::Async { body } => { // Use the first type parameter as the output type of future. // existenail type AsyncBlockImplTrait: Future let inner_ty = self.infer_expr(*body, &Expectation::none()); let opaque_ty_id = OpaqueTyId::AsyncBlockTypeImplTrait(self.owner, *body); - Ty::OpaqueType(opaque_ty_id, Substs::single(inner_ty)) + TyKind::OpaqueType(opaque_ty_id, Substs::single(inner_ty)).intern(&Interner) } Expr::Loop { body, label } => { self.breakables.push(BreakableContext { @@ -192,17 +195,20 @@ impl<'a> InferenceContext<'a> { if ctxt.may_break { ctxt.break_ty } else { - Ty::Never + TyKind::Never.intern(&Interner) } } Expr::While { condition, body, label } => { self.breakables.push(BreakableContext { may_break: false, - break_ty: Ty::Unknown, + break_ty: self.err_ty(), label: label.map(|label| self.body[label].name.clone()), }); // while let is desugared to a match loop, so this is always simple while - self.infer_expr(*condition, &Expectation::has_type(Ty::Scalar(Scalar::Bool))); + self.infer_expr( + *condition, + &Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(&Interner)), + ); self.infer_expr(*body, &Expectation::has_type(Ty::unit())); let _ctxt = self.breakables.pop().expect("breakable stack broken"); // the body may not run, so it diverging doesn't mean we diverge @@ -214,7 +220,7 @@ impl<'a> InferenceContext<'a> { self.breakables.push(BreakableContext { may_break: false, - break_ty: Ty::Unknown, + break_ty: self.err_ty(), label: label.map(|label| self.body[label].name.clone()), }); let pat_ty = @@ -249,12 +255,14 @@ impl<'a> InferenceContext<'a> { None => self.table.new_type_var(), }; sig_tys.push(ret_ty.clone()); - let sig_ty = Ty::Function(FnPointer { + let sig_ty = TyKind::Function(FnPointer { num_args: sig_tys.len() - 1, sig: FnSig { variadic: false }, substs: Substs(sig_tys.clone().into()), - }); - let closure_ty = Ty::Closure(self.owner, tgt_expr, Substs::single(sig_ty)); + }) + .intern(&Interner); + let closure_ty = + TyKind::Closure(self.owner, tgt_expr, Substs::single(sig_ty)).intern(&Interner); // Eagerly try to relate the closure type with the expected // type, otherwise we often won't have enough information to @@ -295,7 +303,7 @@ impl<'a> InferenceContext<'a> { args.len(), ) }) - .unwrap_or((Vec::new(), Ty::Unknown)); + .unwrap_or((Vec::new(), self.err_ty())); self.register_obligations_for_call(&callee_ty); self.check_call_arguments(args, ¶m_tys); self.normalize_associated_types_in(ret_ty) @@ -305,8 +313,11 @@ impl<'a> InferenceContext<'a> { Expr::Match { expr, arms } => { let input_ty = self.infer_expr(*expr, &Expectation::none()); - let mut result_ty = - if arms.is_empty() { Ty::Never } else { self.table.new_type_var() }; + let mut result_ty = if arms.is_empty() { + TyKind::Never.intern(&Interner) + } else { + self.table.new_type_var() + }; let matchee_diverges = self.diverges; let mut all_arms_diverge = Diverges::Always; @@ -317,7 +328,7 @@ impl<'a> InferenceContext<'a> { if let Some(guard_expr) = arm.guard { self.infer_expr( guard_expr, - &Expectation::has_type(Ty::Scalar(Scalar::Bool)), + &Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(&Interner)), ); } @@ -333,9 +344,9 @@ impl<'a> InferenceContext<'a> { Expr::Path(p) => { // FIXME this could be more efficient... let resolver = resolver_for_expr(self.db.upcast(), self.owner, tgt_expr); - self.infer_path(&resolver, p, tgt_expr.into()).unwrap_or(Ty::Unknown) + self.infer_path(&resolver, p, tgt_expr.into()).unwrap_or(self.err_ty()) } - Expr::Continue { .. } => Ty::Never, + Expr::Continue { .. } => TyKind::Never.intern(&Interner), Expr::Break { expr, label } => { let val_ty = if let Some(expr) = expr { self.infer_expr(*expr, &Expectation::none()) @@ -347,7 +358,7 @@ impl<'a> InferenceContext<'a> { if let Some(ctxt) = find_breakable(&mut self.breakables, label.as_ref()) { ctxt.break_ty.clone() } else { - Ty::Unknown + self.err_ty() }; let merged_type = self.coerce_merge_branch(&last_ty, &val_ty); @@ -360,7 +371,7 @@ impl<'a> InferenceContext<'a> { expr: tgt_expr, }); } - Ty::Never + TyKind::Never.intern(&Interner) } Expr::Return { expr } => { if let Some(expr) = expr { @@ -369,14 +380,14 @@ impl<'a> InferenceContext<'a> { let unit = Ty::unit(); self.coerce(&unit, &self.return_ty.clone()); } - Ty::Never + TyKind::Never.intern(&Interner) } Expr::Yield { expr } => { // FIXME: track yield type for coercion if let Some(expr) = expr { self.infer_expr(*expr, &Expectation::none()); } - Ty::Never + TyKind::Never.intern(&Interner) } Expr::RecordLit { path, fields, spread } => { let (ty, def_id) = self.resolve_variant(path.as_ref()); @@ -404,8 +415,9 @@ impl<'a> InferenceContext<'a> { if let Some(field_def) = field_def { self.result.record_field_resolutions.insert(field.expr, field_def); } - let field_ty = field_def - .map_or(Ty::Unknown, |it| field_types[it.local_id].clone().subst(&substs)); + let field_ty = field_def.map_or(self.err_ty(), |it| { + field_types[it.local_id].clone().subst(&substs) + }); self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty)); } if let Some(expr) = spread { @@ -424,27 +436,33 @@ impl<'a> InferenceContext<'a> { environment: self.trait_env.clone(), }, ) - .find_map(|derefed_ty| match canonicalized.decanonicalize_ty(derefed_ty.value) { - Ty::Tuple(_, substs) => { - name.as_tuple_index().and_then(|idx| substs.0.get(idx).cloned()) - } - Ty::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => { - self.db.struct_data(s).variant_data.field(name).map(|local_id| { - let field = FieldId { parent: s.into(), local_id }; - self.write_field_resolution(tgt_expr, field); - self.db.field_types(s.into())[field.local_id].clone().subst(¶meters) - }) - } - Ty::Adt(AdtId(hir_def::AdtId::UnionId(u)), parameters) => { - self.db.union_data(u).variant_data.field(name).map(|local_id| { - let field = FieldId { parent: u.into(), local_id }; - self.write_field_resolution(tgt_expr, field); - self.db.field_types(u.into())[field.local_id].clone().subst(¶meters) - }) + .find_map(|derefed_ty| { + match canonicalized.decanonicalize_ty(derefed_ty.value).interned(&Interner) { + TyKind::Tuple(_, substs) => { + name.as_tuple_index().and_then(|idx| substs.0.get(idx).cloned()) + } + TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => { + self.db.struct_data(*s).variant_data.field(name).map(|local_id| { + let field = FieldId { parent: (*s).into(), local_id }; + self.write_field_resolution(tgt_expr, field); + self.db.field_types((*s).into())[field.local_id] + .clone() + .subst(¶meters) + }) + } + TyKind::Adt(AdtId(hir_def::AdtId::UnionId(u)), parameters) => { + self.db.union_data(*u).variant_data.field(name).map(|local_id| { + let field = FieldId { parent: (*u).into(), local_id }; + self.write_field_resolution(tgt_expr, field); + self.db.field_types((*u).into())[field.local_id] + .clone() + .subst(¶meters) + }) + } + _ => None, } - _ => None, }) - .unwrap_or(Ty::Unknown); + .unwrap_or(self.err_ty()); let ty = self.insert_type_vars(ty); self.normalize_associated_types_in(ty) } @@ -481,9 +499,10 @@ impl<'a> InferenceContext<'a> { }; let inner_ty = self.infer_expr_inner(*expr, &expectation); match rawness { - Rawness::RawPtr => Ty::Raw(mutability, Substs::single(inner_ty)), - Rawness::Ref => Ty::Ref(mutability, Substs::single(inner_ty)), + Rawness::RawPtr => TyKind::Raw(mutability, Substs::single(inner_ty)), + Rawness::Ref => TyKind::Ref(mutability, Substs::single(inner_ty)), } + .intern(&Interner) } Expr::Box { expr } => { let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); @@ -499,7 +518,7 @@ impl<'a> InferenceContext<'a> { sb = sb.fill(repeat_with(|| self.table.new_type_var())); Ty::adt_ty(box_, sb.build()) } else { - Ty::Unknown + self.err_ty() } } Expr::UnaryOp { expr, op } => { @@ -519,31 +538,31 @@ impl<'a> InferenceContext<'a> { Some(derefed_ty) => { canonicalized.decanonicalize_ty(derefed_ty.value) } - None => Ty::Unknown, + None => self.err_ty(), } } - None => Ty::Unknown, + None => self.err_ty(), }, UnaryOp::Neg => { - match &inner_ty { + match inner_ty.interned(&Interner) { // Fast path for builtins - Ty::Scalar(Scalar::Int(_)) - | Ty::Scalar(Scalar::Uint(_)) - | Ty::Scalar(Scalar::Float(_)) - | Ty::InferenceVar(_, TyVariableKind::Integer) - | Ty::InferenceVar(_, TyVariableKind::Float) => inner_ty, + TyKind::Scalar(Scalar::Int(_)) + | TyKind::Scalar(Scalar::Uint(_)) + | TyKind::Scalar(Scalar::Float(_)) + | TyKind::InferenceVar(_, TyVariableKind::Integer) + | TyKind::InferenceVar(_, TyVariableKind::Float) => inner_ty, // Otherwise we resolve via the std::ops::Neg trait _ => self .resolve_associated_type(inner_ty, self.resolve_ops_neg_output()), } } UnaryOp::Not => { - match &inner_ty { + match inner_ty.interned(&Interner) { // Fast path for builtins - Ty::Scalar(Scalar::Bool) - | Ty::Scalar(Scalar::Int(_)) - | Ty::Scalar(Scalar::Uint(_)) - | Ty::InferenceVar(_, TyVariableKind::Integer) => inner_ty, + TyKind::Scalar(Scalar::Bool) + | TyKind::Scalar(Scalar::Int(_)) + | TyKind::Scalar(Scalar::Uint(_)) + | TyKind::InferenceVar(_, TyVariableKind::Integer) => inner_ty, // Otherwise we resolve via the std::ops::Not trait _ => self .resolve_associated_type(inner_ty, self.resolve_ops_not_output()), @@ -554,7 +573,9 @@ impl<'a> InferenceContext<'a> { Expr::BinaryOp { lhs, rhs, op } => match op { Some(op) => { let lhs_expectation = match op { - BinaryOp::LogicOp(..) => Expectation::has_type(Ty::Scalar(Scalar::Bool)), + BinaryOp::LogicOp(..) => { + Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(&Interner)) + } _ => Expectation::none(), }; let lhs_ty = self.infer_expr(*lhs, &lhs_expectation); @@ -563,7 +584,7 @@ impl<'a> InferenceContext<'a> { let ret = op::binary_op_return_ty(*op, lhs_ty.clone(), rhs_ty.clone()); - if ret == Ty::Unknown { + if ret.is_unknown() { cov_mark::hit!(infer_expr_inner_binary_operator_overload); self.resolve_associated_type_with_params( @@ -575,7 +596,7 @@ impl<'a> InferenceContext<'a> { ret } } - _ => Ty::Unknown, + _ => self.err_ty(), }, Expr::Range { lhs, rhs, range_type } => { let lhs_ty = lhs.map(|e| self.infer_expr_inner(e, &Expectation::none())); @@ -586,33 +607,33 @@ impl<'a> InferenceContext<'a> { match (range_type, lhs_ty, rhs_ty) { (RangeOp::Exclusive, None, None) => match self.resolve_range_full() { Some(adt) => Ty::adt_ty(adt, Substs::empty()), - None => Ty::Unknown, + None => self.err_ty(), }, (RangeOp::Exclusive, None, Some(ty)) => match self.resolve_range_to() { Some(adt) => Ty::adt_ty(adt, Substs::single(ty)), - None => Ty::Unknown, + None => self.err_ty(), }, (RangeOp::Inclusive, None, Some(ty)) => { match self.resolve_range_to_inclusive() { Some(adt) => Ty::adt_ty(adt, Substs::single(ty)), - None => Ty::Unknown, + None => self.err_ty(), } } (RangeOp::Exclusive, Some(_), Some(ty)) => match self.resolve_range() { Some(adt) => Ty::adt_ty(adt, Substs::single(ty)), - None => Ty::Unknown, + None => self.err_ty(), }, (RangeOp::Inclusive, Some(_), Some(ty)) => { match self.resolve_range_inclusive() { Some(adt) => Ty::adt_ty(adt, Substs::single(ty)), - None => Ty::Unknown, + None => self.err_ty(), } } (RangeOp::Exclusive, Some(ty), None) => match self.resolve_range_from() { Some(adt) => Ty::adt_ty(adt, Substs::single(ty)), - None => Ty::Unknown, + None => self.err_ty(), }, - (RangeOp::Inclusive, _, None) => Ty::Unknown, + (RangeOp::Inclusive, _, None) => self.err_ty(), } } Expr::Index { base, index } => { @@ -631,19 +652,19 @@ impl<'a> InferenceContext<'a> { index_trait, ); let self_ty = - self_ty.map_or(Ty::Unknown, |t| canonicalized.decanonicalize_ty(t.value)); + self_ty.map_or(self.err_ty(), |t| canonicalized.decanonicalize_ty(t.value)); self.resolve_associated_type_with_params( self_ty, self.resolve_ops_index_output(), &[index_ty], ) } else { - Ty::Unknown + self.err_ty() } } Expr::Tuple { exprs } => { - let mut tys = match &expected.ty { - Ty::Tuple(_, substs) => substs + let mut tys = match expected.ty.interned(&Interner) { + TyKind::Tuple(_, substs) => substs .iter() .cloned() .chain(repeat_with(|| self.table.new_type_var())) @@ -656,11 +677,11 @@ impl<'a> InferenceContext<'a> { self.infer_expr_coerce(*expr, &Expectation::has_type(ty.clone())); } - Ty::Tuple(tys.len(), Substs(tys.into())) + TyKind::Tuple(tys.len(), Substs(tys.into())).intern(&Interner) } Expr::Array(array) => { - let elem_ty = match &expected.ty { - Ty::Array(st) | Ty::Slice(st) => st.as_single().clone(), + let elem_ty = match expected.ty.interned(&Interner) { + TyKind::Array(st) | TyKind::Slice(st) => st.as_single().clone(), _ => self.table.new_type_var(), }; @@ -677,43 +698,51 @@ impl<'a> InferenceContext<'a> { ); self.infer_expr( *repeat, - &Expectation::has_type(Ty::Scalar(Scalar::Uint(UintTy::Usize))), + &Expectation::has_type( + TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner), + ), ); } } - Ty::Array(Substs::single(elem_ty)) + TyKind::Array(Substs::single(elem_ty)).intern(&Interner) } Expr::Literal(lit) => match lit { - Literal::Bool(..) => Ty::Scalar(Scalar::Bool), - Literal::String(..) => Ty::Ref(Mutability::Not, Substs::single(Ty::Str)), + Literal::Bool(..) => TyKind::Scalar(Scalar::Bool).intern(&Interner), + Literal::String(..) => { + TyKind::Ref(Mutability::Not, Substs::single(TyKind::Str.intern(&Interner))) + .intern(&Interner) + } Literal::ByteString(..) => { - let byte_type = Ty::Scalar(Scalar::Uint(UintTy::U8)); - let array_type = Ty::Array(Substs::single(byte_type)); - Ty::Ref(Mutability::Not, Substs::single(array_type)) + let byte_type = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(&Interner); + let array_type = TyKind::Array(Substs::single(byte_type)).intern(&Interner); + TyKind::Ref(Mutability::Not, Substs::single(array_type)).intern(&Interner) } - Literal::Char(..) => Ty::Scalar(Scalar::Char), + Literal::Char(..) => TyKind::Scalar(Scalar::Char).intern(&Interner), Literal::Int(_v, ty) => match ty { Some(int_ty) => { - Ty::Scalar(Scalar::Int(primitive::int_ty_from_builtin(*int_ty))) + TyKind::Scalar(Scalar::Int(primitive::int_ty_from_builtin(*int_ty))) + .intern(&Interner) } None => self.table.new_integer_var(), }, Literal::Uint(_v, ty) => match ty { Some(int_ty) => { - Ty::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(*int_ty))) + TyKind::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(*int_ty))) + .intern(&Interner) } None => self.table.new_integer_var(), }, Literal::Float(_v, ty) => match ty { Some(float_ty) => { - Ty::Scalar(Scalar::Float(primitive::float_ty_from_builtin(*float_ty))) + TyKind::Scalar(Scalar::Float(primitive::float_ty_from_builtin(*float_ty))) + .intern(&Interner) } None => self.table.new_float_var(), }, }, }; - // use a new type variable if we got Ty::Unknown here + // use a new type variable if we got unknown here let ty = self.insert_type_vars_shallow(ty); let ty = self.resolve_ty_as_possible(ty); self.write_expr_ty(tgt_expr, ty.clone()); @@ -730,7 +759,7 @@ impl<'a> InferenceContext<'a> { match stmt { Statement::Let { pat, type_ref, initializer } => { let decl_ty = - type_ref.as_ref().map(|tr| self.make_ty(tr)).unwrap_or(Ty::Unknown); + type_ref.as_ref().map(|tr| self.make_ty(tr)).unwrap_or(self.err_ty()); // Always use the declared type when specified let mut ty = decl_ty.clone(); @@ -738,7 +767,7 @@ impl<'a> InferenceContext<'a> { if let Some(expr) = initializer { let actual_ty = self.infer_expr_coerce(*expr, &Expectation::has_type(decl_ty.clone())); - if decl_ty == Ty::Unknown { + if decl_ty.is_unknown() { ty = actual_ty; } } @@ -802,7 +831,7 @@ impl<'a> InferenceContext<'a> { self.write_method_resolution(tgt_expr, func); (ty, self.db.value_ty(func.into()), Some(generics(self.db.upcast(), func.into()))) } - None => (receiver_ty, Binders::new(0, Ty::Unknown), None), + None => (receiver_ty, Binders::new(0, self.err_ty()), None), }; let substs = self.substs_for_method_call(def_generics, generic_args, &derefed_receiver_ty); let method_ty = method_ty.subst(&substs); @@ -813,15 +842,17 @@ impl<'a> InferenceContext<'a> { if !sig.params().is_empty() { (sig.params()[0].clone(), sig.params()[1..].to_vec(), sig.ret().clone()) } else { - (Ty::Unknown, Vec::new(), sig.ret().clone()) + (self.err_ty(), Vec::new(), sig.ret().clone()) } } - None => (Ty::Unknown, Vec::new(), Ty::Unknown), + None => (self.err_ty(), Vec::new(), self.err_ty()), }; // Apply autoref so the below unification works correctly // FIXME: return correct autorefs from lookup_method let actual_receiver_ty = match expected_receiver_ty.as_reference() { - Some((_, mutability)) => Ty::Ref(mutability, Substs::single(derefed_receiver_ty)), + Some((_, mutability)) => { + TyKind::Ref(mutability, Substs::single(derefed_receiver_ty)).intern(&Interner) + } _ => derefed_receiver_ty, }; self.unify(&expected_receiver_ty, &actual_receiver_ty); @@ -837,7 +868,7 @@ impl<'a> InferenceContext<'a> { // that we have more information about the types of arguments when we // type-check the functions. This isn't really the right way to do this. for &check_closures in &[false, true] { - let param_iter = param_tys.iter().cloned().chain(repeat(Ty::Unknown)); + let param_iter = param_tys.iter().cloned().chain(repeat(self.err_ty())); for (&arg, param_ty) in args.iter().zip(param_iter) { let is_closure = matches!(&self.body[arg], Expr::Lambda { .. }); if is_closure != check_closures { @@ -867,7 +898,7 @@ impl<'a> InferenceContext<'a> { if param.provenance == hir_def::generics::TypeParamProvenance::TraitSelf { substs.push(receiver_ty.clone()); } else { - substs.push(Ty::Unknown); + substs.push(self.err_ty()); } } } @@ -891,15 +922,15 @@ impl<'a> InferenceContext<'a> { }; let supplied_params = substs.len(); for _ in supplied_params..total_len { - substs.push(Ty::Unknown); + substs.push(self.err_ty()); } assert_eq!(substs.len(), total_len); Substs(substs.into()) } fn register_obligations_for_call(&mut self, callable_ty: &Ty) { - if let &Ty::FnDef(def, ref parameters) = callable_ty { - let generic_predicates = self.db.generic_predicates(def.into()); + if let TyKind::FnDef(def, parameters) = callable_ty.interned(&Interner) { + let generic_predicates = self.db.generic_predicates((*def).into()); for predicate in generic_predicates.iter() { let predicate = predicate.clone().subst(parameters); if let Some(obligation) = Obligation::from_predicate(predicate) { diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs index a0ac8d80f..a16755cda 100644 --- a/crates/hir_ty/src/infer/pat.rs +++ b/crates/hir_ty/src/infer/pat.rs @@ -12,7 +12,7 @@ use hir_def::{ use hir_expand::name::Name; use super::{BindingMode, Expectation, InferenceContext}; -use crate::{lower::lower_to_chalk_mutability, utils::variant_data, Substs, Ty}; +use crate::{lower::lower_to_chalk_mutability, utils::variant_data, Interner, Substs, Ty, TyKind}; impl<'a> InferenceContext<'a> { fn infer_tuple_struct_pat( @@ -46,7 +46,7 @@ impl<'a> InferenceContext<'a> { let expected_ty = var_data .as_ref() .and_then(|d| d.field(&Name::new_tuple_field(i))) - .map_or(Ty::Unknown, |field| field_tys[field].clone().subst(&substs)); + .map_or(self.err_ty(), |field| field_tys[field].clone().subst(&substs)); let expected_ty = self.normalize_associated_types_in(expected_ty); self.infer_pat(subpat, &expected_ty, default_bm); } @@ -80,8 +80,8 @@ impl<'a> InferenceContext<'a> { self.result.record_pat_field_resolutions.insert(subpat.pat, field_def); } - let expected_ty = - matching_field.map_or(Ty::Unknown, |field| field_tys[field].clone().subst(&substs)); + let expected_ty = matching_field + .map_or(self.err_ty(), |field| field_tys[field].clone().subst(&substs)); let expected_ty = self.normalize_associated_types_in(expected_ty); self.infer_pat(subpat.pat, &expected_ty, default_bm); } @@ -129,7 +129,8 @@ impl<'a> InferenceContext<'a> { None => (&args[..], &[][..]), }; let n_uncovered_patterns = expectations.len().saturating_sub(args.len()); - let mut expectations_iter = expectations.iter().chain(repeat(&Ty::Unknown)); + let err_ty = self.err_ty(); + let mut expectations_iter = expectations.iter().chain(repeat(&err_ty)); let mut infer_pat = |(&pat, ty)| self.infer_pat(pat, ty, default_bm); let mut inner_tys = Vec::with_capacity(n_uncovered_patterns + args.len()); @@ -137,7 +138,7 @@ impl<'a> InferenceContext<'a> { inner_tys.extend(expectations_iter.by_ref().take(n_uncovered_patterns).cloned()); inner_tys.extend(post.iter().zip(expectations_iter).map(infer_pat)); - Ty::Tuple(inner_tys.len(), Substs(inner_tys.into())) + TyKind::Tuple(inner_tys.len(), Substs(inner_tys.into())).intern(&Interner) } Pat::Or(ref pats) => { if let Some((first_pat, rest)) = pats.split_first() { @@ -147,7 +148,7 @@ impl<'a> InferenceContext<'a> { } ty } else { - Ty::Unknown + self.err_ty() } } Pat::Ref { pat, mutability } => { @@ -159,10 +160,10 @@ impl<'a> InferenceContext<'a> { } inner_ty } - _ => &Ty::Unknown, + _ => &Ty(TyKind::Unknown), }; let subty = self.infer_pat(*pat, expectation, default_bm); - Ty::Ref(mutability, Substs::single(subty)) + TyKind::Ref(mutability, Substs::single(subty)).intern(&Interner) } Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat( p.as_ref(), @@ -178,7 +179,7 @@ impl<'a> InferenceContext<'a> { Pat::Path(path) => { // FIXME use correct resolver for the surrounding expression let resolver = self.resolver.clone(); - self.infer_path(&resolver, &path, pat.into()).unwrap_or(Ty::Unknown) + self.infer_path(&resolver, &path, pat.into()).unwrap_or(self.err_ty()) } Pat::Bind { mode, name: _, subpat } => { let mode = if mode == &BindingAnnotation::Unannotated { @@ -195,7 +196,7 @@ impl<'a> InferenceContext<'a> { let bound_ty = match mode { BindingMode::Ref(mutability) => { - Ty::Ref(mutability, Substs::single(inner_ty.clone())) + TyKind::Ref(mutability, Substs::single(inner_ty.clone())).intern(&Interner) } BindingMode::Move => inner_ty.clone(), }; @@ -204,17 +205,17 @@ impl<'a> InferenceContext<'a> { return inner_ty; } Pat::Slice { prefix, slice, suffix } => { - let (container_ty, elem_ty): (fn(_) -> _, _) = match &expected { - Ty::Array(st) => (Ty::Array, st.as_single().clone()), - Ty::Slice(st) => (Ty::Slice, st.as_single().clone()), - _ => (Ty::Slice, Ty::Unknown), + let (container_ty, elem_ty): (fn(_) -> _, _) = match expected.interned(&Interner) { + TyKind::Array(st) => (TyKind::Array, st.as_single().clone()), + TyKind::Slice(st) => (TyKind::Slice, st.as_single().clone()), + _ => (TyKind::Slice, self.err_ty()), }; for pat_id in prefix.iter().chain(suffix) { self.infer_pat(*pat_id, &elem_ty, default_bm); } - let pat_ty = container_ty(Substs::single(elem_ty)); + let pat_ty = container_ty(Substs::single(elem_ty)).intern(&Interner); if let Some(slice_pat_id) = slice { self.infer_pat(*slice_pat_id, &pat_ty, default_bm); } @@ -232,20 +233,20 @@ impl<'a> InferenceContext<'a> { Some(box_adt) => { let inner_expected = match expected.as_adt() { Some((adt, substs)) if adt == box_adt => substs.as_single(), - _ => &Ty::Unknown, + _ => &Ty(TyKind::Unknown), }; let inner_ty = self.infer_pat(*inner, inner_expected, default_bm); Ty::adt_ty(box_adt, Substs::single(inner_ty)) } - None => Ty::Unknown, + None => self.err_ty(), }, Pat::ConstBlock(expr) => { self.infer_expr(*expr, &Expectation::has_type(expected.clone())) } - Pat::Missing => Ty::Unknown, + Pat::Missing => self.err_ty(), }; - // use a new type variable if we got Ty::Unknown here + // use a new type variable if we got error type here let ty = self.insert_type_vars_shallow(ty); if !self.unify(&ty, expected) { // FIXME record mismatch, we need to change the type of self.type_mismatches for that diff --git a/crates/hir_ty/src/infer/path.rs b/crates/hir_ty/src/infer/path.rs index ae3554bac..392952178 100644 --- a/crates/hir_ty/src/infer/path.rs +++ b/crates/hir_ty/src/infer/path.rs @@ -9,7 +9,7 @@ use hir_def::{ }; use hir_expand::name::Name; -use crate::{method_resolution, Substs, Ty, ValueTyDefId}; +use crate::{method_resolution, Interner, Substs, Ty, TyKind, ValueTyDefId}; use super::{ExprOrPatId, InferenceContext, TraitRef}; @@ -144,7 +144,7 @@ impl<'a> InferenceContext<'a> { remaining_segments_for_ty, true, ); - if let Ty::Unknown = ty { + if let TyKind::Unknown = ty.interned(&Interner) { return None; } @@ -209,7 +209,7 @@ impl<'a> InferenceContext<'a> { name: &Name, id: ExprOrPatId, ) -> Option<(ValueNs, Option)> { - if let Ty::Unknown = ty { + if let TyKind::Unknown = ty.interned(&Interner) { return None; } diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs index 54fcfed10..16d89ed1b 100644 --- a/crates/hir_ty/src/infer/unify.rs +++ b/crates/hir_ty/src/infer/unify.rs @@ -7,8 +7,8 @@ use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; use super::{InferenceContext, Obligation}; use crate::{ - BoundVar, Canonical, DebruijnIndex, GenericPredicate, InEnvironment, InferenceVar, Scalar, - Substs, Ty, TypeWalk, + BoundVar, Canonical, DebruijnIndex, GenericPredicate, InEnvironment, InferenceVar, Interner, + Scalar, Substs, Ty, TyKind, TypeWalk, }; impl<'a> InferenceContext<'a> { @@ -49,8 +49,8 @@ impl<'a, 'b> Canonicalizer<'a, 'b> { fn do_canonicalize(&mut self, t: T, binders: DebruijnIndex) -> T { t.fold_binders( - &mut |ty, binders| match ty { - Ty::InferenceVar(var, kind) => { + &mut |ty, binders| match ty.interned(&Interner) { + &TyKind::InferenceVar(var, kind) => { let inner = var.to_inner(); if self.var_stack.contains(&inner) { // recursive type @@ -66,7 +66,7 @@ impl<'a, 'b> Canonicalizer<'a, 'b> { } else { let root = self.ctx.table.var_unification_table.find(inner); let position = self.add(InferenceVar::from_inner(root), kind); - Ty::BoundVar(BoundVar::new(binders, position)) + TyKind::BoundVar(BoundVar::new(binders, position)).intern(&Interner) } } _ => ty, @@ -108,10 +108,10 @@ impl Canonicalized { pub(super) fn decanonicalize_ty(&self, mut ty: Ty) -> Ty { ty.walk_mut_binders( &mut |ty, binders| { - if let &mut Ty::BoundVar(bound) = ty { + if let &mut TyKind::BoundVar(bound) = &mut ty.0 { if bound.debruijn >= binders { let (v, k) = self.free_vars[bound.index]; - *ty = Ty::InferenceVar(v, k); + *ty = TyKind::InferenceVar(v, k).intern(&Interner); } } }, @@ -142,7 +142,7 @@ impl Canonicalized { // eagerly replace projections in the type; we may be getting types // e.g. from where clauses where this hasn't happened yet let ty = ctx.normalize_associated_types_in(ty.clone().subst_bound_vars(&new_vars)); - ctx.table.unify(&Ty::InferenceVar(v, k), &ty); + ctx.table.unify(&TyKind::InferenceVar(v, k).intern(&Interner), &ty); } } } @@ -166,7 +166,10 @@ pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option { // (kind of hacky) for (i, var) in vars.iter().enumerate() { if &*table.resolve_ty_shallow(var) == var { - table.unify(var, &Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i))); + table.unify( + var, + &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i)).intern(&Interner), + ); } } Some( @@ -196,11 +199,12 @@ impl TypeVariableTable { fn fallback_value(&self, iv: InferenceVar, kind: TyVariableKind) -> Ty { match kind { - _ if self.inner[iv.to_inner().0 as usize].diverging => Ty::Never, - TyVariableKind::General => Ty::Unknown, - TyVariableKind::Integer => Ty::Scalar(Scalar::Int(IntTy::I32)), - TyVariableKind::Float => Ty::Scalar(Scalar::Float(FloatTy::F64)), + _ if self.inner[iv.to_inner().0 as usize].diverging => TyKind::Never, + TyVariableKind::General => TyKind::Unknown, + TyVariableKind::Integer => TyKind::Scalar(Scalar::Int(IntTy::I32)), + TyVariableKind::Float => TyKind::Scalar(Scalar::Float(FloatTy::F64)), } + .intern(&Interner) } } @@ -227,7 +231,7 @@ impl InferenceTable { self.type_variable_table.push(TypeVariableData { diverging }); let key = self.var_unification_table.new_key(TypeVarValue::Unknown); assert_eq!(key.0 as usize, self.type_variable_table.inner.len() - 1); - Ty::InferenceVar(InferenceVar::from_inner(key), kind) + TyKind::InferenceVar(InferenceVar::from_inner(key), kind).intern(&Interner) } pub(crate) fn new_type_var(&mut self) -> Ty { @@ -290,12 +294,12 @@ impl InferenceTable { } pub(super) fn unify_inner_trivial(&mut self, ty1: &Ty, ty2: &Ty, depth: usize) -> bool { - match (ty1, ty2) { - (Ty::Unknown, _) | (_, Ty::Unknown) => true, + match (ty1.interned(&Interner), ty2.interned(&Interner)) { + (TyKind::Unknown, _) | (_, TyKind::Unknown) => true, - (Ty::Placeholder(p1), Ty::Placeholder(p2)) if *p1 == *p2 => true, + (TyKind::Placeholder(p1), TyKind::Placeholder(p2)) if *p1 == *p2 => true, - (Ty::Dyn(dyn1), Ty::Dyn(dyn2)) if dyn1.len() == dyn2.len() => { + (TyKind::Dyn(dyn1), TyKind::Dyn(dyn2)) if dyn1.len() == dyn2.len() => { for (pred1, pred2) in dyn1.iter().zip(dyn2.iter()) { if !self.unify_preds(pred1, pred2, depth + 1) { return false; @@ -305,16 +309,16 @@ impl InferenceTable { } ( - Ty::InferenceVar(tv1, TyVariableKind::General), - Ty::InferenceVar(tv2, TyVariableKind::General), + TyKind::InferenceVar(tv1, TyVariableKind::General), + TyKind::InferenceVar(tv2, TyVariableKind::General), ) | ( - Ty::InferenceVar(tv1, TyVariableKind::Integer), - Ty::InferenceVar(tv2, TyVariableKind::Integer), + TyKind::InferenceVar(tv1, TyVariableKind::Integer), + TyKind::InferenceVar(tv2, TyVariableKind::Integer), ) | ( - Ty::InferenceVar(tv1, TyVariableKind::Float), - Ty::InferenceVar(tv2, TyVariableKind::Float), + TyKind::InferenceVar(tv1, TyVariableKind::Float), + TyKind::InferenceVar(tv2, TyVariableKind::Float), ) if self.type_variable_table.is_diverging(*tv1) == self.type_variable_table.is_diverging(*tv2) => { @@ -326,24 +330,37 @@ impl InferenceTable { // The order of MaybeNeverTypeVar matters here. // Unifying MaybeNeverTypeVar and TypeVar will let the latter become MaybeNeverTypeVar. // Unifying MaybeNeverTypeVar and other concrete type will let the former become it. - (Ty::InferenceVar(tv, TyVariableKind::General), other) - | (other, Ty::InferenceVar(tv, TyVariableKind::General)) - | (Ty::InferenceVar(tv, TyVariableKind::Integer), other @ Ty::Scalar(Scalar::Int(_))) - | (other @ Ty::Scalar(Scalar::Int(_)), Ty::InferenceVar(tv, TyVariableKind::Integer)) + (TyKind::InferenceVar(tv, TyVariableKind::General), other) + | (other, TyKind::InferenceVar(tv, TyVariableKind::General)) | ( - Ty::InferenceVar(tv, TyVariableKind::Integer), - other @ Ty::Scalar(Scalar::Uint(_)), + TyKind::InferenceVar(tv, TyVariableKind::Integer), + other @ TyKind::Scalar(Scalar::Int(_)), ) | ( - other @ Ty::Scalar(Scalar::Uint(_)), - Ty::InferenceVar(tv, TyVariableKind::Integer), + other @ TyKind::Scalar(Scalar::Int(_)), + TyKind::InferenceVar(tv, TyVariableKind::Integer), ) - | (Ty::InferenceVar(tv, TyVariableKind::Float), other @ Ty::Scalar(Scalar::Float(_))) - | (other @ Ty::Scalar(Scalar::Float(_)), Ty::InferenceVar(tv, TyVariableKind::Float)) => - { + | ( + TyKind::InferenceVar(tv, TyVariableKind::Integer), + other @ TyKind::Scalar(Scalar::Uint(_)), + ) + | ( + other @ TyKind::Scalar(Scalar::Uint(_)), + TyKind::InferenceVar(tv, TyVariableKind::Integer), + ) + | ( + TyKind::InferenceVar(tv, TyVariableKind::Float), + other @ TyKind::Scalar(Scalar::Float(_)), + ) + | ( + other @ TyKind::Scalar(Scalar::Float(_)), + TyKind::InferenceVar(tv, TyVariableKind::Float), + ) => { // the type var is unknown since we tried to resolve it - self.var_unification_table - .union_value(tv.to_inner(), TypeVarValue::Known(other.clone())); + self.var_unification_table.union_value( + tv.to_inner(), + TypeVarValue::Known(other.clone().intern(&Interner)), + ); true } @@ -387,8 +404,8 @@ impl InferenceTable { if i > 0 { cov_mark::hit!(type_var_resolves_to_int_var); } - match &*ty { - Ty::InferenceVar(tv, _) => { + match &ty.0 { + TyKind::InferenceVar(tv, _) => { let inner = tv.to_inner(); match self.var_unification_table.inlined_probe_value(inner).known() { Some(known_ty) => { @@ -410,8 +427,8 @@ impl InferenceTable { /// be resolved as far as possible, i.e. contain no type variables with /// known type. fn resolve_ty_as_possible_inner(&mut self, tv_stack: &mut Vec, ty: Ty) -> Ty { - ty.fold(&mut |ty| match ty { - Ty::InferenceVar(tv, kind) => { + ty.fold(&mut |ty| match ty.interned(&Interner) { + &TyKind::InferenceVar(tv, kind) => { let inner = tv.to_inner(); if tv_stack.contains(&inner) { cov_mark::hit!(type_var_cycles_resolve_as_possible); @@ -435,10 +452,10 @@ impl InferenceTable { } /// Resolves the type completely; type variables without known type are - /// replaced by Ty::Unknown. + /// replaced by TyKind::Unknown. fn resolve_ty_completely_inner(&mut self, tv_stack: &mut Vec, ty: Ty) -> Ty { - ty.fold(&mut |ty| match ty { - Ty::InferenceVar(tv, kind) => { + ty.fold(&mut |ty| match ty.interned(&Interner) { + &TyKind::InferenceVar(tv, kind) => { let inner = tv.to_inner(); if tv_stack.contains(&inner) { cov_mark::hit!(type_var_cycles_resolve_completely); -- cgit v1.2.3