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/diagnostics/expr.rs | 11 +- crates/hir_ty/src/diagnostics/match_check.rs | 8 +- crates/hir_ty/src/diagnostics/unsafe_check.rs | 6 +- crates/hir_ty/src/display.rs | 164 ++++----- crates/hir_ty/src/infer.rs | 17 +- 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 +- crates/hir_ty/src/lib.rs | 492 +++++++++++--------------- crates/hir_ty/src/lower.rs | 33 +- crates/hir_ty/src/method_resolution.rs | 126 ++++--- crates/hir_ty/src/op.rs | 39 +- crates/hir_ty/src/traits/chalk.rs | 9 +- crates/hir_ty/src/traits/chalk/mapping.rs | 189 +++++----- 15 files changed, 644 insertions(+), 832 deletions(-) (limited to 'crates/hir_ty') diff --git a/crates/hir_ty/src/diagnostics/expr.rs b/crates/hir_ty/src/diagnostics/expr.rs index d740b7265..66a88e2b6 100644 --- a/crates/hir_ty/src/diagnostics/expr.rs +++ b/crates/hir_ty/src/diagnostics/expr.rs @@ -17,7 +17,7 @@ use crate::{ MissingPatFields, RemoveThisSemicolon, }, utils::variant_data, - ApplicationTy, InferenceResult, Ty, TypeCtor, + InferenceResult, Ty, }; pub(crate) use hir_def::{ @@ -381,14 +381,11 @@ impl<'a, 'b> ExprValidator<'a, 'b> { _ => return, }; - let core_result_ctor = TypeCtor::Adt(AdtId::EnumId(core_result_enum)); - let core_option_ctor = TypeCtor::Adt(AdtId::EnumId(core_option_enum)); - - let (params, required) = match &mismatch.expected { - Ty::Apply(ApplicationTy { ctor, parameters }) if ctor == &core_result_ctor => { + let (params, required) = match mismatch.expected { + Ty::Adt(AdtId::EnumId(enum_id), ref parameters) if enum_id == core_result_enum => { (parameters, "Ok".to_string()) } - Ty::Apply(ApplicationTy { ctor, parameters }) if ctor == &core_option_ctor => { + Ty::Adt(AdtId::EnumId(enum_id), ref parameters) if enum_id == core_option_enum => { (parameters, "Some".to_string()) } _ => return, diff --git a/crates/hir_ty/src/diagnostics/match_check.rs b/crates/hir_ty/src/diagnostics/match_check.rs index 1c1423fbf..86fee0050 100644 --- a/crates/hir_ty/src/diagnostics/match_check.rs +++ b/crates/hir_ty/src/diagnostics/match_check.rs @@ -227,7 +227,7 @@ use hir_def::{ use la_arena::Idx; use smallvec::{smallvec, SmallVec}; -use crate::{db::HirDatabase, ApplicationTy, InferenceResult, Ty, TypeCtor}; +use crate::{db::HirDatabase, InferenceResult, Ty}; #[derive(Debug, Clone, Copy)] /// Either a pattern from the source code being analyzed, represented as @@ -627,14 +627,12 @@ pub(super) fn is_useful( // - `!` type // In those cases, no match arm is useful. match cx.infer[cx.match_expr].strip_references() { - Ty::Apply(ApplicationTy { ctor: TypeCtor::Adt(AdtId::EnumId(enum_id)), .. }) => { + Ty::Adt(AdtId::EnumId(enum_id), ..) => { if cx.db.enum_data(*enum_id).variants.is_empty() { return Ok(Usefulness::NotUseful); } } - Ty::Apply(ApplicationTy { ctor: TypeCtor::Never, .. }) => { - return Ok(Usefulness::NotUseful); - } + Ty::Never => return Ok(Usefulness::NotUseful), _ => (), } diff --git a/crates/hir_ty/src/diagnostics/unsafe_check.rs b/crates/hir_ty/src/diagnostics/unsafe_check.rs index 9c506112d..b439915c7 100644 --- a/crates/hir_ty/src/diagnostics/unsafe_check.rs +++ b/crates/hir_ty/src/diagnostics/unsafe_check.rs @@ -11,9 +11,7 @@ use hir_def::{ }; use hir_expand::diagnostics::DiagnosticSink; -use crate::{ - db::HirDatabase, diagnostics::MissingUnsafe, ApplicationTy, InferenceResult, Ty, TypeCtor, -}; +use crate::{db::HirDatabase, diagnostics::MissingUnsafe, InferenceResult, Ty}; pub(super) struct UnsafeValidator<'a, 'b: 'a> { owner: DefWithBodyId, @@ -112,7 +110,7 @@ fn walk_unsafe( } } Expr::UnaryOp { expr, op: UnaryOp::Deref } => { - if let Ty::Apply(ApplicationTy { ctor: TypeCtor::RawPtr(..), .. }) = &infer[*expr] { + if let Ty::RawPtr(..) = &infer[*expr] { unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); } } diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index b4801cb21..1a3b9095a 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs @@ -3,9 +3,8 @@ use std::{borrow::Cow, fmt}; use crate::{ - db::HirDatabase, primitive, utils::generics, ApplicationTy, CallableDefId, FnSig, - GenericPredicate, Lifetime, Obligation, OpaqueTy, OpaqueTyId, ProjectionTy, Scalar, Substs, - TraitRef, Ty, TypeCtor, + db::HirDatabase, primitive, utils::generics, CallableDefId, FnSig, GenericPredicate, Lifetime, + Obligation, OpaqueTy, OpaqueTyId, ProjectionTy, Scalar, Substs, TraitRef, Ty, }; use arrayvec::ArrayVec; use hir_def::{ @@ -235,39 +234,62 @@ impl HirDisplay for &Ty { } } -impl HirDisplay for ApplicationTy { +impl HirDisplay for ProjectionTy { fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { if f.should_truncate() { return write!(f, "{}", TYPE_HINT_TRUNCATION); } - match self.ctor { - TypeCtor::Scalar(Scalar::Bool) => write!(f, "bool")?, - TypeCtor::Scalar(Scalar::Char) => write!(f, "char")?, - TypeCtor::Scalar(Scalar::Float(t)) => { - write!(f, "{}", primitive::float_ty_to_string(t))? - } - TypeCtor::Scalar(Scalar::Int(t)) => write!(f, "{}", primitive::int_ty_to_string(t))?, - TypeCtor::Scalar(Scalar::Uint(t)) => write!(f, "{}", primitive::uint_ty_to_string(t))?, - TypeCtor::Str => write!(f, "str")?, - TypeCtor::Slice => { - let t = self.parameters.as_single(); + let trait_ = f.db.trait_data(self.trait_(f.db)); + let first_parameter = self.parameters[0].into_displayable( + f.db, + f.max_size, + f.omit_verbose_types, + f.display_target, + ); + write!(f, "<{} as {}", first_parameter, trait_.name)?; + if self.parameters.len() > 1 { + write!(f, "<")?; + f.write_joined(&self.parameters[1..], ", ")?; + write!(f, ">")?; + } + write!(f, ">::{}", f.db.type_alias_data(self.associated_ty).name)?; + Ok(()) + } +} + +impl HirDisplay for Ty { + fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { + if f.should_truncate() { + return write!(f, "{}", TYPE_HINT_TRUNCATION); + } + + match self { + Ty::Never => write!(f, "!")?, + Ty::Str => write!(f, "str")?, + Ty::Scalar(Scalar::Bool) => write!(f, "bool")?, + Ty::Scalar(Scalar::Char) => write!(f, "char")?, + &Ty::Scalar(Scalar::Float(t)) => write!(f, "{}", primitive::float_ty_to_string(t))?, + &Ty::Scalar(Scalar::Int(t)) => write!(f, "{}", primitive::int_ty_to_string(t))?, + &Ty::Scalar(Scalar::Uint(t)) => write!(f, "{}", primitive::uint_ty_to_string(t))?, + Ty::Slice(parameters) => { + let t = parameters.as_single(); write!(f, "[")?; t.hir_fmt(f)?; write!(f, "]")?; } - TypeCtor::Array => { - let t = self.parameters.as_single(); + Ty::Array(parameters) => { + let t = parameters.as_single(); write!(f, "[")?; t.hir_fmt(f)?; write!(f, "; _]")?; } - TypeCtor::RawPtr(m) | TypeCtor::Ref(m) => { - let t = self.parameters.as_single(); + Ty::RawPtr(m, parameters) | Ty::Ref(m, parameters) => { + let t = parameters.as_single(); let ty_display = t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target); - if matches!(self.ctor, TypeCtor::RawPtr(_)) { + if matches!(self, Ty::RawPtr(..)) { write!(f, "*{}", m.as_keyword_for_ptr())?; } else { write!(f, "&{}", m.as_keyword_for_ref())?; @@ -308,25 +330,23 @@ impl HirDisplay for ApplicationTy { write!(f, "{}", ty_display)?; } } - TypeCtor::Never => write!(f, "!")?, - TypeCtor::Tuple { .. } => { - let ts = &self.parameters; - if ts.len() == 1 { + Ty::Tuple { substs, .. } => { + if substs.len() == 1 { write!(f, "(")?; - ts[0].hir_fmt(f)?; + substs[0].hir_fmt(f)?; write!(f, ",)")?; } else { write!(f, "(")?; - f.write_joined(&*ts.0, ", ")?; + f.write_joined(&*substs.0, ", ")?; write!(f, ")")?; } } - TypeCtor::FnPtr { is_varargs, .. } => { - let sig = FnSig::from_fn_ptr_substs(&self.parameters, is_varargs); + &Ty::FnPtr { is_varargs, ref substs, .. } => { + let sig = FnSig::from_fn_ptr_substs(&substs, is_varargs); sig.hir_fmt(f)?; } - TypeCtor::FnDef(def) => { - let sig = f.db.callable_item_signature(def).subst(&self.parameters); + &Ty::FnDef(def, ref parameters) => { + let sig = f.db.callable_item_signature(def).subst(parameters); match def { CallableDefId::FunctionId(ff) => { write!(f, "fn {}", f.db.function_data(ff).name)? @@ -336,7 +356,7 @@ impl HirDisplay for ApplicationTy { write!(f, "{}", f.db.enum_data(e.parent).variants[e.local_id].name)? } }; - if self.parameters.len() > 0 { + if parameters.len() > 0 { let generics = generics(f.db.upcast(), def.into()); let (parent_params, self_param, type_params, _impl_trait_params) = generics.provenance_split(); @@ -344,7 +364,7 @@ impl HirDisplay for ApplicationTy { // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self? if total_len > 0 { write!(f, "<")?; - f.write_joined(&self.parameters.0[..total_len], ", ")?; + f.write_joined(¶meters.0[..total_len], ", ")?; write!(f, ">")?; } } @@ -363,7 +383,7 @@ impl HirDisplay for ApplicationTy { write!(f, " -> {}", ret_display)?; } } - TypeCtor::Adt(def_id) => { + &Ty::Adt(def_id, ref parameters) => { match f.display_target { DisplayTarget::Diagnostics | DisplayTarget::Test => { let name = match def_id { @@ -388,19 +408,18 @@ impl HirDisplay for ApplicationTy { } } - if self.parameters.len() > 0 { + if parameters.len() > 0 { let parameters_to_write = if f.display_target.is_source_code() || f.omit_verbose_types() { match self - .ctor .as_generic_def() .map(|generic_def_id| f.db.generic_defaults(generic_def_id)) .filter(|defaults| !defaults.is_empty()) { - None => self.parameters.0.as_ref(), + None => parameters.0.as_ref(), Some(default_parameters) => { let mut default_from = 0; - for (i, parameter) in self.parameters.iter().enumerate() { + for (i, parameter) in parameters.iter().enumerate() { match (parameter, default_parameters.get(i)) { (&Ty::Unknown, _) | (_, None) => { default_from = i + 1; @@ -408,18 +427,18 @@ impl HirDisplay for ApplicationTy { (_, Some(default_parameter)) => { let actual_default = default_parameter .clone() - .subst(&self.parameters.prefix(i)); + .subst(¶meters.prefix(i)); if parameter != &actual_default { default_from = i + 1; } } } } - &self.parameters.0[0..default_from] + ¶meters.0[0..default_from] } } } else { - self.parameters.0.as_ref() + parameters.0.as_ref() }; if !parameters_to_write.is_empty() { write!(f, "<")?; @@ -428,7 +447,7 @@ impl HirDisplay for ApplicationTy { } } } - TypeCtor::AssociatedType(type_alias) => { + &Ty::AssociatedType(type_alias, ref parameters) => { let trait_ = match type_alias.lookup(f.db.upcast()).container { AssocContainerId::TraitId(it) => it, _ => panic!("not an associated type"), @@ -439,30 +458,28 @@ impl HirDisplay for ApplicationTy { // Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types) if f.display_target.is_test() { write!(f, "{}::{}", trait_.name, type_alias_data.name)?; - if self.parameters.len() > 0 { + if parameters.len() > 0 { write!(f, "<")?; - f.write_joined(&*self.parameters.0, ", ")?; + f.write_joined(&*parameters.0, ", ")?; write!(f, ">")?; } } else { - let projection_ty = ProjectionTy { - associated_ty: type_alias, - parameters: self.parameters.clone(), - }; + let projection_ty = + ProjectionTy { associated_ty: type_alias, parameters: parameters.clone() }; projection_ty.hir_fmt(f)?; } } - TypeCtor::ForeignType(type_alias) => { + &Ty::ForeignType(type_alias, ref parameters) => { let type_alias = f.db.type_alias_data(type_alias); write!(f, "{}", type_alias.name)?; - if self.parameters.len() > 0 { + if parameters.len() > 0 { write!(f, "<")?; - f.write_joined(&*self.parameters.0, ", ")?; + f.write_joined(&*parameters.0, ", ")?; write!(f, ">")?; } } - TypeCtor::OpaqueType(opaque_ty_id) => { + &Ty::OpaqueType(opaque_ty_id, ref parameters) => { match opaque_ty_id { OpaqueTyId::ReturnTypeImplTrait(func, idx) => { let datas = @@ -470,19 +487,19 @@ impl HirDisplay for ApplicationTy { let data = (*datas) .as_ref() .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); - let bounds = data.subst(&self.parameters); + let bounds = data.subst(¶meters); write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?; // FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution } OpaqueTyId::AsyncBlockTypeImplTrait(..) => { write!(f, "impl Future")?; } } } - TypeCtor::Closure { .. } => { - let sig = self.parameters[0].callable_sig(f.db); + Ty::Closure { substs, .. } => { + let sig = substs[0].callable_sig(f.db); if let Some(sig) = sig { if sig.params().is_empty() { write!(f, "||")?; @@ -505,43 +522,6 @@ impl HirDisplay for ApplicationTy { write!(f, "{{closure}}")?; } } - } - Ok(()) - } -} - -impl HirDisplay for ProjectionTy { - fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { - if f.should_truncate() { - return write!(f, "{}", TYPE_HINT_TRUNCATION); - } - - let trait_ = f.db.trait_data(self.trait_(f.db)); - let first_parameter = self.parameters[0].into_displayable( - f.db, - f.max_size, - f.omit_verbose_types, - f.display_target, - ); - write!(f, "<{} as {}", first_parameter, trait_.name)?; - if self.parameters.len() > 1 { - write!(f, "<")?; - f.write_joined(&self.parameters[1..], ", ")?; - write!(f, ">")?; - } - write!(f, ">::{}", f.db.type_alias_data(self.associated_ty).name)?; - Ok(()) - } -} - -impl HirDisplay for Ty { - fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { - if f.should_truncate() { - return write!(f, "{}", TYPE_HINT_TRUNCATION); - } - - match self { - Ty::Apply(a_ty) => a_ty.hir_fmt(f)?, Ty::Projection(p_ty) => p_ty.hir_fmt(f)?, Ty::Placeholder(id) => { let generics = generics(f.db.upcast(), id.parent); diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index 657f011d2..a1769729f 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs @@ -38,7 +38,7 @@ use syntax::SmolStr; use super::{ primitive::{FloatTy, IntTy}, traits::{Guidance, Obligation, ProjectionPredicate, Solution}, - InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk, + InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeWalk, }; use crate::{ db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, Scalar, @@ -46,15 +46,6 @@ use crate::{ pub(crate) use unify::unify; -macro_rules! ty_app { - ($ctor:pat, $param:pat) => { - crate::Ty::Apply(crate::ApplicationTy { ctor: $ctor, parameters: $param }) - }; - ($ctor:pat) => { - ty_app!($ctor, _) - }; -} - mod unify; mod path; mod expr; @@ -684,9 +675,9 @@ impl InferTy { fn fallback_value(self) -> Ty { match self { InferTy::TypeVar(..) => Ty::Unknown, - InferTy::IntVar(..) => Ty::simple(TypeCtor::Scalar(Scalar::Int(IntTy::I32))), - InferTy::FloatVar(..) => Ty::simple(TypeCtor::Scalar(Scalar::Float(FloatTy::F64))), - InferTy::MaybeNeverTypeVar(..) => Ty::simple(TypeCtor::Never), + InferTy::IntVar(..) => Ty::Scalar(Scalar::Int(IntTy::I32)), + InferTy::FloatVar(..) => Ty::Scalar(Scalar::Float(FloatTy::F64)), + InferTy::MaybeNeverTypeVar(..) => Ty::Never, } } } 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 diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index 676519594..5cbb9a3cc 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs @@ -25,7 +25,7 @@ mod test_db; use std::{iter, mem, ops::Deref, sync::Arc}; -use base_db::{salsa, CrateId}; +use base_db::salsa; use hir_def::{ builtin_type::BuiltinType, expr::ExprId, @@ -57,192 +57,6 @@ pub enum Lifetime { Static, } -/// A type constructor or type name: this might be something like the primitive -/// type `bool`, a struct like `Vec`, or things like function pointers or -/// tuples. -#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] -pub enum TypeCtor { - /// a scalar type like `bool` or `u32` - Scalar(Scalar), - - /// Structures, enumerations and unions. - Adt(AdtId), - - /// The pointee of a string slice. Written as `str`. - Str, - - /// The pointee of an array slice. Written as `[T]`. - Slice, - - /// An array with the given length. Written as `[T; n]`. - Array, - - /// A raw pointer. Written as `*mut T` or `*const T` - RawPtr(Mutability), - - /// A reference; a pointer with an associated lifetime. Written as - /// `&'a mut T` or `&'a T`. - Ref(Mutability), - - /// The anonymous type of a function declaration/definition. Each - /// function has a unique type, which is output (for a function - /// named `foo` returning an `i32`) as `fn() -> i32 {foo}`. - /// - /// This includes tuple struct / enum variant constructors as well. - /// - /// For example the type of `bar` here: - /// - /// ``` - /// fn foo() -> i32 { 1 } - /// let bar = foo; // bar: fn() -> i32 {foo} - /// ``` - FnDef(CallableDefId), - - /// A pointer to a function. Written as `fn() -> i32`. - /// - /// For example the type of `bar` here: - /// - /// ``` - /// fn foo() -> i32 { 1 } - /// let bar: fn() -> i32 = foo; - /// ``` - // FIXME make this a Ty variant like in Chalk - FnPtr { num_args: u16, is_varargs: bool }, - - /// The never type `!`. - Never, - - /// A tuple type. For example, `(i32, bool)`. - Tuple { cardinality: u16 }, - - /// Represents an associated item like `Iterator::Item`. This is used - /// when we have tried to normalize a projection like `T::Item` but - /// couldn't find a better representation. In that case, we generate - /// an **application type** like `(Iterator::Item)`. - AssociatedType(TypeAliasId), - - /// This represents a placeholder for an opaque type in situations where we - /// don't know the hidden type (i.e. currently almost always). This is - /// analogous to the `AssociatedType` type constructor. - /// It is also used as the type of async block, with one type parameter - /// representing the Future::Output type. - OpaqueType(OpaqueTyId), - - /// Represents a foreign type declared in external blocks. - ForeignType(TypeAliasId), - - /// The type of a specific closure. - /// - /// The closure signature is stored in a `FnPtr` type in the first type - /// parameter. - Closure { def: DefWithBodyId, expr: ExprId }, -} - -impl TypeCtor { - pub fn num_ty_params(self, db: &dyn HirDatabase) -> usize { - match self { - TypeCtor::Scalar(_) - | TypeCtor::Str - | TypeCtor::Never => 0, - TypeCtor::Slice - | TypeCtor::Array - | TypeCtor::RawPtr(_) - | TypeCtor::Ref(_) - | TypeCtor::Closure { .. } // 1 param representing the signature of the closure - => 1, - TypeCtor::Adt(adt) => { - let generic_params = generics(db.upcast(), adt.into()); - generic_params.len() - } - TypeCtor::FnDef(callable) => { - let generic_params = generics(db.upcast(), callable.into()); - generic_params.len() - } - TypeCtor::AssociatedType(type_alias) => { - let generic_params = generics(db.upcast(), type_alias.into()); - generic_params.len() - } - TypeCtor::ForeignType(type_alias) => { - let generic_params = generics(db.upcast(), type_alias.into()); - generic_params.len() - } - TypeCtor::OpaqueType(opaque_ty_id) => { - match opaque_ty_id { - OpaqueTyId::ReturnTypeImplTrait(func, _) => { - let generic_params = generics(db.upcast(), func.into()); - generic_params.len() - } - // 1 param representing Future::Output type. - OpaqueTyId::AsyncBlockTypeImplTrait(..) => 1, - } - } - TypeCtor::FnPtr { num_args, is_varargs: _ } => num_args as usize + 1, - TypeCtor::Tuple { cardinality } => cardinality as usize, - } - } - - pub fn krate(self, db: &dyn HirDatabase) -> Option { - match self { - TypeCtor::Scalar(_) - | TypeCtor::Str - | TypeCtor::Never - | TypeCtor::Slice - | TypeCtor::Array - | TypeCtor::RawPtr(_) - | TypeCtor::Ref(_) - | TypeCtor::FnPtr { .. } - | TypeCtor::Tuple { .. } => None, - // Closure's krate is irrelevant for coherence I would think? - TypeCtor::Closure { .. } => None, - TypeCtor::Adt(adt) => Some(adt.module(db.upcast()).krate()), - TypeCtor::FnDef(callable) => Some(callable.krate(db)), - TypeCtor::AssociatedType(type_alias) => { - Some(type_alias.lookup(db.upcast()).module(db.upcast()).krate()) - } - TypeCtor::ForeignType(type_alias) => { - Some(type_alias.lookup(db.upcast()).module(db.upcast()).krate()) - } - TypeCtor::OpaqueType(opaque_ty_id) => match opaque_ty_id { - OpaqueTyId::ReturnTypeImplTrait(func, _) => { - Some(func.lookup(db.upcast()).module(db.upcast()).krate()) - } - OpaqueTyId::AsyncBlockTypeImplTrait(def, _) => { - Some(def.module(db.upcast()).krate()) - } - }, - } - } - - pub fn as_generic_def(self) -> Option { - match self { - TypeCtor::Scalar(_) - | TypeCtor::Str - | TypeCtor::Never - | TypeCtor::Slice - | TypeCtor::Array - | TypeCtor::RawPtr(_) - | TypeCtor::Ref(_) - | TypeCtor::FnPtr { .. } - | TypeCtor::Tuple { .. } - | TypeCtor::Closure { .. } => None, - TypeCtor::Adt(adt) => Some(adt.into()), - TypeCtor::FnDef(callable) => Some(callable.into()), - TypeCtor::AssociatedType(type_alias) => Some(type_alias.into()), - TypeCtor::ForeignType(type_alias) => Some(type_alias.into()), - TypeCtor::OpaqueType(_impl_trait_id) => None, - } - } -} - -/// A nominal type with (maybe 0) type parameters. This might be a primitive -/// type like `bool`, a struct, tuple, function pointer, reference or -/// several other things. -#[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub struct ApplicationTy { - pub ctor: TypeCtor, - pub parameters: Substs, -} - #[derive(Clone, PartialEq, Eq, Debug, Hash)] pub struct OpaqueTy { pub opaque_ty_id: OpaqueTyId, @@ -293,10 +107,80 @@ impl TypeWalk for ProjectionTy { /// This should be cheap to clone. #[derive(Clone, PartialEq, Eq, Debug, Hash)] pub enum Ty { - /// A nominal type with (maybe 0) type parameters. This might be a primitive - /// type like `bool`, a struct, tuple, function pointer, reference or - /// several other things. - Apply(ApplicationTy), + /// Structures, enumerations and unions. + Adt(AdtId, Substs), + + /// Represents an associated item like `Iterator::Item`. This is used + /// when we have tried to normalize a projection like `T::Item` but + /// couldn't find a better representation. In that case, we generate + /// an **application type** like `(Iterator::Item)`. + AssociatedType(TypeAliasId, Substs), + + /// a scalar type like `bool` or `u32` + Scalar(Scalar), + + /// A tuple type. For example, `(i32, bool)`. + Tuple { cardinality: u16, substs: Substs }, + + /// An array with the given length. Written as `[T; n]`. + Array(Substs), + + /// The pointee of an array slice. Written as `[T]`. + Slice(Substs), + + /// A raw pointer. Written as `*mut T` or `*const T` + RawPtr(Mutability, Substs), + + /// A reference; a pointer with an associated lifetime. Written as + /// `&'a mut T` or `&'a T`. + Ref(Mutability, Substs), + + /// This represents a placeholder for an opaque type in situations where we + /// don't know the hidden type (i.e. currently almost always). This is + /// analogous to the `AssociatedType` type constructor. + /// It is also used as the type of async block, with one type parameter + /// representing the Future::Output type. + OpaqueType(OpaqueTyId, Substs), + + /// The anonymous type of a function declaration/definition. Each + /// function has a unique type, which is output (for a function + /// named `foo` returning an `i32`) as `fn() -> i32 {foo}`. + /// + /// This includes tuple struct / enum variant constructors as well. + /// + /// For example the type of `bar` here: + /// + /// ``` + /// fn foo() -> i32 { 1 } + /// let bar = foo; // bar: fn() -> i32 {foo} + /// ``` + FnDef(CallableDefId, Substs), + + /// The pointee of a string slice. Written as `str`. + Str, + + /// The never type `!`. + Never, + + /// The type of a specific closure. + /// + /// The closure signature is stored in a `FnPtr` type in the first type + /// parameter. + Closure { def: DefWithBodyId, expr: ExprId, substs: Substs }, + + /// Represents a foreign type declared in external blocks. + ForeignType(TypeAliasId, Substs), + + /// A pointer to a function. Written as `fn() -> i32`. + /// + /// For example the type of `bar` here: + /// + /// ``` + /// fn foo() -> i32 { 1 } + /// let bar: fn() -> i32 = foo; + /// ``` + // FIXME make this a Ty variant like in Chalk + FnPtr { num_args: u16, is_varargs: bool, substs: Substs }, /// A "projection" type corresponds to an (unnormalized) /// projection like `>::Foo`. Note that the @@ -420,10 +304,6 @@ impl Substs { Substs::builder(generic_params.len()) } - pub fn build_for_type_ctor(db: &dyn HirDatabase, type_ctor: TypeCtor) -> SubstsBuilder { - Substs::builder(type_ctor.num_ty_params(db)) - } - fn builder(param_count: usize) -> SubstsBuilder { SubstsBuilder { vec: Vec::with_capacity(param_count), param_count } } @@ -701,54 +581,42 @@ impl TypeWalk for FnSig { } impl Ty { - pub fn simple(ctor: TypeCtor) -> Ty { - Ty::Apply(ApplicationTy { ctor, parameters: Substs::empty() }) - } - pub fn apply_one(ctor: TypeCtor, param: Ty) -> Ty { - Ty::Apply(ApplicationTy { ctor, parameters: Substs::single(param) }) - } - pub fn apply(ctor: TypeCtor, parameters: Substs) -> Ty { - Ty::Apply(ApplicationTy { ctor, parameters }) - } pub fn unit() -> Self { - Ty::apply(TypeCtor::Tuple { cardinality: 0 }, Substs::empty()) + Ty::Tuple { cardinality: 0, substs: Substs::empty() } } + pub fn fn_ptr(sig: FnSig) -> Self { - Ty::apply( - TypeCtor::FnPtr { num_args: sig.params().len() as u16, is_varargs: sig.is_varargs }, - Substs(sig.params_and_return), - ) + Ty::FnPtr { + num_args: sig.params().len() as u16, + is_varargs: sig.is_varargs, + substs: Substs(sig.params_and_return), + } } + pub fn builtin(builtin: BuiltinType) -> Self { - Ty::simple(match builtin { - BuiltinType::Char => TypeCtor::Scalar(Scalar::Char), - BuiltinType::Bool => TypeCtor::Scalar(Scalar::Bool), - BuiltinType::Str => TypeCtor::Str, - BuiltinType::Int(t) => TypeCtor::Scalar(Scalar::Int(primitive::int_ty_from_builtin(t))), - BuiltinType::Uint(t) => { - TypeCtor::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(t))) - } - BuiltinType::Float(t) => { - TypeCtor::Scalar(Scalar::Float(primitive::float_ty_from_builtin(t))) - } - }) + match builtin { + BuiltinType::Char => Ty::Scalar(Scalar::Char), + BuiltinType::Bool => Ty::Scalar(Scalar::Bool), + BuiltinType::Str => Ty::Str, + BuiltinType::Int(t) => Ty::Scalar(Scalar::Int(primitive::int_ty_from_builtin(t))), + BuiltinType::Uint(t) => Ty::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(t))), + BuiltinType::Float(t) => Ty::Scalar(Scalar::Float(primitive::float_ty_from_builtin(t))), + } } pub fn as_reference(&self) -> Option<(&Ty, Mutability)> { match self { - Ty::Apply(ApplicationTy { ctor: TypeCtor::Ref(mutability), parameters }) => { - Some((parameters.as_single(), *mutability)) - } + Ty::Ref(mutability, parameters) => Some((parameters.as_single(), *mutability)), _ => None, } } pub fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)> { match self { - Ty::Apply(ApplicationTy { ctor: TypeCtor::Ref(mutability), parameters }) => { + Ty::Ref(mutability, parameters) => { Some((parameters.as_single(), Rawness::Ref, *mutability)) } - Ty::Apply(ApplicationTy { ctor: TypeCtor::RawPtr(mutability), parameters }) => { + Ty::RawPtr(mutability, parameters) => { Some((parameters.as_single(), Rawness::RawPtr, *mutability)) } _ => None, @@ -758,7 +626,7 @@ impl Ty { pub fn strip_references(&self) -> &Ty { let mut t: &Ty = self; - while let Ty::Apply(ApplicationTy { ctor: TypeCtor::Ref(_mutability), parameters }) = t { + while let Ty::Ref(_mutability, parameters) = t { t = parameters.as_single(); } @@ -767,30 +635,64 @@ impl Ty { pub fn as_adt(&self) -> Option<(AdtId, &Substs)> { match self { - Ty::Apply(ApplicationTy { ctor: TypeCtor::Adt(adt_def), parameters }) => { - Some((*adt_def, parameters)) - } + Ty::Adt(adt_def, parameters) => Some((*adt_def, parameters)), _ => None, } } pub fn as_tuple(&self) -> Option<&Substs> { match self { - Ty::Apply(ApplicationTy { ctor: TypeCtor::Tuple { .. }, parameters }) => { - Some(parameters) - } + Ty::Tuple { substs: parameters, .. } => Some(parameters), + _ => None, + } + } + + pub fn as_generic_def(&self) -> Option { + match *self { + Ty::Adt(adt, ..) => Some(adt.into()), + Ty::FnDef(callable, ..) => Some(callable.into()), + Ty::AssociatedType(type_alias, ..) => Some(type_alias.into()), + Ty::ForeignType(type_alias, ..) => Some(type_alias.into()), _ => None, } } pub fn is_never(&self) -> bool { - matches!(self, Ty::Apply(ApplicationTy { ctor: TypeCtor::Never, .. })) + matches!(self, Ty::Never) } pub fn is_unknown(&self) -> bool { matches!(self, Ty::Unknown) } + pub fn equals_ctor(&self, other: &Ty) -> bool { + match (self, other) { + (Ty::Adt(adt, ..), Ty::Adt(adt2, ..)) => adt == adt2, + (Ty::Slice(_), Ty::Slice(_)) | (Ty::Array(_), Ty::Array(_)) => true, + (Ty::FnDef(def_id, ..), Ty::FnDef(def_id2, ..)) => def_id == def_id2, + (Ty::OpaqueType(ty_id, ..), Ty::OpaqueType(ty_id2, ..)) => ty_id == ty_id2, + (Ty::AssociatedType(ty_id, ..), Ty::AssociatedType(ty_id2, ..)) + | (Ty::ForeignType(ty_id, ..), Ty::ForeignType(ty_id2, ..)) => ty_id == ty_id2, + (Ty::Closure { def, expr, .. }, Ty::Closure { def: def2, expr: expr2, .. }) => { + expr == expr2 && def == def2 + } + (Ty::Ref(mutability, ..), Ty::Ref(mutability2, ..)) + | (Ty::RawPtr(mutability, ..), Ty::RawPtr(mutability2, ..)) => { + mutability == mutability2 + } + ( + Ty::FnPtr { num_args, is_varargs, .. }, + Ty::FnPtr { num_args: num_args2, is_varargs: is_varargs2, .. }, + ) => num_args == num_args2 && is_varargs == is_varargs2, + (Ty::Tuple { cardinality, .. }, Ty::Tuple { cardinality: cardinality2, .. }) => { + cardinality == cardinality2 + } + (Ty::Str, Ty::Str) | (Ty::Never, Ty::Never) => true, + (Ty::Scalar(scalar), Ty::Scalar(scalar2)) => scalar == scalar2, + _ => false, + } + } + /// If this is a `dyn Trait` type, this returns the `Trait` part. pub fn dyn_trait_ref(&self) -> Option<&TraitRef> { match self { @@ -809,41 +711,32 @@ impl Ty { fn builtin_deref(&self) -> Option { match self { - Ty::Apply(a_ty) => match a_ty.ctor { - TypeCtor::Ref(..) => Some(Ty::clone(a_ty.parameters.as_single())), - TypeCtor::RawPtr(..) => Some(Ty::clone(a_ty.parameters.as_single())), - _ => None, - }, + Ty::Ref(.., parameters) => Some(Ty::clone(parameters.as_single())), + Ty::RawPtr(.., parameters) => Some(Ty::clone(parameters.as_single())), _ => None, } } pub fn as_fn_def(&self) -> Option { match self { - &Ty::Apply(ApplicationTy { - ctor: TypeCtor::FnDef(CallableDefId::FunctionId(func)), - .. - }) => Some(func), + &Ty::FnDef(CallableDefId::FunctionId(func), ..) => Some(func), _ => None, } } pub fn callable_sig(&self, db: &dyn HirDatabase) -> Option { match self { - Ty::Apply(a_ty) => match a_ty.ctor { - TypeCtor::FnPtr { is_varargs, .. } => { - Some(FnSig::from_fn_ptr_substs(&a_ty.parameters, is_varargs)) - } - TypeCtor::FnDef(def) => { - let sig = db.callable_item_signature(def); - Some(sig.subst(&a_ty.parameters)) - } - TypeCtor::Closure { .. } => { - let sig_param = &a_ty.parameters[0]; - sig_param.callable_sig(db) - } - _ => None, - }, + &Ty::FnPtr { is_varargs, substs: ref parameters, .. } => { + Some(FnSig::from_fn_ptr_substs(¶meters, is_varargs)) + } + &Ty::FnDef(def, ref parameters) => { + let sig = db.callable_item_signature(def); + Some(sig.subst(¶meters)) + } + Ty::Closure { substs: parameters, .. } => { + let sig_param = ¶meters[0]; + sig_param.callable_sig(db) + } _ => None, } } @@ -852,28 +745,71 @@ impl Ty { /// the `Substs` for these type parameters with the given ones. (So e.g. if /// `self` is `Option<_>` and the substs contain `u32`, we'll have /// `Option` afterwards.) - pub fn apply_substs(self, substs: Substs) -> Ty { - match self { - Ty::Apply(ApplicationTy { ctor, parameters: previous_substs }) => { - assert_eq!(previous_substs.len(), substs.len()); - Ty::Apply(ApplicationTy { ctor, parameters: substs }) + pub fn apply_substs(mut self, new_substs: Substs) -> Ty { + match &mut self { + Ty::Adt(_, substs) + | Ty::Slice(substs) + | Ty::Array(substs) + | Ty::RawPtr(_, substs) + | Ty::Ref(_, substs) + | Ty::FnDef(_, substs) + | Ty::FnPtr { substs, .. } + | Ty::Tuple { substs, .. } + | Ty::OpaqueType(_, substs) + | Ty::AssociatedType(_, substs) + | Ty::ForeignType(_, substs) + | Ty::Closure { substs, .. } => { + assert_eq!(substs.len(), new_substs.len()); + *substs = new_substs; } - _ => self, + _ => (), } + self } /// Returns the type parameters of this type if it has some (i.e. is an ADT /// or function); so if `self` is `Option`, this returns the `u32`. - pub fn substs(&self) -> Option { + pub fn substs(&self) -> Option<&Substs> { + match self { + Ty::Adt(_, substs) + | Ty::Slice(substs) + | Ty::Array(substs) + | Ty::RawPtr(_, substs) + | Ty::Ref(_, substs) + | Ty::FnDef(_, substs) + | Ty::FnPtr { substs, .. } + | Ty::Tuple { substs, .. } + | Ty::OpaqueType(_, substs) + | Ty::AssociatedType(_, substs) + | Ty::ForeignType(_, substs) + | Ty::Closure { substs, .. } => Some(substs), + + _ => None, + } + } + + pub fn substs_mut(&mut self) -> Option<&mut Substs> { match self { - Ty::Apply(ApplicationTy { parameters, .. }) => Some(parameters.clone()), + Ty::Adt(_, substs) + | Ty::Slice(substs) + | Ty::Array(substs) + | Ty::RawPtr(_, substs) + | Ty::Ref(_, substs) + | Ty::FnDef(_, substs) + | Ty::FnPtr { substs, .. } + | Ty::Tuple { substs, .. } + | Ty::OpaqueType(_, substs) + | Ty::AssociatedType(_, substs) + | Ty::ForeignType(_, substs) + | Ty::Closure { substs, .. } => Some(substs), + _ => None, } } pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option> { match self { - Ty::Apply(ApplicationTy { ctor: TypeCtor::OpaqueType(opaque_ty_id), .. }) => { + Ty::OpaqueType(opaque_ty_id, ..) => { match opaque_ty_id { OpaqueTyId::AsyncBlockTypeImplTrait(def, _expr) => { let krate = def.module(db.upcast()).krate(); @@ -934,7 +870,7 @@ impl Ty { pub fn associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option { match self { - Ty::Apply(ApplicationTy { ctor: TypeCtor::AssociatedType(type_alias_id), .. }) => { + Ty::AssociatedType(type_alias_id, ..) => { match type_alias_id.lookup(db.upcast()).container { AssocContainerId::TraitId(trait_id) => Some(trait_id), _ => None, @@ -1049,11 +985,6 @@ pub trait TypeWalk { impl TypeWalk for Ty { fn walk(&self, f: &mut impl FnMut(&Ty)) { match self { - Ty::Apply(a_ty) => { - for t in a_ty.parameters.iter() { - t.walk(f); - } - } Ty::Projection(p_ty) => { for t in p_ty.parameters.iter() { t.walk(f); @@ -1069,7 +1000,13 @@ impl TypeWalk for Ty { t.walk(f); } } - Ty::Placeholder { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} + _ => { + if let Some(substs) = self.substs() { + for t in substs.iter() { + t.walk(f); + } + } + } } f(self); } @@ -1080,9 +1017,6 @@ impl TypeWalk for Ty { binders: DebruijnIndex, ) { match self { - Ty::Apply(a_ty) => { - a_ty.parameters.walk_mut_binders(f, binders); - } Ty::Projection(p_ty) => { p_ty.parameters.walk_mut_binders(f, binders); } @@ -1094,7 +1028,11 @@ impl TypeWalk for Ty { Ty::Opaque(o_ty) => { o_ty.parameters.walk_mut_binders(f, binders); } - Ty::Placeholder { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} + _ => { + if let Some(substs) = self.substs_mut() { + substs.walk_mut_binders(f, binders); + } + } } f(self, binders); } diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index 99b0ecf3b..6b919a09e 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs @@ -33,7 +33,7 @@ use crate::{ }, Binders, BoundVar, DebruijnIndex, FnSig, GenericPredicate, OpaqueTy, OpaqueTyId, PolyFnSig, ProjectionPredicate, ProjectionTy, ReturnTypeImplTrait, ReturnTypeImplTraits, Substs, - TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk, + TraitEnvironment, TraitRef, Ty, TypeWalk, }; #[derive(Debug)] @@ -145,13 +145,10 @@ impl Ty { pub fn from_hir_ext(ctx: &TyLoweringContext<'_>, type_ref: &TypeRef) -> (Self, Option) { let mut res = None; let ty = match type_ref { - TypeRef::Never => Ty::simple(TypeCtor::Never), + TypeRef::Never => Ty::Never, TypeRef::Tuple(inner) => { let inner_tys: Arc<[Ty]> = inner.iter().map(|tr| Ty::from_hir(ctx, tr)).collect(); - Ty::apply( - TypeCtor::Tuple { cardinality: inner_tys.len() as u16 }, - Substs(inner_tys), - ) + Ty::Tuple { cardinality: inner_tys.len() as u16, substs: Substs(inner_tys) } } TypeRef::Path(path) => { let (ty, res_) = Ty::from_hir_path(ctx, path); @@ -160,27 +157,24 @@ impl Ty { } TypeRef::RawPtr(inner, mutability) => { let inner_ty = Ty::from_hir(ctx, inner); - Ty::apply_one(TypeCtor::RawPtr(*mutability), inner_ty) + Ty::RawPtr(*mutability, Substs::single(inner_ty)) } TypeRef::Array(inner) => { let inner_ty = Ty::from_hir(ctx, inner); - Ty::apply_one(TypeCtor::Array, inner_ty) + Ty::Array(Substs::single(inner_ty)) } TypeRef::Slice(inner) => { let inner_ty = Ty::from_hir(ctx, inner); - Ty::apply_one(TypeCtor::Slice, inner_ty) + Ty::Slice(Substs::single(inner_ty)) } TypeRef::Reference(inner, _, mutability) => { let inner_ty = Ty::from_hir(ctx, inner); - Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty) + Ty::Ref(*mutability, Substs::single(inner_ty)) } TypeRef::Placeholder => Ty::Unknown, TypeRef::Fn(params, is_varargs) => { let sig = Substs(params.iter().map(|tr| Ty::from_hir(ctx, tr)).collect()); - Ty::apply( - TypeCtor::FnPtr { num_args: sig.len() as u16 - 1, is_varargs: *is_varargs }, - sig, - ) + Ty::FnPtr { num_args: sig.len() as u16 - 1, is_varargs: *is_varargs, substs: sig } } TypeRef::DynTrait(bounds) => { let self_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)); @@ -414,7 +408,6 @@ impl Ty { // FIXME: report error TypeNs::EnumVariantId(_) => return (Ty::Unknown, None), }; - Ty::from_type_relative_path(ctx, ty, Some(resolution), remaining_segments) } @@ -1025,7 +1018,7 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig { fn type_for_fn(db: &dyn HirDatabase, def: FunctionId) -> Binders { let generics = generics(db.upcast(), def.into()); let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST); - Binders::new(substs.len(), Ty::apply(TypeCtor::FnDef(def.into()), substs)) + Binders::new(substs.len(), Ty::FnDef(def.into(), substs)) } /// Build the declared type of a const. @@ -1068,7 +1061,7 @@ fn type_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> Binders PolyFnSig { @@ -1093,13 +1086,13 @@ fn type_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) - } let generics = generics(db.upcast(), def.parent.into()); let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST); - Binders::new(substs.len(), Ty::apply(TypeCtor::FnDef(def.into()), substs)) + Binders::new(substs.len(), Ty::FnDef(def.into(), substs)) } fn type_for_adt(db: &dyn HirDatabase, adt: AdtId) -> Binders { let generics = generics(db.upcast(), adt.into()); let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST); - Binders::new(substs.len(), Ty::apply(TypeCtor::Adt(adt), substs)) + Binders::new(substs.len(), Ty::Adt(adt, substs)) } fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders { @@ -1109,7 +1102,7 @@ fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders { TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST); if db.type_alias_data(t).is_extern { - Binders::new(substs.len(), Ty::apply(TypeCtor::ForeignType(t), substs)) + Binders::new(substs.len(), Ty::ForeignType(t, substs)) } else { let type_ref = &db.type_alias_data(t).type_ref; let inner = Ty::from_hir(&ctx, type_ref.as_ref().unwrap_or(&TypeRef::Error)); diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs index 66d8de959..087b67935 100644 --- a/crates/hir_ty/src/method_resolution.rs +++ b/crates/hir_ty/src/method_resolution.rs @@ -7,8 +7,8 @@ use std::{iter, sync::Arc}; use arrayvec::ArrayVec; use base_db::CrateId; use hir_def::{ - lang_item::LangItemTarget, type_ref::Mutability, AssocContainerId, AssocItemId, FunctionId, - GenericDefId, HasModule, ImplId, Lookup, ModuleId, TraitId, + lang_item::LangItemTarget, type_ref::Mutability, AdtId, AssocContainerId, AssocItemId, + FunctionId, GenericDefId, HasModule, ImplId, Lookup, ModuleId, TraitId, TypeAliasId, }; use hir_expand::name::Name; use rustc_hash::{FxHashMap, FxHashSet}; @@ -18,15 +18,24 @@ use crate::{ db::HirDatabase, primitive::{self, FloatTy, IntTy, UintTy}, utils::all_super_traits, - ApplicationTy, Canonical, DebruijnIndex, InEnvironment, Scalar, Substs, TraitEnvironment, - TraitRef, Ty, TyKind, TypeCtor, TypeWalk, + Canonical, DebruijnIndex, InEnvironment, Scalar, Substs, TraitEnvironment, TraitRef, Ty, + TyKind, TypeWalk, }; /// This is used as a key for indexing impls. #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum TyFingerprint { - Apply(TypeCtor), + Str, + Slice, + Array, + Never, + RawPtr(Mutability), + Scalar(Scalar), + Adt(AdtId), Dyn(TraitId), + Tuple { cardinality: u16 }, + ForeignType(TypeAliasId), + FnPtr { num_args: u16, is_varargs: bool }, } impl TyFingerprint { @@ -34,32 +43,44 @@ impl TyFingerprint { /// have impls: if we have some `struct S`, we can have an `impl S`, but not /// `impl &S`. Hence, this will return `None` for reference types and such. pub(crate) fn for_impl(ty: &Ty) -> Option { - match ty { - Ty::Apply(a_ty) => Some(TyFingerprint::Apply(a_ty.ctor)), - Ty::Dyn(_) => ty.dyn_trait().map(|trait_| TyFingerprint::Dyn(trait_)), - _ => None, - } + let fp = match ty { + &Ty::Str => TyFingerprint::Str, + &Ty::Never => TyFingerprint::Never, + &Ty::Slice(..) => TyFingerprint::Slice, + &Ty::Array(..) => TyFingerprint::Array, + &Ty::Scalar(scalar) => TyFingerprint::Scalar(scalar), + &Ty::Adt(adt, _) => TyFingerprint::Adt(adt), + &Ty::Tuple { cardinality: u16, .. } => TyFingerprint::Tuple { cardinality: u16 }, + &Ty::RawPtr(mutability, ..) => TyFingerprint::RawPtr(mutability), + &Ty::ForeignType(alias_id, ..) => TyFingerprint::ForeignType(alias_id), + &Ty::FnPtr { num_args, is_varargs, .. } => { + TyFingerprint::FnPtr { num_args, is_varargs } + } + Ty::Dyn(_) => ty.dyn_trait().map(|trait_| TyFingerprint::Dyn(trait_))?, + _ => return None, + }; + Some(fp) } } pub(crate) const ALL_INT_FPS: [TyFingerprint; 12] = [ - TyFingerprint::Apply(TypeCtor::Scalar(Scalar::Int(IntTy::I8))), - TyFingerprint::Apply(TypeCtor::Scalar(Scalar::Int(IntTy::I16))), - TyFingerprint::Apply(TypeCtor::Scalar(Scalar::Int(IntTy::I32))), - TyFingerprint::Apply(TypeCtor::Scalar(Scalar::Int(IntTy::I64))), - TyFingerprint::Apply(TypeCtor::Scalar(Scalar::Int(IntTy::I128))), - TyFingerprint::Apply(TypeCtor::Scalar(Scalar::Int(IntTy::Isize))), - TyFingerprint::Apply(TypeCtor::Scalar(Scalar::Uint(UintTy::U8))), - TyFingerprint::Apply(TypeCtor::Scalar(Scalar::Uint(UintTy::U16))), - TyFingerprint::Apply(TypeCtor::Scalar(Scalar::Uint(UintTy::U32))), - TyFingerprint::Apply(TypeCtor::Scalar(Scalar::Uint(UintTy::U64))), - TyFingerprint::Apply(TypeCtor::Scalar(Scalar::Uint(UintTy::U128))), - TyFingerprint::Apply(TypeCtor::Scalar(Scalar::Uint(UintTy::Usize))), + TyFingerprint::Scalar(Scalar::Int(IntTy::I8)), + TyFingerprint::Scalar(Scalar::Int(IntTy::I16)), + TyFingerprint::Scalar(Scalar::Int(IntTy::I32)), + TyFingerprint::Scalar(Scalar::Int(IntTy::I64)), + TyFingerprint::Scalar(Scalar::Int(IntTy::I128)), + TyFingerprint::Scalar(Scalar::Int(IntTy::Isize)), + TyFingerprint::Scalar(Scalar::Uint(UintTy::U8)), + TyFingerprint::Scalar(Scalar::Uint(UintTy::U16)), + TyFingerprint::Scalar(Scalar::Uint(UintTy::U32)), + TyFingerprint::Scalar(Scalar::Uint(UintTy::U64)), + TyFingerprint::Scalar(Scalar::Uint(UintTy::U128)), + TyFingerprint::Scalar(Scalar::Uint(UintTy::Usize)), ]; pub(crate) const ALL_FLOAT_FPS: [TyFingerprint; 2] = [ - TyFingerprint::Apply(TypeCtor::Scalar(Scalar::Float(FloatTy::F32))), - TyFingerprint::Apply(TypeCtor::Scalar(Scalar::Float(FloatTy::F64))), + TyFingerprint::Scalar(Scalar::Float(FloatTy::F32)), + TyFingerprint::Scalar(Scalar::Float(FloatTy::F64)), ]; /// Trait impls defined or available in some crate. @@ -211,32 +232,29 @@ impl Ty { let mod_to_crate_ids = |module: ModuleId| Some(std::iter::once(module.krate()).collect()); let lang_item_targets = match self { - Ty::Apply(a_ty) => match a_ty.ctor { - TypeCtor::Adt(def_id) => { - return mod_to_crate_ids(def_id.module(db.upcast())); - } - TypeCtor::ForeignType(type_alias_id) => { - return mod_to_crate_ids(type_alias_id.lookup(db.upcast()).module(db.upcast())); - } - TypeCtor::Scalar(Scalar::Bool) => lang_item_crate!("bool"), - TypeCtor::Scalar(Scalar::Char) => lang_item_crate!("char"), - TypeCtor::Scalar(Scalar::Float(f)) => match f { - // There are two lang items: one in libcore (fXX) and one in libstd (fXX_runtime) - FloatTy::F32 => lang_item_crate!("f32", "f32_runtime"), - FloatTy::F64 => lang_item_crate!("f64", "f64_runtime"), - }, - TypeCtor::Scalar(Scalar::Int(t)) => { - lang_item_crate!(primitive::int_ty_to_string(t)) - } - TypeCtor::Scalar(Scalar::Uint(t)) => { - lang_item_crate!(primitive::uint_ty_to_string(t)) - } - TypeCtor::Str => lang_item_crate!("str_alloc", "str"), - TypeCtor::Slice => lang_item_crate!("slice_alloc", "slice"), - TypeCtor::RawPtr(Mutability::Shared) => lang_item_crate!("const_ptr"), - TypeCtor::RawPtr(Mutability::Mut) => lang_item_crate!("mut_ptr"), - _ => return None, + Ty::Adt(def_id, _) => { + return mod_to_crate_ids(def_id.module(db.upcast())); + } + Ty::ForeignType(type_alias_id, _) => { + return mod_to_crate_ids(type_alias_id.lookup(db.upcast()).module(db.upcast())); + } + Ty::Scalar(Scalar::Bool) => lang_item_crate!("bool"), + Ty::Scalar(Scalar::Char) => lang_item_crate!("char"), + Ty::Scalar(Scalar::Float(f)) => match f { + // There are two lang items: one in libcore (fXX) and one in libstd (fXX_runtime) + FloatTy::F32 => lang_item_crate!("f32", "f32_runtime"), + FloatTy::F64 => lang_item_crate!("f64", "f64_runtime"), }, + &Ty::Scalar(Scalar::Int(t)) => { + lang_item_crate!(primitive::int_ty_to_string(t)) + } + &Ty::Scalar(Scalar::Uint(t)) => { + lang_item_crate!(primitive::uint_ty_to_string(t)) + } + Ty::Str => lang_item_crate!("str_alloc", "str"), + Ty::Slice(_) => lang_item_crate!("slice_alloc", "slice"), + Ty::RawPtr(Mutability::Shared, _) => lang_item_crate!("const_ptr"), + Ty::RawPtr(Mutability::Mut, _) => lang_item_crate!("mut_ptr"), Ty::Dyn(_) => { return self.dyn_trait().and_then(|trait_| { mod_to_crate_ids(GenericDefId::TraitId(trait_).module(db.upcast())) @@ -413,7 +431,7 @@ fn iterate_method_candidates_with_autoref( } let refed = Canonical { kinds: deref_chain[0].kinds.clone(), - value: Ty::apply_one(TypeCtor::Ref(Mutability::Shared), deref_chain[0].value.clone()), + value: Ty::Ref(Mutability::Shared, Substs::single(deref_chain[0].value.clone())), }; if iterate_method_candidates_by_receiver( &refed, @@ -429,7 +447,7 @@ fn iterate_method_candidates_with_autoref( } let ref_muted = Canonical { kinds: deref_chain[0].kinds.clone(), - value: Ty::apply_one(TypeCtor::Ref(Mutability::Mut), deref_chain[0].value.clone()), + value: Ty::Ref(Mutability::Mut, Substs::single(deref_chain[0].value.clone())), }; if iterate_method_candidates_by_receiver( &ref_muted, @@ -756,11 +774,9 @@ fn autoderef_method_receiver( ) -> Vec> { let mut deref_chain: Vec<_> = autoderef::autoderef(db, Some(krate), ty).collect(); // As a last step, we can do array unsizing (that's the only unsizing that rustc does for method receivers!) - if let Some(Ty::Apply(ApplicationTy { ctor: TypeCtor::Array, parameters })) = - deref_chain.last().map(|ty| &ty.value) - { + if let Some(Ty::Array(parameters)) = deref_chain.last().map(|ty| &ty.value) { let kinds = deref_chain.last().unwrap().kinds.clone(); - let unsized_ty = Ty::apply(TypeCtor::Slice, parameters.clone()); + let unsized_ty = Ty::Slice(parameters.clone()); deref_chain.push(Canonical { value: unsized_ty, kinds }) } deref_chain diff --git a/crates/hir_ty/src/op.rs b/crates/hir_ty/src/op.rs index a4999c51d..1c01a67ad 100644 --- a/crates/hir_ty/src/op.rs +++ b/crates/hir_ty/src/op.rs @@ -1,30 +1,23 @@ //! Helper functions for binary operator type inference. use hir_def::expr::{ArithOp, BinaryOp, CmpOp}; -use super::{InferTy, Ty, TypeCtor}; -use crate::{ApplicationTy, Scalar}; +use crate::{InferTy, Scalar, Ty}; pub(super) fn binary_op_return_ty(op: BinaryOp, lhs_ty: Ty, rhs_ty: Ty) -> Ty { match op { - BinaryOp::LogicOp(_) | BinaryOp::CmpOp(_) => Ty::simple(TypeCtor::Scalar(Scalar::Bool)), + BinaryOp::LogicOp(_) | BinaryOp::CmpOp(_) => Ty::Scalar(Scalar::Bool), BinaryOp::Assignment { .. } => Ty::unit(), BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => match lhs_ty { - Ty::Apply(ApplicationTy { ctor, .. }) => match ctor { - TypeCtor::Scalar(Scalar::Int(_)) - | TypeCtor::Scalar(Scalar::Uint(_)) - | TypeCtor::Scalar(Scalar::Float(_)) => lhs_ty, - _ => Ty::Unknown, - }, + Ty::Scalar(Scalar::Int(_)) + | Ty::Scalar(Scalar::Uint(_)) + | Ty::Scalar(Scalar::Float(_)) => lhs_ty, Ty::Infer(InferTy::IntVar(..)) | Ty::Infer(InferTy::FloatVar(..)) => lhs_ty, _ => Ty::Unknown, }, BinaryOp::ArithOp(_) => match rhs_ty { - Ty::Apply(ApplicationTy { ctor, .. }) => match ctor { - TypeCtor::Scalar(Scalar::Int(_)) - | TypeCtor::Scalar(Scalar::Uint(_)) - | TypeCtor::Scalar(Scalar::Float(_)) => rhs_ty, - _ => Ty::Unknown, - }, + Ty::Scalar(Scalar::Int(_)) + | Ty::Scalar(Scalar::Uint(_)) + | Ty::Scalar(Scalar::Float(_)) => rhs_ty, Ty::Infer(InferTy::IntVar(..)) | Ty::Infer(InferTy::FloatVar(..)) => rhs_ty, _ => Ty::Unknown, }, @@ -33,13 +26,10 @@ pub(super) fn binary_op_return_ty(op: BinaryOp, lhs_ty: Ty, rhs_ty: Ty) -> Ty { pub(super) fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty { match op { - BinaryOp::LogicOp(..) => Ty::simple(TypeCtor::Scalar(Scalar::Bool)), + BinaryOp::LogicOp(..) => Ty::Scalar(Scalar::Bool), BinaryOp::Assignment { op: None } => lhs_ty, BinaryOp::CmpOp(CmpOp::Eq { .. }) => match lhs_ty { - Ty::Apply(ApplicationTy { ctor, .. }) => match ctor { - TypeCtor::Scalar(_) | TypeCtor::Str => lhs_ty, - _ => Ty::Unknown, - }, + Ty::Scalar(_) | Ty::Str => lhs_ty, Ty::Infer(InferTy::IntVar(..)) | Ty::Infer(InferTy::FloatVar(..)) => lhs_ty, _ => Ty::Unknown, }, @@ -47,12 +37,9 @@ pub(super) fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty { BinaryOp::CmpOp(CmpOp::Ord { .. }) | BinaryOp::Assignment { op: Some(_) } | BinaryOp::ArithOp(_) => match lhs_ty { - Ty::Apply(ApplicationTy { ctor, .. }) => match ctor { - TypeCtor::Scalar(Scalar::Int(_)) - | TypeCtor::Scalar(Scalar::Uint(_)) - | TypeCtor::Scalar(Scalar::Float(_)) => lhs_ty, - _ => Ty::Unknown, - }, + Ty::Scalar(Scalar::Int(_)) + | Ty::Scalar(Scalar::Uint(_)) + | Ty::Scalar(Scalar::Float(_)) => lhs_ty, Ty::Infer(InferTy::IntVar(..)) | Ty::Infer(InferTy::FloatVar(..)) => lhs_ty, _ => Ty::Unknown, }, diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs index d74c83737..c53e327da 100644 --- a/crates/hir_ty/src/traits/chalk.rs +++ b/crates/hir_ty/src/traits/chalk.rs @@ -20,7 +20,7 @@ use crate::{ method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS}, utils::generics, BoundVar, CallableDefId, DebruijnIndex, FnSig, GenericPredicate, ProjectionPredicate, - ProjectionTy, Substs, TraitRef, Ty, TypeCtor, + ProjectionTy, Substs, TraitRef, Ty, }; use mapping::{ convert_where_clauses, generic_predicate_to_inline_bound, make_binders, TypeAliasAsAssocType, @@ -489,10 +489,11 @@ pub(crate) fn struct_datum_query( struct_id: AdtId, ) -> Arc { debug!("struct_datum {:?}", struct_id); - let type_ctor = TypeCtor::Adt(from_chalk(db, struct_id)); + let adt_id = from_chalk(db, struct_id); + let type_ctor = Ty::Adt(adt_id, Substs::empty()); debug!("struct {:?} = {:?}", struct_id, type_ctor); - let num_params = type_ctor.num_ty_params(db); - let upstream = type_ctor.krate(db) != Some(krate); + let num_params = generics(db.upcast(), adt_id.into()).len(); + let upstream = adt_id.module(db.upcast()).krate() != krate; let where_clauses = type_ctor .as_generic_def() .map(|generic_def| { diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs index 5a3cb7906..297ddeabd 100644 --- a/crates/hir_ty/src/traits/chalk/mapping.rs +++ b/crates/hir_ty/src/traits/chalk/mapping.rs @@ -16,9 +16,8 @@ use crate::{ db::HirDatabase, primitive::UintTy, traits::{Canonical, Obligation}, - ApplicationTy, CallableDefId, GenericPredicate, InEnvironment, OpaqueTy, OpaqueTyId, - ProjectionPredicate, ProjectionTy, Scalar, Substs, TraitEnvironment, TraitRef, Ty, TyKind, - TypeCtor, + CallableDefId, GenericPredicate, InEnvironment, OpaqueTy, OpaqueTyId, ProjectionPredicate, + ProjectionTy, Scalar, Substs, TraitEnvironment, TraitRef, Ty, TyKind, }; use super::interner::*; @@ -28,75 +27,71 @@ impl ToChalk for Ty { type Chalk = chalk_ir::Ty; fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty { match self { - Ty::Apply(apply_ty) => match apply_ty.ctor { - TypeCtor::Ref(m) => ref_to_chalk(db, m, apply_ty.parameters), - TypeCtor::Array => array_to_chalk(db, apply_ty.parameters), - TypeCtor::FnPtr { num_args: _, is_varargs } => { - let substitution = - chalk_ir::FnSubst(apply_ty.parameters.to_chalk(db).shifted_in(&Interner)); - chalk_ir::TyKind::Function(chalk_ir::FnPointer { - num_binders: 0, - sig: chalk_ir::FnSig { - abi: (), - safety: chalk_ir::Safety::Safe, - variadic: is_varargs, - }, - substitution, - }) - .intern(&Interner) - } - TypeCtor::AssociatedType(type_alias) => { - let assoc_type = TypeAliasAsAssocType(type_alias); - let assoc_type_id = assoc_type.to_chalk(db); - let substitution = apply_ty.parameters.to_chalk(db); - chalk_ir::TyKind::AssociatedType(assoc_type_id, substitution).intern(&Interner) - } + Ty::Ref(m, parameters) => ref_to_chalk(db, m, parameters), + Ty::Array(parameters) => array_to_chalk(db, parameters), + Ty::FnPtr { num_args: _, is_varargs, substs } => { + let substitution = chalk_ir::FnSubst(substs.to_chalk(db).shifted_in(&Interner)); + chalk_ir::TyKind::Function(chalk_ir::FnPointer { + num_binders: 0, + sig: chalk_ir::FnSig { + abi: (), + safety: chalk_ir::Safety::Safe, + variadic: is_varargs, + }, + substitution, + }) + .intern(&Interner) + } + Ty::AssociatedType(type_alias, substs) => { + let assoc_type = TypeAliasAsAssocType(type_alias); + let assoc_type_id = assoc_type.to_chalk(db); + let substitution = substs.to_chalk(db); + chalk_ir::TyKind::AssociatedType(assoc_type_id, substitution).intern(&Interner) + } - TypeCtor::OpaqueType(impl_trait_id) => { - let id = impl_trait_id.to_chalk(db); - let substitution = apply_ty.parameters.to_chalk(db); - chalk_ir::TyKind::OpaqueType(id, substitution).intern(&Interner) - } + Ty::OpaqueType(impl_trait_id, substs) => { + let id = impl_trait_id.to_chalk(db); + let substitution = substs.to_chalk(db); + chalk_ir::TyKind::OpaqueType(id, substitution).intern(&Interner) + } - TypeCtor::ForeignType(type_alias) => { - let foreign_type = TypeAliasAsForeignType(type_alias); - let foreign_type_id = foreign_type.to_chalk(db); - chalk_ir::TyKind::Foreign(foreign_type_id).intern(&Interner) - } + Ty::ForeignType(type_alias, _) => { + let foreign_type = TypeAliasAsForeignType(type_alias); + let foreign_type_id = foreign_type.to_chalk(db); + chalk_ir::TyKind::Foreign(foreign_type_id).intern(&Interner) + } - TypeCtor::Scalar(scalar) => chalk_ir::TyKind::Scalar(scalar).intern(&Interner), + Ty::Scalar(scalar) => chalk_ir::TyKind::Scalar(scalar).intern(&Interner), - TypeCtor::Tuple { cardinality } => { - let substitution = apply_ty.parameters.to_chalk(db); - chalk_ir::TyKind::Tuple(cardinality.into(), substitution).intern(&Interner) - } - TypeCtor::RawPtr(mutability) => { - let ty = apply_ty.parameters[0].clone().to_chalk(db); - chalk_ir::TyKind::Raw(mutability.to_chalk(db), ty).intern(&Interner) - } - TypeCtor::Slice => { - chalk_ir::TyKind::Slice(apply_ty.parameters[0].clone().to_chalk(db)) - .intern(&Interner) - } - TypeCtor::Str => chalk_ir::TyKind::Str.intern(&Interner), - TypeCtor::FnDef(callable_def) => { - let id = callable_def.to_chalk(db); - let substitution = apply_ty.parameters.to_chalk(db); - chalk_ir::TyKind::FnDef(id, substitution).intern(&Interner) - } - TypeCtor::Never => chalk_ir::TyKind::Never.intern(&Interner), + Ty::Tuple { cardinality, substs } => { + let substitution = substs.to_chalk(db); + chalk_ir::TyKind::Tuple(cardinality.into(), substitution).intern(&Interner) + } + Ty::RawPtr(mutability, substs) => { + let ty = substs[0].clone().to_chalk(db); + chalk_ir::TyKind::Raw(mutability.to_chalk(db), ty).intern(&Interner) + } + Ty::Slice(substs) => { + chalk_ir::TyKind::Slice(substs[0].clone().to_chalk(db)).intern(&Interner) + } + Ty::Str => chalk_ir::TyKind::Str.intern(&Interner), + Ty::FnDef(callable_def, substs) => { + let id = callable_def.to_chalk(db); + let substitution = substs.to_chalk(db); + chalk_ir::TyKind::FnDef(id, substitution).intern(&Interner) + } + Ty::Never => chalk_ir::TyKind::Never.intern(&Interner), - TypeCtor::Closure { def, expr } => { - let closure_id = db.intern_closure((def, expr)); - let substitution = apply_ty.parameters.to_chalk(db); - chalk_ir::TyKind::Closure(closure_id.into(), substitution).intern(&Interner) - } + Ty::Closure { def, expr, substs } => { + let closure_id = db.intern_closure((def, expr)); + let substitution = substs.to_chalk(db); + chalk_ir::TyKind::Closure(closure_id.into(), substitution).intern(&Interner) + } - TypeCtor::Adt(adt_id) => { - let substitution = apply_ty.parameters.to_chalk(db); - chalk_ir::TyKind::Adt(chalk_ir::AdtId(adt_id), substitution).intern(&Interner) - } - }, + Ty::Adt(adt_id, substs) => { + let substitution = substs.to_chalk(db); + chalk_ir::TyKind::Adt(chalk_ir::AdtId(adt_id), substitution).intern(&Interner) + } Ty::Projection(proj_ty) => { let associated_ty_id = TypeAliasAsAssocType(proj_ty.associated_ty).to_chalk(db); let substitution = proj_ty.parameters.to_chalk(db); @@ -143,9 +138,7 @@ impl ToChalk for Ty { fn from_chalk(db: &dyn HirDatabase, chalk: chalk_ir::Ty) -> Self { match chalk.data(&Interner).kind.clone() { chalk_ir::TyKind::Error => Ty::Unknown, - chalk_ir::TyKind::Array(ty, _size) => { - Ty::apply(TypeCtor::Array, Substs::single(from_chalk(db, ty))) - } + chalk_ir::TyKind::Array(ty, _size) => Ty::Array(Substs::single(from_chalk(db, ty))), chalk_ir::TyKind::Placeholder(idx) => { assert_eq!(idx.ui, UniverseIndex::ROOT); let interned_id = crate::db::GlobalTypeParamId::from_intern_id( @@ -175,13 +168,11 @@ impl ToChalk for Ty { db, substitution.0.shifted_out(&Interner).expect("fn ptr should have no binders"), ); - Ty::Apply(ApplicationTy { - ctor: TypeCtor::FnPtr { - num_args: (parameters.len() - 1) as u16, - is_varargs: variadic, - }, - parameters, - }) + Ty::FnPtr { + num_args: (parameters.len() - 1) as u16, + is_varargs: variadic, + substs: parameters, + } } chalk_ir::TyKind::BoundVar(idx) => Ty::Bound(idx), chalk_ir::TyKind::InferenceVar(_iv, _kind) => Ty::Unknown, @@ -196,60 +187,50 @@ impl ToChalk for Ty { Ty::Dyn(predicates) } - chalk_ir::TyKind::Adt(struct_id, subst) => { - apply_ty_from_chalk(db, TypeCtor::Adt(struct_id.0), subst) - } - chalk_ir::TyKind::AssociatedType(type_id, subst) => apply_ty_from_chalk( - db, - TypeCtor::AssociatedType(from_chalk::(db, type_id).0), - subst, + chalk_ir::TyKind::Adt(struct_id, subst) => Ty::Adt(struct_id.0, from_chalk(db, subst)), + chalk_ir::TyKind::AssociatedType(type_id, subst) => Ty::AssociatedType( + from_chalk::(db, type_id).0, + from_chalk(db, subst), ), + chalk_ir::TyKind::OpaqueType(opaque_type_id, subst) => { - apply_ty_from_chalk(db, TypeCtor::OpaqueType(from_chalk(db, opaque_type_id)), subst) + Ty::OpaqueType(from_chalk(db, opaque_type_id), from_chalk(db, subst)) } - chalk_ir::TyKind::Scalar(scalar) => Ty::simple(TypeCtor::Scalar(scalar)), + chalk_ir::TyKind::Scalar(scalar) => Ty::Scalar(scalar), chalk_ir::TyKind::Tuple(cardinality, subst) => { - apply_ty_from_chalk(db, TypeCtor::Tuple { cardinality: cardinality as u16 }, subst) + Ty::Tuple { cardinality: cardinality as u16, substs: from_chalk(db, subst) } } chalk_ir::TyKind::Raw(mutability, ty) => { - Ty::apply_one(TypeCtor::RawPtr(from_chalk(db, mutability)), from_chalk(db, ty)) + Ty::RawPtr(from_chalk(db, mutability), Substs::single(from_chalk(db, ty))) } - chalk_ir::TyKind::Slice(ty) => Ty::apply_one(TypeCtor::Slice, from_chalk(db, ty)), + chalk_ir::TyKind::Slice(ty) => Ty::Slice(Substs::single(from_chalk(db, ty))), chalk_ir::TyKind::Ref(mutability, _lifetime, ty) => { - Ty::apply_one(TypeCtor::Ref(from_chalk(db, mutability)), from_chalk(db, ty)) + Ty::Ref(from_chalk(db, mutability), Substs::single(from_chalk(db, ty))) } - chalk_ir::TyKind::Str => Ty::simple(TypeCtor::Str), - chalk_ir::TyKind::Never => Ty::simple(TypeCtor::Never), + chalk_ir::TyKind::Str => Ty::Str, + chalk_ir::TyKind::Never => Ty::Never, chalk_ir::TyKind::FnDef(fn_def_id, subst) => { - let callable_def = from_chalk(db, fn_def_id); - apply_ty_from_chalk(db, TypeCtor::FnDef(callable_def), subst) + Ty::FnDef(from_chalk(db, fn_def_id), from_chalk(db, subst)) } chalk_ir::TyKind::Closure(id, subst) => { let id: crate::db::ClosureId = id.into(); let (def, expr) = db.lookup_intern_closure(id); - apply_ty_from_chalk(db, TypeCtor::Closure { def, expr }, subst) + Ty::Closure { def, expr, substs: from_chalk(db, subst) } } - chalk_ir::TyKind::Foreign(foreign_def_id) => Ty::simple(TypeCtor::ForeignType( + chalk_ir::TyKind::Foreign(foreign_def_id) => Ty::ForeignType( from_chalk::(db, foreign_def_id).0, - )), + Substs::empty(), + ), chalk_ir::TyKind::Generator(_, _) => unimplemented!(), // FIXME chalk_ir::TyKind::GeneratorWitness(_, _) => unimplemented!(), // FIXME } } } -fn apply_ty_from_chalk( - db: &dyn HirDatabase, - ctor: TypeCtor, - subst: chalk_ir::Substitution, -) -> Ty { - Ty::Apply(ApplicationTy { ctor, parameters: from_chalk(db, subst) }) -} - /// We currently don't model lifetimes, but Chalk does. So, we have to insert a /// fake lifetime here, because Chalks built-in logic may expect it to be there. fn ref_to_chalk( -- cgit v1.2.3