Merge #7813
7813: Inline TypeCtor into Ty r=flodiebold a=Veykril This removes the `ApplicationTy` variant from `Ty` bringing the representation a lot closer to chalk's `TyKind`. Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
This commit is contained in:
commit
2fc137b70f
@ -31,9 +31,9 @@
|
||||
display::{write_bounds_like_dyn_trait_with_prefix, HirDisplayError, HirFormatter},
|
||||
method_resolution,
|
||||
traits::{FnTrait, Solution, SolutionVariables},
|
||||
ApplicationTy, BoundVar, CallableDefId, Canonical, DebruijnIndex, FnSig, GenericPredicate,
|
||||
InEnvironment, Obligation, ProjectionPredicate, ProjectionTy, Scalar, Substs, TraitEnvironment,
|
||||
Ty, TyDefId, TyKind, TypeCtor,
|
||||
BoundVar, CallableDefId, Canonical, DebruijnIndex, FnSig, GenericPredicate, InEnvironment,
|
||||
Obligation, ProjectionPredicate, ProjectionTy, Scalar, Substs, TraitEnvironment, Ty, TyDefId,
|
||||
TyKind,
|
||||
};
|
||||
use rustc_hash::FxHashSet;
|
||||
use stdx::{format_to, impl_from};
|
||||
@ -1547,28 +1547,19 @@ fn from_def(
|
||||
}
|
||||
|
||||
pub fn is_unit(&self) -> bool {
|
||||
matches!(
|
||||
self.ty.value,
|
||||
Ty::Apply(ApplicationTy { ctor: TypeCtor::Tuple { cardinality: 0 }, .. })
|
||||
)
|
||||
matches!(self.ty.value, Ty::Tuple { cardinality: 0, .. })
|
||||
}
|
||||
pub fn is_bool(&self) -> bool {
|
||||
matches!(
|
||||
self.ty.value,
|
||||
Ty::Apply(ApplicationTy { ctor: TypeCtor::Scalar(Scalar::Bool), .. })
|
||||
)
|
||||
matches!(self.ty.value, Ty::Scalar(Scalar::Bool))
|
||||
}
|
||||
|
||||
pub fn is_mutable_reference(&self) -> bool {
|
||||
matches!(
|
||||
self.ty.value,
|
||||
Ty::Apply(ApplicationTy { ctor: TypeCtor::Ref(Mutability::Mut), .. })
|
||||
)
|
||||
matches!(self.ty.value, Ty::Ref(Mutability::Mut, ..))
|
||||
}
|
||||
|
||||
pub fn remove_ref(&self) -> Option<Type> {
|
||||
if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Ref(_), .. }) = self.ty.value {
|
||||
self.ty.value.substs().map(|substs| self.derived(substs[0].clone()))
|
||||
if let Ty::Ref(.., substs) = &self.ty.value {
|
||||
Some(self.derived(substs[0].clone()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -1688,7 +1679,7 @@ pub fn is_copy(&self, db: &dyn HirDatabase) -> bool {
|
||||
|
||||
pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> {
|
||||
let def = match self.ty.value {
|
||||
Ty::Apply(ApplicationTy { ctor: TypeCtor::FnDef(def), parameters: _ }) => Some(def),
|
||||
Ty::FnDef(def, _) => Some(def),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
@ -1697,20 +1688,16 @@ pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> {
|
||||
}
|
||||
|
||||
pub fn is_closure(&self) -> bool {
|
||||
matches!(&self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::Closure { .. }, .. }))
|
||||
matches!(&self.ty.value, Ty::Closure { .. })
|
||||
}
|
||||
|
||||
pub fn is_fn(&self) -> bool {
|
||||
matches!(
|
||||
&self.ty.value,
|
||||
Ty::Apply(ApplicationTy { ctor: TypeCtor::FnDef(..), .. })
|
||||
| Ty::Apply(ApplicationTy { ctor: TypeCtor::FnPtr { .. }, .. })
|
||||
)
|
||||
matches!(&self.ty.value, Ty::FnDef(..) | Ty::FnPtr { .. })
|
||||
}
|
||||
|
||||
pub fn is_packed(&self, db: &dyn HirDatabase) -> bool {
|
||||
let adt_id = match self.ty.value {
|
||||
Ty::Apply(ApplicationTy { ctor: TypeCtor::Adt(adt_id), .. }) => adt_id,
|
||||
Ty::Adt(adt_id, ..) => adt_id,
|
||||
_ => return false,
|
||||
};
|
||||
|
||||
@ -1722,7 +1709,7 @@ pub fn is_packed(&self, db: &dyn HirDatabase) -> bool {
|
||||
}
|
||||
|
||||
pub fn is_raw_ptr(&self) -> bool {
|
||||
matches!(&self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::RawPtr(..), .. }))
|
||||
matches!(&self.ty.value, Ty::RawPtr(..))
|
||||
}
|
||||
|
||||
pub fn contains_unknown(&self) -> bool {
|
||||
@ -1731,44 +1718,34 @@ pub fn contains_unknown(&self) -> bool {
|
||||
fn go(ty: &Ty) -> bool {
|
||||
match ty {
|
||||
Ty::Unknown => true,
|
||||
Ty::Apply(a_ty) => a_ty.parameters.iter().any(go),
|
||||
_ => false,
|
||||
_ => ty.substs().map_or(false, |substs| substs.iter().any(go)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> {
|
||||
if let Ty::Apply(a_ty) = &self.ty.value {
|
||||
let variant_id = match a_ty.ctor {
|
||||
TypeCtor::Adt(AdtId::StructId(s)) => s.into(),
|
||||
TypeCtor::Adt(AdtId::UnionId(u)) => u.into(),
|
||||
_ => return Vec::new(),
|
||||
};
|
||||
|
||||
return db
|
||||
.field_types(variant_id)
|
||||
.iter()
|
||||
.map(|(local_id, ty)| {
|
||||
let def = Field { parent: variant_id.into(), id: local_id };
|
||||
let ty = ty.clone().subst(&a_ty.parameters);
|
||||
(def, self.derived(ty))
|
||||
})
|
||||
.collect();
|
||||
let (variant_id, substs) = match self.ty.value {
|
||||
Ty::Adt(AdtId::StructId(s), ref substs) => (s.into(), substs),
|
||||
Ty::Adt(AdtId::UnionId(u), ref substs) => (u.into(), substs),
|
||||
_ => return Vec::new(),
|
||||
};
|
||||
Vec::new()
|
||||
|
||||
db.field_types(variant_id)
|
||||
.iter()
|
||||
.map(|(local_id, ty)| {
|
||||
let def = Field { parent: variant_id.into(), id: local_id };
|
||||
let ty = ty.clone().subst(substs);
|
||||
(def, self.derived(ty))
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec<Type> {
|
||||
let mut res = Vec::new();
|
||||
if let Ty::Apply(a_ty) = &self.ty.value {
|
||||
if let TypeCtor::Tuple { .. } = a_ty.ctor {
|
||||
for ty in a_ty.parameters.iter() {
|
||||
let ty = ty.clone();
|
||||
res.push(self.derived(ty));
|
||||
}
|
||||
}
|
||||
};
|
||||
res
|
||||
if let Ty::Tuple { substs, .. } = &self.ty.value {
|
||||
substs.iter().map(|ty| self.derived(ty.clone())).collect()
|
||||
} else {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn autoderef<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Type> + 'a {
|
||||
@ -1805,15 +1782,13 @@ pub fn iterate_assoc_items<T>(
|
||||
}
|
||||
|
||||
pub fn type_parameters(&self) -> impl Iterator<Item = Type> + '_ {
|
||||
let ty = self.ty.value.strip_references();
|
||||
let substs = match ty {
|
||||
Ty::Apply(apply_ty) => &apply_ty.parameters,
|
||||
Ty::Opaque(opaque_ty) => &opaque_ty.parameters,
|
||||
_ => return Either::Left(iter::empty()),
|
||||
};
|
||||
|
||||
let iter = substs.iter().map(move |ty| self.derived(ty.clone()));
|
||||
Either::Right(iter)
|
||||
self.ty
|
||||
.value
|
||||
.strip_references()
|
||||
.substs()
|
||||
.into_iter()
|
||||
.flat_map(|substs| substs.iter())
|
||||
.map(move |ty| self.derived(ty.clone()))
|
||||
}
|
||||
|
||||
pub fn iterate_method_candidates<T>(
|
||||
@ -1903,17 +1878,8 @@ pub fn as_associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<Tr
|
||||
|
||||
// FIXME: provide required accessors such that it becomes implementable from outside.
|
||||
pub fn is_equal_for_find_impls(&self, other: &Type) -> bool {
|
||||
match (&self.ty.value, &other.ty.value) {
|
||||
(Ty::Apply(a_original_ty), Ty::Apply(ApplicationTy { ctor, parameters })) => match ctor
|
||||
{
|
||||
TypeCtor::Ref(..) => match parameters.as_single() {
|
||||
Ty::Apply(a_ty) => a_original_ty.ctor == a_ty.ctor,
|
||||
_ => false,
|
||||
},
|
||||
_ => a_original_ty.ctor == *ctor,
|
||||
},
|
||||
_ => false,
|
||||
}
|
||||
let rref = other.remove_ref();
|
||||
self.ty.value.equals_ctor(rref.as_ref().map_or(&other.ty.value, |it| &it.ty.value))
|
||||
}
|
||||
|
||||
fn derived(&self, ty: Ty) -> Type {
|
||||
@ -1958,26 +1924,18 @@ fn walk_bounds(
|
||||
fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) {
|
||||
let ty = type_.ty.value.strip_references();
|
||||
match ty {
|
||||
Ty::Apply(ApplicationTy { ctor, parameters }) => {
|
||||
match ctor {
|
||||
TypeCtor::Adt(_) => {
|
||||
cb(type_.derived(ty.clone()));
|
||||
}
|
||||
TypeCtor::AssociatedType(_) => {
|
||||
if let Some(_) = ty.associated_type_parent_trait(db) {
|
||||
cb(type_.derived(ty.clone()));
|
||||
}
|
||||
}
|
||||
TypeCtor::OpaqueType(..) => {
|
||||
if let Some(bounds) = ty.impl_trait_bounds(db) {
|
||||
walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
Ty::Adt(..) => {
|
||||
cb(type_.derived(ty.clone()));
|
||||
}
|
||||
Ty::AssociatedType(..) => {
|
||||
if let Some(_) = ty.associated_type_parent_trait(db) {
|
||||
cb(type_.derived(ty.clone()));
|
||||
}
|
||||
}
|
||||
Ty::OpaqueType(..) => {
|
||||
if let Some(bounds) = ty.impl_trait_bounds(db) {
|
||||
walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
|
||||
}
|
||||
|
||||
// adt params, tuples, etc...
|
||||
walk_substs(db, type_, parameters, cb);
|
||||
}
|
||||
Ty::Opaque(opaque_ty) => {
|
||||
if let Some(bounds) = ty.impl_trait_bounds(db) {
|
||||
@ -1995,7 +1953,10 @@ fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) {
|
||||
walk_bounds(db, &type_.derived(ty.clone()), bounds.as_ref(), cb);
|
||||
}
|
||||
|
||||
_ => (),
|
||||
_ => {}
|
||||
}
|
||||
if let Some(substs) = ty.substs() {
|
||||
walk_substs(db, type_, &substs, cb);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile};
|
||||
use hir_ty::{
|
||||
diagnostics::{record_literal_missing_fields, record_pattern_missing_fields},
|
||||
InferenceResult, Substs, Ty,
|
||||
InferenceResult, Substs,
|
||||
};
|
||||
use syntax::{
|
||||
ast::{self, AstNode},
|
||||
@ -299,14 +299,11 @@ pub(crate) fn record_literal_missing_fields(
|
||||
let infer = self.infer.as_ref()?;
|
||||
|
||||
let expr_id = self.expr_id(db, &literal.clone().into())?;
|
||||
let substs = match &infer.type_of_expr[expr_id] {
|
||||
Ty::Apply(a_ty) => &a_ty.parameters,
|
||||
_ => return None,
|
||||
};
|
||||
let substs = infer.type_of_expr[expr_id].substs()?;
|
||||
|
||||
let (variant, missing_fields, _exhaustive) =
|
||||
record_literal_missing_fields(db, infer, expr_id, &body[expr_id])?;
|
||||
let res = self.missing_fields(db, krate, substs, variant, missing_fields);
|
||||
let res = self.missing_fields(db, krate, &substs, variant, missing_fields);
|
||||
Some(res)
|
||||
}
|
||||
|
||||
@ -320,14 +317,11 @@ pub(crate) fn record_pattern_missing_fields(
|
||||
let infer = self.infer.as_ref()?;
|
||||
|
||||
let pat_id = self.pat_id(&pattern.clone().into())?;
|
||||
let substs = match &infer.type_of_pat[pat_id] {
|
||||
Ty::Apply(a_ty) => &a_ty.parameters,
|
||||
_ => return None,
|
||||
};
|
||||
let substs = infer.type_of_pat[pat_id].substs()?;
|
||||
|
||||
let (variant, missing_fields, _exhaustive) =
|
||||
record_pattern_missing_fields(db, infer, pat_id, &body[pat_id])?;
|
||||
let res = self.missing_fields(db, krate, substs, variant, missing_fields);
|
||||
let res = self.missing_fields(db, krate, &substs, variant, missing_fields);
|
||||
Some(res)
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
MissingPatFields, RemoveThisSemicolon,
|
||||
},
|
||||
utils::variant_data,
|
||||
ApplicationTy, InferenceResult, Ty, TypeCtor,
|
||||
InferenceResult, Ty,
|
||||
};
|
||||
|
||||
pub(crate) use hir_def::{
|
||||
@ -381,14 +381,11 @@ fn validate_results_in_tail_expr(&mut self, body_id: ExprId, id: ExprId, db: &dy
|
||||
_ => 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,
|
||||
|
@ -227,7 +227,7 @@
|
||||
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),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
|
@ -11,9 +11,7 @@
|
||||
};
|
||||
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 });
|
||||
}
|
||||
}
|
||||
|
@ -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 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
|
||||
}
|
||||
}
|
||||
|
||||
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,24 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
|
||||
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, 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, parameters) => {
|
||||
let def = *def;
|
||||
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 +357,7 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
|
||||
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 +365,7 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
|
||||
// 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,10 +384,10 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
|
||||
write!(f, " -> {}", ret_display)?;
|
||||
}
|
||||
}
|
||||
TypeCtor::Adt(def_id) => {
|
||||
Ty::Adt(def_id, parameters) => {
|
||||
match f.display_target {
|
||||
DisplayTarget::Diagnostics | DisplayTarget::Test => {
|
||||
let name = match def_id {
|
||||
let name = match *def_id {
|
||||
AdtId::StructId(it) => f.db.struct_data(it).name.clone(),
|
||||
AdtId::UnionId(it) => f.db.union_data(it).name.clone(),
|
||||
AdtId::EnumId(it) => f.db.enum_data(it).name.clone(),
|
||||
@ -376,7 +397,7 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
|
||||
DisplayTarget::SourceCode { module_id } => {
|
||||
if let Some(path) = find_path::find_path(
|
||||
f.db.upcast(),
|
||||
ItemInNs::Types(def_id.into()),
|
||||
ItemInNs::Types((*def_id).into()),
|
||||
module_id,
|
||||
) {
|
||||
write!(f, "{}", path)?;
|
||||
@ -388,19 +409,18 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
|
||||
}
|
||||
}
|
||||
|
||||
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 +428,18 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
|
||||
(_, 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,61 +448,59 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
|
||||
}
|
||||
}
|
||||
}
|
||||
TypeCtor::AssociatedType(type_alias) => {
|
||||
Ty::AssociatedType(type_alias, parameters) => {
|
||||
let trait_ = match type_alias.lookup(f.db.upcast()).container {
|
||||
AssocContainerId::TraitId(it) => it,
|
||||
_ => panic!("not an associated type"),
|
||||
};
|
||||
let trait_ = f.db.trait_data(trait_);
|
||||
let type_alias_data = f.db.type_alias_data(type_alias);
|
||||
let type_alias_data = f.db.type_alias_data(*type_alias);
|
||||
|
||||
// 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) => {
|
||||
let type_alias = f.db.type_alias_data(type_alias);
|
||||
Ty::ForeignType(type_alias, 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, parameters) => {
|
||||
match opaque_ty_id {
|
||||
OpaqueTyId::ReturnTypeImplTrait(func, idx) => {
|
||||
&OpaqueTyId::ReturnTypeImplTrait(func, idx) => {
|
||||
let datas =
|
||||
f.db.return_type_impl_traits(func).expect("impl trait id without data");
|
||||
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<Output = ")?;
|
||||
self.parameters[0].hir_fmt(f)?;
|
||||
parameters[0].hir_fmt(f)?;
|
||||
write!(f, ">")?;
|
||||
}
|
||||
}
|
||||
}
|
||||
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 +523,6 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
|
||||
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);
|
||||
|
@ -38,7 +38,7 @@
|
||||
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 @@
|
||||
|
||||
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 @@ fn to_inner(self) -> unify::TypeVarId {
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 @@ pub(super) fn coerce_merge_branch(&mut self, ty1: &Ty, ty2: &Ty) -> Ty {
|
||||
} 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 @@ pub(super) fn coerce_merge_branch(&mut self, ty1: &Ty, ty2: &Ty) -> Ty {
|
||||
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 @@ fn coerce_inner(&mut self, mut from_ty: Ty, to_ty: &Ty) -> bool {
|
||||
|
||||
// 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 @@ fn coerce_inner(&mut self, mut from_ty: Ty, to_ty: &Ty) -> bool {
|
||||
// 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 @@ fn unify_autoderef_behind_ref(&mut self, from_ty: &Ty, to_ty: &Ty) -> bool {
|
||||
},
|
||||
) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,8 +18,8 @@
|
||||
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 @@ fn callable_sig_from_fn_trait(&mut self, ty: &Ty, num_args: usize) -> Option<(Ve
|
||||
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 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
|
||||
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 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
|
||||
// existenail type AsyncBlockImplTrait<InnerType>: Future<Output = InnerType>
|
||||
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 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
|
||||
if ctxt.may_break {
|
||||
ctxt.break_ty
|
||||
} else {
|
||||
Ty::simple(TypeCtor::Never)
|
||||
Ty::Never
|
||||
}
|
||||
}
|
||||
Expr::While { condition, body, label } => {
|
||||
@ -206,10 +200,7 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
|
||||
label: label.map(|label| self.body[label].name.clone()),
|
||||
});
|
||||
// while let is desugared to a match loop, so this is always simple while
|
||||
self.infer_expr(
|
||||
*condition,
|
||||
&Expectation::has_type(Ty::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 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
|
||||
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 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
|
||||
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 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
|
||||
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 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
|
||||
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 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
|
||||
expr: tgt_expr,
|
||||
});
|
||||
}
|
||||
|
||||
Ty::simple(TypeCtor::Never)
|
||||
Ty::Never
|
||||
}
|
||||
Expr::Return { expr } => {
|
||||
if let Some(expr) = expr {
|
||||
@ -380,14 +368,14 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
|
||||
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 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
|
||||
|
||||
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 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
|
||||
},
|
||||
)
|
||||
.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 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
|
||||
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 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
|
||||
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 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
|
||||
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 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
|
||||
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 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
|
||||
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 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
|
||||
}
|
||||
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 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
|
||||
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 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
|
||||
);
|
||||
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 @@ fn infer_method_call(
|
||||
// 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 @@ fn substs_for_method_call(
|
||||
}
|
||||
|
||||
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 =
|
||||
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 = a_ty
|
||||
.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(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
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 @@ fn infer_tuple_struct_pat(
|
||||
}
|
||||
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 @@ fn infer_record_pat(
|
||||
|
||||
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 @@ pub(super) fn infer_pat(
|
||||
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 @@ pub(super) fn infer_pat(
|
||||
_ => &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 @@ pub(super) fn infer_pat(
|
||||
|
||||
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 @@ pub(super) fn infer_pat(
|
||||
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 @@ pub(super) fn infer_pat(
|
||||
};
|
||||
|
||||
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,
|
||||
},
|
||||
|
@ -9,7 +9,7 @@
|
||||
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 @@ fn unify_inner(&mut self, ty1: &Ty, ty2: &Ty, depth: usize) -> bool {
|
||||
// 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 @@ pub(super) fn unify_inner_trivial(&mut self, ty1: &Ty, ty2: &Ty, depth: usize) -
|
||||
| (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
|
||||
|
@ -25,7 +25,7 @@ macro_rules! eprintln {
|
||||
|
||||
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)<T>`.
|
||||
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<CrateId> {
|
||||
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<GenericDefId> {
|
||||
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 @@ fn walk_mut_binders(
|
||||
/// 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)<T>`.
|
||||
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 `<P0 as Trait<P1..Pn>>::Foo`. Note that the
|
||||
@ -420,10 +304,6 @@ pub(crate) fn build_for_generics(generic_params: &Generics) -> SubstsBuilder {
|
||||
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 @@ fn walk_mut_binders(
|
||||
}
|
||||
|
||||
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 @@ pub fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)> {
|
||||
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 @@ pub fn strip_references(&self) -> &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<GenericDefId> {
|
||||
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 @@ pub fn dyn_trait(&self) -> Option<TraitId> {
|
||||
|
||||
fn builtin_deref(&self) -> Option<Ty> {
|
||||
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<FunctionId> {
|
||||
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<FnSig> {
|
||||
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: parameters, .. } => {
|
||||
Some(FnSig::from_fn_ptr_substs(¶meters, *is_varargs))
|
||||
}
|
||||
Ty::FnDef(def, 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,69 @@ pub fn callable_sig(&self, db: &dyn HirDatabase) -> Option<FnSig> {
|
||||
/// 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<u32>` 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<u32>`, this returns the `u32`.
|
||||
pub fn substs(&self) -> Option<Substs> {
|
||||
pub fn substs(&self) -> Option<&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 substs_mut(&mut self) -> Option<&mut 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 impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<GenericPredicate>> {
|
||||
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 +868,7 @@ pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<GenericPredi
|
||||
|
||||
pub fn associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<TraitId> {
|
||||
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 +983,6 @@ fn shift_bound_vars(self, n: DebruijnIndex) -> Self
|
||||
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 +998,13 @@ fn walk(&self, f: &mut impl FnMut(&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 +1015,6 @@ fn walk_mut_binders(
|
||||
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 +1026,11 @@ fn walk_mut_binders(
|
||||
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);
|
||||
}
|
||||
|
@ -33,7 +33,7 @@
|
||||
},
|
||||
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 @@ pub fn from_hir(ctx: &TyLoweringContext<'_>, type_ref: &TypeRef) -> Self {
|
||||
pub fn from_hir_ext(ctx: &TyLoweringContext<'_>, type_ref: &TypeRef) -> (Self, Option<TypeNs>) {
|
||||
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 @@ pub fn from_hir_ext(ctx: &TyLoweringContext<'_>, type_ref: &TypeRef) -> (Self, O
|
||||
}
|
||||
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 @@ pub(crate) fn from_partly_resolved_hir_path(
|
||||
// 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<Ty> {
|
||||
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<T
|
||||
}
|
||||
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))
|
||||
}
|
||||
|
||||
fn fn_sig_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) -> 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<Ty> {
|
||||
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<Ty> {
|
||||
@ -1109,7 +1102,7 @@ fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> {
|
||||
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));
|
||||
|
@ -7,8 +7,8 @@
|
||||
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 @@
|
||||
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<TyFingerprint> {
|
||||
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 @@ macro_rules! lang_item_crate {
|
||||
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<Canonical<Ty>> {
|
||||
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
|
||||
|
@ -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,
|
||||
},
|
||||
|
@ -20,7 +20,7 @@
|
||||
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<StructDatum> {
|
||||
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| {
|
||||
|
@ -16,9 +16,8 @@
|
||||
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<Interner>;
|
||||
fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty<Interner> {
|
||||
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 @@ fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty<Interner> {
|
||||
fn from_chalk(db: &dyn HirDatabase, chalk: chalk_ir::Ty<Interner>) -> 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 @@ fn from_chalk(db: &dyn HirDatabase, chalk: chalk_ir::Ty<Interner>) -> Self {
|
||||
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 @@ fn from_chalk(db: &dyn HirDatabase, chalk: chalk_ir::Ty<Interner>) -> Self {
|
||||
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::<TypeAliasAsAssocType, _>(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::<TypeAliasAsAssocType, _>(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::<TypeAliasAsForeignType, _>(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<Interner>,
|
||||
) -> 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(
|
||||
|
Loading…
Reference in New Issue
Block a user