From a3f5491a1a312393429a44028e7496fe0a12f8c2 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sun, 28 Feb 2021 19:13:37 +0100 Subject: Inline TypeCtor into Ty --- crates/hir_ty/src/infer/coerce.rs | 79 ++++++------- crates/hir_ty/src/infer/expr.rs | 238 +++++++++++++++----------------------- crates/hir_ty/src/infer/pat.rs | 27 ++--- crates/hir_ty/src/infer/unify.rs | 38 +++--- 4 files changed, 157 insertions(+), 225 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 32c7c57cd..cd5fb3252 100644 --- a/crates/hir_ty/src/infer/coerce.rs +++ b/crates/hir_ty/src/infer/coerce.rs @@ -7,7 +7,7 @@ use hir_def::{lang_item::LangItemTarget, type_ref::Mutability}; use test_utils::mark; -use crate::{autoderef, traits::Solution, Obligation, Substs, TraitRef, Ty, TypeCtor}; +use crate::{autoderef, traits::Solution, Obligation, Substs, TraitRef, Ty}; use super::{unify::TypeVarValue, InEnvironment, InferTy, InferenceContext}; @@ -33,7 +33,7 @@ impl<'a> InferenceContext<'a> { } else if self.coerce(ty2, ty1) { ty1.clone() } else { - if let (ty_app!(TypeCtor::FnDef(_)), ty_app!(TypeCtor::FnDef(_))) = (ty1, ty2) { + if let (Ty::FnDef(..), Ty::FnDef(..)) = (ty1, ty2) { 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 @@ -53,12 +53,12 @@ impl<'a> InferenceContext<'a> { fn coerce_inner(&mut self, mut from_ty: Ty, to_ty: &Ty) -> bool { match (&from_ty, to_ty) { // Never type will make type variable to fallback to Never Type instead of Unknown. - (ty_app!(TypeCtor::Never), Ty::Infer(InferTy::TypeVar(tv))) => { + (Ty::Never, Ty::Infer(InferTy::TypeVar(tv))) => { let var = self.table.new_maybe_never_type_var(); self.table.var_unification_table.union_value(*tv, TypeVarValue::Known(var)); return true; } - (ty_app!(TypeCtor::Never), _) => return true, + (Ty::Never, _) => return true, // Trivial cases, this should go after `never` check to // avoid infer result type to be never @@ -71,38 +71,33 @@ impl<'a> InferenceContext<'a> { // Pointer weakening and function to pointer match (&mut from_ty, to_ty) { - // `*mut T`, `&mut T, `&T`` -> `*const T` + // `*mut T` -> `*const T` // `&mut T` -> `&T` - // `&mut T` -> `*mut T` - (ty_app!(c1@TypeCtor::RawPtr(_)), ty_app!(c2@TypeCtor::RawPtr(Mutability::Shared))) - | (ty_app!(c1@TypeCtor::Ref(_)), ty_app!(c2@TypeCtor::RawPtr(Mutability::Shared))) - | (ty_app!(c1@TypeCtor::Ref(_)), ty_app!(c2@TypeCtor::Ref(Mutability::Shared))) - | (ty_app!(c1@TypeCtor::Ref(Mutability::Mut)), ty_app!(c2@TypeCtor::RawPtr(_))) => { - *c1 = *c2; + (Ty::RawPtr(m1, ..), Ty::RawPtr(m2 @ Mutability::Shared, ..)) + | (Ty::Ref(m1, ..), Ty::Ref(m2 @ Mutability::Shared, ..)) => { + *m1 = *m2; + } + // `&T` -> `*const T` + // `&mut T` -> `*mut T`/`*const T` + (Ty::Ref(.., substs), &Ty::RawPtr(m2 @ Mutability::Shared, ..)) + | (Ty::Ref(Mutability::Mut, substs), &Ty::RawPtr(m2, ..)) => { + from_ty = Ty::RawPtr(m2, substs.clone()); } - // Illegal mutablity conversion - ( - ty_app!(TypeCtor::RawPtr(Mutability::Shared)), - ty_app!(TypeCtor::RawPtr(Mutability::Mut)), - ) - | ( - ty_app!(TypeCtor::Ref(Mutability::Shared)), - ty_app!(TypeCtor::Ref(Mutability::Mut)), - ) => return false, + // Illegal mutability conversion + (Ty::RawPtr(Mutability::Shared, ..), Ty::RawPtr(Mutability::Mut, ..)) + | (Ty::Ref(Mutability::Shared, ..), Ty::Ref(Mutability::Mut, ..)) => return false, // `{function_type}` -> `fn()` - (ty_app!(TypeCtor::FnDef(_)), ty_app!(TypeCtor::FnPtr { .. })) => { - match from_ty.callable_sig(self.db) { - None => return false, - Some(sig) => { - from_ty = Ty::fn_ptr(sig); - } + (Ty::FnDef(..), Ty::FnPtr { .. }) => match from_ty.callable_sig(self.db) { + None => return false, + Some(sig) => { + from_ty = Ty::fn_ptr(sig); } - } + }, - (ty_app!(TypeCtor::Closure { .. }, params), ty_app!(TypeCtor::FnPtr { .. })) => { - from_ty = params[0].clone(); + (Ty::Closure { substs, .. }, Ty::FnPtr { .. }) => { + from_ty = substs[0].clone(); } _ => {} @@ -115,9 +110,7 @@ impl<'a> InferenceContext<'a> { // Auto Deref if cannot coerce match (&from_ty, to_ty) { // FIXME: DerefMut - (ty_app!(TypeCtor::Ref(_), st1), ty_app!(TypeCtor::Ref(_), st2)) => { - self.unify_autoderef_behind_ref(&st1[0], &st2[0]) - } + (Ty::Ref(_, st1), Ty::Ref(_, st2)) => self.unify_autoderef_behind_ref(&st1[0], &st2[0]), // Otherwise, normal unify _ => self.unify(&from_ty, to_ty), @@ -178,17 +171,17 @@ impl<'a> InferenceContext<'a> { }, ) { let derefed_ty = canonicalized.decanonicalize_ty(derefed_ty.value); - match (&*self.resolve_ty_shallow(&derefed_ty), &*to_ty) { - // Stop when constructor matches. - (ty_app!(from_ctor, st1), ty_app!(to_ctor, st2)) if from_ctor == to_ctor => { - // It will not recurse to `coerce`. - return self.table.unify_substs(st1, st2, 0); - } - _ => { - if self.table.unify_inner_trivial(&derefed_ty, &to_ty, 0) { - return true; - } - } + let from_ty = self.resolve_ty_shallow(&derefed_ty); + // Stop when constructor matches. + if from_ty.equals_ctor(&to_ty) { + // It will not recurse to `coerce`. + return match (from_ty.substs(), to_ty.substs()) { + (Some(st1), Some(st2)) => self.table.unify_substs(st1, st2, 0), + (None, None) => true, + _ => false, + }; + } else if self.table.unify_inner_trivial(&derefed_ty, &to_ty, 0) { + return true; } } diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 3fec0e431..2369c9bef 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs @@ -18,8 +18,8 @@ use crate::{ primitive::{self, UintTy}, traits::{FnTrait, InEnvironment}, utils::{generics, variant_data, Generics}, - ApplicationTy, Binders, CallableDefId, InferTy, Mutability, Obligation, OpaqueTyId, Rawness, - Scalar, Substs, TraitRef, Ty, TypeCtor, + Binders, CallableDefId, InferTy, Mutability, Obligation, OpaqueTyId, Rawness, Scalar, Substs, + TraitRef, Ty, }; use super::{ @@ -82,10 +82,7 @@ impl<'a> InferenceContext<'a> { arg_tys.push(arg); } let parameters = param_builder.build(); - let arg_ty = Ty::Apply(ApplicationTy { - ctor: TypeCtor::Tuple { cardinality: num_args as u16 }, - parameters, - }); + let arg_ty = Ty::Tuple { cardinality: num_args as u16, substs: parameters }; let substs = Substs::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build(); @@ -120,10 +117,7 @@ impl<'a> InferenceContext<'a> { Expr::Missing => Ty::Unknown, 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::simple(TypeCtor::Scalar(Scalar::Bool))), - ); + self.infer_expr(*condition, &Expectation::has_type(Ty::Scalar(Scalar::Bool))); let condition_diverges = mem::replace(&mut self.diverges, Diverges::Maybe); let mut both_arms_diverge = Diverges::Always; @@ -178,7 +172,7 @@ impl<'a> InferenceContext<'a> { // existenail type AsyncBlockImplTrait: Future let inner_ty = self.infer_expr(*body, &Expectation::none()); let opaque_ty_id = OpaqueTyId::AsyncBlockTypeImplTrait(self.owner, *body); - Ty::apply_one(TypeCtor::OpaqueType(opaque_ty_id), inner_ty) + Ty::OpaqueType(opaque_ty_id, Substs::single(inner_ty)) } Expr::Loop { body, label } => { self.breakables.push(BreakableContext { @@ -196,7 +190,7 @@ impl<'a> InferenceContext<'a> { if ctxt.may_break { ctxt.break_ty } else { - Ty::simple(TypeCtor::Never) + Ty::Never } } Expr::While { condition, body, label } => { @@ -206,10 +200,7 @@ impl<'a> InferenceContext<'a> { 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::simple(TypeCtor::Scalar(Scalar::Bool))), - ); + self.infer_expr(*condition, &Expectation::has_type(Ty::Scalar(Scalar::Bool))); 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 @@ -256,12 +247,13 @@ impl<'a> InferenceContext<'a> { None => self.table.new_type_var(), }; sig_tys.push(ret_ty.clone()); - let sig_ty = Ty::apply( - TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1, is_varargs: false }, - Substs(sig_tys.clone().into()), - ); + let sig_ty = Ty::FnPtr { + num_args: sig_tys.len() as u16 - 1, + is_varargs: false, + substs: Substs(sig_tys.clone().into()), + }; let closure_ty = - Ty::apply_one(TypeCtor::Closure { def: self.owner, expr: tgt_expr }, sig_ty); + Ty::Closure { def: self.owner, expr: tgt_expr, substs: Substs::single(sig_ty) }; // Eagerly try to relate the closure type with the expected // type, otherwise we often won't have enough information to @@ -312,11 +304,8 @@ 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::simple(TypeCtor::Never) - } else { - self.table.new_type_var() - }; + let mut result_ty = + if arms.is_empty() { Ty::Never } else { self.table.new_type_var() }; let matchee_diverges = self.diverges; let mut all_arms_diverge = Diverges::Always; @@ -327,7 +316,7 @@ impl<'a> InferenceContext<'a> { if let Some(guard_expr) = arm.guard { self.infer_expr( guard_expr, - &Expectation::has_type(Ty::simple(TypeCtor::Scalar(Scalar::Bool))), + &Expectation::has_type(Ty::Scalar(Scalar::Bool)), ); } @@ -345,7 +334,7 @@ impl<'a> InferenceContext<'a> { let resolver = resolver_for_expr(self.db.upcast(), self.owner, tgt_expr); self.infer_path(&resolver, p, tgt_expr.into()).unwrap_or(Ty::Unknown) } - Expr::Continue { .. } => Ty::simple(TypeCtor::Never), + Expr::Continue { .. } => Ty::Never, Expr::Break { expr, label } => { let val_ty = if let Some(expr) = expr { self.infer_expr(*expr, &Expectation::none()) @@ -370,8 +359,7 @@ impl<'a> InferenceContext<'a> { expr: tgt_expr, }); } - - Ty::simple(TypeCtor::Never) + Ty::Never } Expr::Return { expr } => { if let Some(expr) = expr { @@ -380,14 +368,14 @@ impl<'a> InferenceContext<'a> { let unit = Ty::unit(); self.coerce(&unit, &self.return_ty.clone()); } - Ty::simple(TypeCtor::Never) + Ty::Never } Expr::Yield { expr } => { // FIXME: track yield type for coercion if let Some(expr) = expr { self.infer_expr(*expr, &Expectation::none()); } - Ty::simple(TypeCtor::Never) + Ty::Never } Expr::RecordLit { path, fields, spread } => { let (ty, def_id) = self.resolve_variant(path.as_ref()); @@ -397,7 +385,7 @@ impl<'a> InferenceContext<'a> { self.unify(&ty, &expected.ty); - let substs = ty.substs().unwrap_or_else(Substs::empty); + let substs = ty.substs().cloned().unwrap_or_else(Substs::empty); let field_types = def_id.map(|it| self.db.field_types(it)).unwrap_or_default(); let variant_data = def_id.map(|it| variant_data(self.db.upcast(), it)); for (field_idx, field) in fields.iter().enumerate() { @@ -436,30 +424,23 @@ impl<'a> InferenceContext<'a> { }, ) .find_map(|derefed_ty| match canonicalized.decanonicalize_ty(derefed_ty.value) { - Ty::Apply(a_ty) => match a_ty.ctor { - TypeCtor::Tuple { .. } => name - .as_tuple_index() - .and_then(|idx| a_ty.parameters.0.get(idx).cloned()), - TypeCtor::Adt(AdtId::StructId(s)) => { - 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(&a_ty.parameters) - }) - } - TypeCtor::Adt(AdtId::UnionId(u)) => { - 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(&a_ty.parameters) - }) - } - _ => None, - }, + Ty::Tuple { substs, .. } => { + name.as_tuple_index().and_then(|idx| substs.0.get(idx).cloned()) + } + Ty::Adt(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::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, }) .unwrap_or(Ty::Unknown); @@ -497,19 +478,18 @@ impl<'a> InferenceContext<'a> { Expectation::none() }; let inner_ty = self.infer_expr_inner(*expr, &expectation); - let ty = match rawness { - Rawness::RawPtr => TypeCtor::RawPtr(*mutability), - Rawness::Ref => TypeCtor::Ref(*mutability), - }; - Ty::apply_one(ty, inner_ty) + match rawness { + Rawness::RawPtr => Ty::RawPtr(*mutability, Substs::single(inner_ty)), + Rawness::Ref => Ty::Ref(*mutability, Substs::single(inner_ty)), + } } Expr::Box { expr } => { let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); if let Some(box_) = self.resolve_boxed_box() { - let mut sb = Substs::build_for_type_ctor(self.db, TypeCtor::Adt(box_)); + let mut sb = Substs::builder(generics(self.db.upcast(), box_.into()).len()); sb = sb.push(inner_ty); sb = sb.fill(repeat_with(|| self.table.new_type_var())); - Ty::apply(TypeCtor::Adt(box_), sb.build()) + Ty::Adt(box_, sb.build()) } else { Ty::Unknown } @@ -539,14 +519,9 @@ impl<'a> InferenceContext<'a> { UnaryOp::Neg => { match &inner_ty { // Fast path for builtins - Ty::Apply(ApplicationTy { - ctor: TypeCtor::Scalar(Scalar::Int(_)), - .. - }) - | Ty::Apply(ApplicationTy { - ctor: TypeCtor::Scalar(Scalar::Float(_)), - .. - }) + Ty::Scalar(Scalar::Int(_)) + | Ty::Scalar(Scalar::Uint(_)) + | Ty::Scalar(Scalar::Float(_)) | Ty::Infer(InferTy::IntVar(..)) | Ty::Infer(InferTy::FloatVar(..)) => inner_ty, // Otherwise we resolve via the std::ops::Neg trait @@ -557,18 +532,9 @@ impl<'a> InferenceContext<'a> { UnaryOp::Not => { match &inner_ty { // Fast path for builtins - Ty::Apply(ApplicationTy { - ctor: TypeCtor::Scalar(Scalar::Bool), - .. - }) - | Ty::Apply(ApplicationTy { - ctor: TypeCtor::Scalar(Scalar::Int(_)), - .. - }) - | Ty::Apply(ApplicationTy { - ctor: TypeCtor::Scalar(Scalar::Uint(_)), - .. - }) + Ty::Scalar(Scalar::Bool) + | Ty::Scalar(Scalar::Int(_)) + | Ty::Scalar(Scalar::Uint(_)) | Ty::Infer(InferTy::IntVar(..)) => inner_ty, // Otherwise we resolve via the std::ops::Not trait _ => self @@ -580,9 +546,7 @@ impl<'a> InferenceContext<'a> { Expr::BinaryOp { lhs, rhs, op } => match op { Some(op) => { let lhs_expectation = match op { - BinaryOp::LogicOp(..) => { - Expectation::has_type(Ty::simple(TypeCtor::Scalar(Scalar::Bool))) - } + BinaryOp::LogicOp(..) => Expectation::has_type(Ty::Scalar(Scalar::Bool)), _ => Expectation::none(), }; let lhs_ty = self.infer_expr(*lhs, &lhs_expectation); @@ -613,31 +577,31 @@ impl<'a> InferenceContext<'a> { let rhs_ty = rhs.map(|e| self.infer_expr(e, &rhs_expect)); match (range_type, lhs_ty, rhs_ty) { (RangeOp::Exclusive, None, None) => match self.resolve_range_full() { - Some(adt) => Ty::simple(TypeCtor::Adt(adt)), + Some(adt) => Ty::Adt(adt, Substs::empty()), None => Ty::Unknown, }, (RangeOp::Exclusive, None, Some(ty)) => match self.resolve_range_to() { - Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty), + Some(adt) => Ty::Adt(adt, Substs::single(ty)), None => Ty::Unknown, }, (RangeOp::Inclusive, None, Some(ty)) => { match self.resolve_range_to_inclusive() { - Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty), + Some(adt) => Ty::Adt(adt, Substs::single(ty)), None => Ty::Unknown, } } (RangeOp::Exclusive, Some(_), Some(ty)) => match self.resolve_range() { - Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty), + Some(adt) => Ty::Adt(adt, Substs::single(ty)), None => Ty::Unknown, }, (RangeOp::Inclusive, Some(_), Some(ty)) => { match self.resolve_range_inclusive() { - Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty), + Some(adt) => Ty::Adt(adt, Substs::single(ty)), None => Ty::Unknown, } } (RangeOp::Exclusive, Some(ty), None) => match self.resolve_range_from() { - Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty), + Some(adt) => Ty::Adt(adt, Substs::single(ty)), None => Ty::Unknown, }, (RangeOp::Inclusive, _, None) => Ty::Unknown, @@ -671,7 +635,7 @@ impl<'a> InferenceContext<'a> { } Expr::Tuple { exprs } => { let mut tys = match &expected.ty { - ty_app!(TypeCtor::Tuple { .. }, st) => st + Ty::Tuple { substs, .. } => substs .iter() .cloned() .chain(repeat_with(|| self.table.new_type_var())) @@ -684,15 +648,11 @@ impl<'a> InferenceContext<'a> { self.infer_expr_coerce(*expr, &Expectation::has_type(ty.clone())); } - Ty::apply(TypeCtor::Tuple { cardinality: tys.len() as u16 }, Substs(tys.into())) + Ty::Tuple { cardinality: tys.len() as u16, substs: Substs(tys.into()) } } Expr::Array(array) => { let elem_ty = match &expected.ty { - // FIXME: remove when https://github.com/rust-lang/rust/issues/80501 is fixed - #[allow(unreachable_patterns)] - ty_app!(TypeCtor::Array, st) | ty_app!(TypeCtor::Slice, st) => { - st.as_single().clone() - } + Ty::Array(st) | Ty::Slice(st) => st.as_single().clone(), _ => self.table.new_type_var(), }; @@ -709,42 +669,38 @@ impl<'a> InferenceContext<'a> { ); self.infer_expr( *repeat, - &Expectation::has_type(Ty::simple(TypeCtor::Scalar(Scalar::Uint( - UintTy::Usize, - )))), + &Expectation::has_type(Ty::Scalar(Scalar::Uint(UintTy::Usize))), ); } } - Ty::apply_one(TypeCtor::Array, elem_ty) + Ty::Array(Substs::single(elem_ty)) } Expr::Literal(lit) => match lit { - Literal::Bool(..) => Ty::simple(TypeCtor::Scalar(Scalar::Bool)), - Literal::String(..) => { - Ty::apply_one(TypeCtor::Ref(Mutability::Shared), Ty::simple(TypeCtor::Str)) - } + Literal::Bool(..) => Ty::Scalar(Scalar::Bool), + Literal::String(..) => Ty::Ref(Mutability::Shared, Substs::single(Ty::Str)), Literal::ByteString(..) => { - let byte_type = Ty::simple(TypeCtor::Scalar(Scalar::Uint(UintTy::U8))); - let array_type = Ty::apply_one(TypeCtor::Array, byte_type); - Ty::apply_one(TypeCtor::Ref(Mutability::Shared), array_type) + let byte_type = Ty::Scalar(Scalar::Uint(UintTy::U8)); + let array_type = Ty::Array(Substs::single(byte_type)); + Ty::Ref(Mutability::Shared, Substs::single(array_type)) } - Literal::Char(..) => Ty::simple(TypeCtor::Scalar(Scalar::Char)), + Literal::Char(..) => Ty::Scalar(Scalar::Char), Literal::Int(_v, ty) => match ty { - Some(int_ty) => Ty::simple(TypeCtor::Scalar(Scalar::Int( - primitive::int_ty_from_builtin(*int_ty), - ))), + Some(int_ty) => { + Ty::Scalar(Scalar::Int(primitive::int_ty_from_builtin(*int_ty))) + } None => self.table.new_integer_var(), }, Literal::Uint(_v, ty) => match ty { - Some(int_ty) => Ty::simple(TypeCtor::Scalar(Scalar::Uint( - primitive::uint_ty_from_builtin(*int_ty), - ))), + Some(int_ty) => { + Ty::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(*int_ty))) + } None => self.table.new_integer_var(), }, Literal::Float(_v, ty) => match ty { - Some(float_ty) => Ty::simple(TypeCtor::Scalar(Scalar::Float( - primitive::float_ty_from_builtin(*float_ty), - ))), + Some(float_ty) => { + Ty::Scalar(Scalar::Float(primitive::float_ty_from_builtin(*float_ty))) + } None => self.table.new_float_var(), }, }, @@ -857,7 +813,7 @@ impl<'a> InferenceContext<'a> { // 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::apply_one(TypeCtor::Ref(mutability), derefed_receiver_ty), + Some((_, mutability)) => Ty::Ref(mutability, Substs::single(derefed_receiver_ty)), _ => derefed_receiver_ty, }; self.unify(&expected_receiver_ty, &actual_receiver_ty); @@ -934,30 +890,26 @@ impl<'a> InferenceContext<'a> { } fn register_obligations_for_call(&mut self, callable_ty: &Ty) { - if let Ty::Apply(a_ty) = callable_ty { - if let TypeCtor::FnDef(def) = a_ty.ctor { - let generic_predicates = self.db.generic_predicates(def.into()); - for predicate in generic_predicates.iter() { - let predicate = predicate.clone().subst(&a_ty.parameters); - if let Some(obligation) = Obligation::from_predicate(predicate) { - self.obligations.push(obligation); - } + if let &Ty::FnDef(def, ref parameters) = callable_ty { + 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) { + self.obligations.push(obligation); } - // add obligation for trait implementation, if this is a trait method - match def { - CallableDefId::FunctionId(f) => { - if let AssocContainerId::TraitId(trait_) = - f.lookup(self.db.upcast()).container - { - // construct a TraitDef - let substs = a_ty - .parameters - .prefix(generics(self.db.upcast(), trait_.into()).len()); - self.obligations.push(Obligation::Trait(TraitRef { trait_, substs })); - } + } + // add obligation for trait implementation, if this is a trait method + match def { + CallableDefId::FunctionId(f) => { + if let AssocContainerId::TraitId(trait_) = f.lookup(self.db.upcast()).container + { + // construct a TraitDef + let substs = + parameters.prefix(generics(self.db.upcast(), trait_.into()).len()); + self.obligations.push(Obligation::Trait(TraitRef { trait_, substs })); } - CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_) => {} } + CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_) => {} } } } diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs index d974f805b..e96e08c3c 100644 --- a/crates/hir_ty/src/infer/pat.rs +++ b/crates/hir_ty/src/infer/pat.rs @@ -13,7 +13,7 @@ use hir_expand::name::Name; use test_utils::mark; use super::{BindingMode, Expectation, InferenceContext}; -use crate::{utils::variant_data, Substs, Ty, TypeCtor}; +use crate::{utils::variant_data, Substs, Ty}; impl<'a> InferenceContext<'a> { fn infer_tuple_struct_pat( @@ -32,7 +32,7 @@ impl<'a> InferenceContext<'a> { } self.unify(&ty, expected); - let substs = ty.substs().unwrap_or_else(Substs::empty); + let substs = ty.substs().cloned().unwrap_or_else(Substs::empty); let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); let (pre, post) = match ellipsis { @@ -71,7 +71,7 @@ impl<'a> InferenceContext<'a> { self.unify(&ty, expected); - let substs = ty.substs().unwrap_or_else(Substs::empty); + let substs = ty.substs().cloned().unwrap_or_else(Substs::empty); let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); for subpat in subpats { @@ -138,10 +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::apply( - TypeCtor::Tuple { cardinality: inner_tys.len() as u16 }, - Substs(inner_tys.into()), - ) + Ty::Tuple { cardinality: inner_tys.len() as u16, substs: Substs(inner_tys.into()) } } Pat::Or(ref pats) => { if let Some((first_pat, rest)) = pats.split_first() { @@ -165,7 +162,7 @@ impl<'a> InferenceContext<'a> { _ => &Ty::Unknown, }; let subty = self.infer_pat(*pat, expectation, default_bm); - Ty::apply_one(TypeCtor::Ref(*mutability), subty) + Ty::Ref(*mutability, Substs::single(subty)) } Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat( p.as_ref(), @@ -198,7 +195,7 @@ impl<'a> InferenceContext<'a> { let bound_ty = match mode { BindingMode::Ref(mutability) => { - Ty::apply_one(TypeCtor::Ref(mutability), inner_ty.clone()) + Ty::Ref(mutability, Substs::single(inner_ty.clone())) } BindingMode::Move => inner_ty.clone(), }; @@ -207,17 +204,17 @@ impl<'a> InferenceContext<'a> { return inner_ty; } Pat::Slice { prefix, slice, suffix } => { - let (container_ty, elem_ty) = match &expected { - ty_app!(TypeCtor::Array, st) => (TypeCtor::Array, st.as_single().clone()), - ty_app!(TypeCtor::Slice, st) => (TypeCtor::Slice, st.as_single().clone()), - _ => (TypeCtor::Slice, Ty::Unknown), + 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), }; for pat_id in prefix.iter().chain(suffix) { self.infer_pat(*pat_id, &elem_ty, default_bm); } - let pat_ty = Ty::apply_one(container_ty, elem_ty); + let pat_ty = container_ty(Substs::single(elem_ty)); if let Some(slice_pat_id) = slice { self.infer_pat(*slice_pat_id, &pat_ty, default_bm); } @@ -239,7 +236,7 @@ impl<'a> InferenceContext<'a> { }; let inner_ty = self.infer_pat(*inner, inner_expected, default_bm); - Ty::apply_one(TypeCtor::Adt(box_adt), inner_ty) + Ty::Adt(box_adt, Substs::single(inner_ty)) } None => Ty::Unknown, }, diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs index 57eb8cede..2852ad5bf 100644 --- a/crates/hir_ty/src/infer/unify.rs +++ b/crates/hir_ty/src/infer/unify.rs @@ -9,7 +9,7 @@ use test_utils::mark; use super::{InferenceContext, Obligation}; use crate::{ BoundVar, Canonical, DebruijnIndex, GenericPredicate, InEnvironment, InferTy, Scalar, Substs, - Ty, TyKind, TypeCtor, TypeWalk, + Ty, TyKind, TypeWalk, }; impl<'a> InferenceContext<'a> { @@ -257,12 +257,14 @@ impl InferenceTable { // try to resolve type vars first let ty1 = self.resolve_ty_shallow(ty1); let ty2 = self.resolve_ty_shallow(ty2); - match (&*ty1, &*ty2) { - (Ty::Apply(a_ty1), Ty::Apply(a_ty2)) if a_ty1.ctor == a_ty2.ctor => { - self.unify_substs(&a_ty1.parameters, &a_ty2.parameters, depth + 1) + if ty1.equals_ctor(&ty2) { + match (ty1.substs(), ty2.substs()) { + (Some(st1), Some(st2)) => self.unify_substs(st1, st2, depth + 1), + (None, None) => true, + _ => false, } - - _ => self.unify_inner_trivial(&ty1, &ty2, depth), + } else { + self.unify_inner_trivial(&ty1, &ty2, depth) } } @@ -300,24 +302,12 @@ impl InferenceTable { | (other, Ty::Infer(InferTy::TypeVar(tv))) | (Ty::Infer(InferTy::MaybeNeverTypeVar(tv)), other) | (other, Ty::Infer(InferTy::MaybeNeverTypeVar(tv))) - | (Ty::Infer(InferTy::IntVar(tv)), other @ ty_app!(TypeCtor::Scalar(Scalar::Int(_)))) - | (other @ ty_app!(TypeCtor::Scalar(Scalar::Int(_))), Ty::Infer(InferTy::IntVar(tv))) - | ( - Ty::Infer(InferTy::IntVar(tv)), - other @ ty_app!(TypeCtor::Scalar(Scalar::Uint(_))), - ) - | ( - other @ ty_app!(TypeCtor::Scalar(Scalar::Uint(_))), - Ty::Infer(InferTy::IntVar(tv)), - ) - | ( - Ty::Infer(InferTy::FloatVar(tv)), - other @ ty_app!(TypeCtor::Scalar(Scalar::Float(_))), - ) - | ( - other @ ty_app!(TypeCtor::Scalar(Scalar::Float(_))), - Ty::Infer(InferTy::FloatVar(tv)), - ) => { + | (Ty::Infer(InferTy::IntVar(tv)), other @ Ty::Scalar(Scalar::Int(_))) + | (other @ Ty::Scalar(Scalar::Int(_)), Ty::Infer(InferTy::IntVar(tv))) + | (Ty::Infer(InferTy::IntVar(tv)), other @ Ty::Scalar(Scalar::Uint(_))) + | (other @ Ty::Scalar(Scalar::Uint(_)), Ty::Infer(InferTy::IntVar(tv))) + | (Ty::Infer(InferTy::FloatVar(tv)), other @ Ty::Scalar(Scalar::Float(_))) + | (other @ Ty::Scalar(Scalar::Float(_)), Ty::Infer(InferTy::FloatVar(tv))) => { // the type var is unknown since we tried to resolve it self.var_unification_table.union_value(*tv, TypeVarValue::Known(other.clone())); true -- cgit v1.2.3