pub fn remove_ref(&self) -> Option<Type> {
match &self.ty.value.interned(&Interner) {
- TyKind::Ref(.., substs) => Some(self.derived(substs[0].clone())),
+ TyKind::Ref(.., ty) => Some(self.derived(ty.clone())),
_ => None,
}
}
return go(&self.ty.value);
fn go(ty: &Ty) -> bool {
- if ty.is_unknown() {
- true
- } else {
- ty.substs().map_or(false, |substs| substs.iter().any(go))
+ match ty.interned(&Interner) {
+ TyKind::Unknown => true,
+
+ TyKind::Adt(_, substs)
+ | TyKind::AssociatedType(_, substs)
+ | TyKind::Tuple(_, substs)
+ | TyKind::OpaqueType(_, substs)
+ | TyKind::FnDef(_, substs)
+ | TyKind::Closure(_, substs) => substs.iter().any(go),
+
+ TyKind::Array(ty) | TyKind::Slice(ty) | TyKind::Raw(_, ty) | TyKind::Ref(_, ty) => {
+ go(ty)
+ }
+
+ TyKind::Scalar(_)
+ | TyKind::Str
+ | TyKind::Never
+ | TyKind::Placeholder(_)
+ | TyKind::BoundVar(_)
+ | TyKind::InferenceVar(_, _)
+ | TyKind::Dyn(_)
+ | TyKind::Function(_)
+ | TyKind::Alias(_)
+ | TyKind::ForeignType(_) => false,
}
}
}
walk_bounds(db, &type_.derived(ty.clone()), bounds.as_ref(), cb);
}
+ TyKind::Ref(_, ty) | TyKind::Raw(_, ty) | TyKind::Array(ty) | TyKind::Slice(ty) => {
+ walk_type(db, &type_.derived(ty.clone()), cb);
+ }
+
_ => {}
}
if let Some(substs) = ty.substs() {
&TyKind::Scalar(Scalar::Float(t)) => write!(f, "{}", primitive::float_ty_to_string(t))?,
&TyKind::Scalar(Scalar::Int(t)) => write!(f, "{}", primitive::int_ty_to_string(t))?,
&TyKind::Scalar(Scalar::Uint(t)) => write!(f, "{}", primitive::uint_ty_to_string(t))?,
- TyKind::Slice(parameters) => {
- let t = parameters.as_single();
+ TyKind::Slice(t) => {
write!(f, "[")?;
t.hir_fmt(f)?;
write!(f, "]")?;
}
- TyKind::Array(parameters) => {
- let t = parameters.as_single();
+ TyKind::Array(t) => {
write!(f, "[")?;
t.hir_fmt(f)?;
write!(f, "; _]")?;
}
- TyKind::Raw(m, parameters) | TyKind::Ref(m, parameters) => {
- let t = parameters.as_single();
+ TyKind::Raw(m, t) | TyKind::Ref(m, t) => {
let ty_display =
t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target);
// Auto Deref if cannot coerce
match (from_ty.interned(&Interner), to_ty.interned(&Interner)) {
// FIXME: DerefMut
- (TyKind::Ref(_, st1), TyKind::Ref(_, st2)) => {
- self.unify_autoderef_behind_ref(&st1[0], &st2[0])
- }
+ (TyKind::Ref(_, st1), TyKind::Ref(_, st2)) => self.unify_autoderef_behind_ref(st1, st2),
// Otherwise, normal unify
_ => self.unify(&from_ty, to_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,
- };
+ return self.table.unify(&from_ty, &to_ty);
} else if self.table.unify_inner_trivial(&derefed_ty, &to_ty, 0) {
return true;
}
};
let inner_ty = self.infer_expr_inner(*expr, &expectation);
match rawness {
- Rawness::RawPtr => TyKind::Raw(mutability, Substs::single(inner_ty)),
- Rawness::Ref => TyKind::Ref(mutability, Substs::single(inner_ty)),
+ Rawness::RawPtr => TyKind::Raw(mutability, inner_ty),
+ Rawness::Ref => TyKind::Ref(mutability, inner_ty),
}
.intern(&Interner)
}
}
Expr::Array(array) => {
let elem_ty = match expected.ty.interned(&Interner) {
- TyKind::Array(st) | TyKind::Slice(st) => st.as_single().clone(),
+ TyKind::Array(st) | TyKind::Slice(st) => st.clone(),
_ => self.table.new_type_var(),
};
}
}
- TyKind::Array(Substs::single(elem_ty)).intern(&Interner)
+ TyKind::Array(elem_ty).intern(&Interner)
}
Expr::Literal(lit) => match lit {
Literal::Bool(..) => TyKind::Scalar(Scalar::Bool).intern(&Interner),
Literal::String(..) => {
- TyKind::Ref(Mutability::Not, Substs::single(TyKind::Str.intern(&Interner)))
- .intern(&Interner)
+ TyKind::Ref(Mutability::Not, TyKind::Str.intern(&Interner)).intern(&Interner)
}
Literal::ByteString(..) => {
let byte_type = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(&Interner);
- let array_type = TyKind::Array(Substs::single(byte_type)).intern(&Interner);
- TyKind::Ref(Mutability::Not, Substs::single(array_type)).intern(&Interner)
+ let array_type = TyKind::Array(byte_type).intern(&Interner);
+ TyKind::Ref(Mutability::Not, array_type).intern(&Interner)
}
Literal::Char(..) => TyKind::Scalar(Scalar::Char).intern(&Interner),
Literal::Int(_v, ty) => match ty {
// Apply autoref so the below unification works correctly
// FIXME: return correct autorefs from lookup_method
let actual_receiver_ty = match expected_receiver_ty.as_reference() {
- Some((_, mutability)) => {
- TyKind::Ref(mutability, Substs::single(derefed_receiver_ty)).intern(&Interner)
- }
+ Some((_, mutability)) => TyKind::Ref(mutability, derefed_receiver_ty).intern(&Interner),
_ => derefed_receiver_ty,
};
self.unify(&expected_receiver_ty, &actual_receiver_ty);
_ => self.result.standard_types.unknown.clone(),
};
let subty = self.infer_pat(*pat, &expectation, default_bm);
- TyKind::Ref(mutability, Substs::single(subty)).intern(&Interner)
+ TyKind::Ref(mutability, subty).intern(&Interner)
}
Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat(
p.as_ref(),
let bound_ty = match mode {
BindingMode::Ref(mutability) => {
- TyKind::Ref(mutability, Substs::single(inner_ty.clone())).intern(&Interner)
+ TyKind::Ref(mutability, inner_ty.clone()).intern(&Interner)
}
BindingMode::Move => inner_ty.clone(),
};
}
Pat::Slice { prefix, slice, suffix } => {
let (container_ty, elem_ty): (fn(_) -> _, _) = match expected.interned(&Interner) {
- TyKind::Array(st) => (TyKind::Array, st.as_single().clone()),
- TyKind::Slice(st) => (TyKind::Slice, st.as_single().clone()),
+ TyKind::Array(st) => (TyKind::Array, st.clone()),
+ TyKind::Slice(st) => (TyKind::Slice, st.clone()),
_ => (TyKind::Slice, self.err_ty()),
};
self.infer_pat(*pat_id, &elem_ty, default_bm);
}
- let pat_ty = container_ty(Substs::single(elem_ty)).intern(&Interner);
+ let pat_ty = container_ty(elem_ty).intern(&Interner);
if let Some(slice_pat_id) = slice {
self.infer_pat(*slice_pat_id, &pat_ty, default_bm);
}
use super::{InferenceContext, Obligation};
use crate::{
- BoundVar, Canonical, DebruijnIndex, GenericPredicate, InEnvironment, InferenceVar, Interner,
- Scalar, Substs, Ty, TyKind, TypeWalk,
+ BoundVar, Canonical, DebruijnIndex, FnPointer, GenericPredicate, InEnvironment, InferenceVar,
+ Interner, Scalar, Substs, Ty, TyKind, TypeWalk,
};
impl<'a> InferenceContext<'a> {
let ty1 = self.resolve_ty_shallow(ty1);
let ty2 = self.resolve_ty_shallow(ty2);
if ty1.equals_ctor(&ty2) {
- match (ty1.substs(), ty2.substs()) {
- (Some(st1), Some(st2)) => self.unify_substs(st1, st2, depth + 1),
- (None, None) => true,
+ match (ty1.interned(&Interner), ty2.interned(&Interner)) {
+ (TyKind::Adt(_, substs1), TyKind::Adt(_, substs2))
+ | (TyKind::FnDef(_, substs1), TyKind::FnDef(_, substs2))
+ | (
+ TyKind::Function(FnPointer { substs: substs1, .. }),
+ TyKind::Function(FnPointer { substs: substs2, .. }),
+ )
+ | (TyKind::Tuple(_, substs1), TyKind::Tuple(_, substs2))
+ | (TyKind::OpaqueType(_, substs1), TyKind::OpaqueType(_, substs2))
+ | (TyKind::AssociatedType(_, substs1), TyKind::AssociatedType(_, substs2))
+ | (TyKind::Closure(.., substs1), TyKind::Closure(.., substs2)) => {
+ self.unify_substs(substs1, substs2, depth + 1)
+ }
+ (TyKind::Ref(_, ty1), TyKind::Ref(_, ty2))
+ | (TyKind::Raw(_, ty1), TyKind::Raw(_, ty2))
+ | (TyKind::Array(ty1), TyKind::Array(ty2))
+ | (TyKind::Slice(ty1), TyKind::Slice(ty2)) => self.unify_inner(ty1, ty2, depth + 1),
_ => false,
}
} else {
Tuple(usize, Substs),
/// An array with the given length. Written as `[T; n]`.
- Array(Substs),
+ Array(Ty),
/// The pointee of an array slice. Written as `[T]`.
- Slice(Substs),
+ Slice(Ty),
/// A raw pointer. Written as `*mut T` or `*const T`
- Raw(Mutability, Substs),
+ Raw(Mutability, Ty),
/// A reference; a pointer with an associated lifetime. Written as
/// `&'a mut T` or `&'a T`.
- Ref(Mutability, Substs),
+ Ref(Mutability, Ty),
/// 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
pub fn as_reference(&self) -> Option<(&Ty, Mutability)> {
match self.interned(&Interner) {
- TyKind::Ref(mutability, parameters) => Some((parameters.as_single(), *mutability)),
+ TyKind::Ref(mutability, ty) => Some((ty, *mutability)),
_ => None,
}
}
pub fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)> {
match self.interned(&Interner) {
- TyKind::Ref(mutability, parameters) => {
- Some((parameters.as_single(), Rawness::Ref, *mutability))
- }
- TyKind::Raw(mutability, parameters) => {
- Some((parameters.as_single(), Rawness::RawPtr, *mutability))
- }
+ TyKind::Ref(mutability, ty) => Some((ty, Rawness::Ref, *mutability)),
+ TyKind::Raw(mutability, ty) => Some((ty, Rawness::RawPtr, *mutability)),
_ => None,
}
}
pub fn strip_references(&self) -> &Ty {
let mut t: &Ty = self;
- while let TyKind::Ref(_mutability, parameters) = t.interned(&Interner) {
- t = parameters.as_single();
+ while let TyKind::Ref(_mutability, ty) = t.interned(&Interner) {
+ t = ty;
}
t
fn builtin_deref(&self) -> Option<Ty> {
match self.interned(&Interner) {
- TyKind::Ref(.., parameters) => Some(Ty::clone(parameters.as_single())),
- TyKind::Raw(.., parameters) => Some(Ty::clone(parameters.as_single())),
+ TyKind::Ref(.., ty) => Some(ty.clone()),
+ TyKind::Raw(.., ty) => Some(ty.clone()),
_ => None,
}
}
}
}
- /// If this is a type with type parameters (an ADT or function), replaces
- /// 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(mut self, new_substs: Substs) -> Ty {
- match self.interned_mut() {
- TyKind::Adt(_, substs)
- | TyKind::Slice(substs)
- | TyKind::Array(substs)
- | TyKind::Raw(_, substs)
- | TyKind::Ref(_, substs)
- | TyKind::FnDef(_, substs)
- | TyKind::Function(FnPointer { substs, .. })
- | TyKind::Tuple(_, substs)
- | TyKind::OpaqueType(_, substs)
- | TyKind::AssociatedType(_, substs)
- | TyKind::Closure(.., substs) => {
- assert_eq!(substs.len(), new_substs.len());
- *substs = new_substs;
- }
- _ => (),
- }
- 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> {
match self.interned(&Interner) {
TyKind::Adt(_, substs)
- | TyKind::Slice(substs)
- | TyKind::Array(substs)
- | TyKind::Raw(_, substs)
- | TyKind::Ref(_, substs)
| TyKind::FnDef(_, substs)
| TyKind::Function(FnPointer { substs, .. })
| TyKind::Tuple(_, substs)
}
}
- pub fn substs_mut(&mut self) -> Option<&mut Substs> {
+ fn substs_mut(&mut self) -> Option<&mut Substs> {
match self.interned_mut() {
TyKind::Adt(_, substs)
- | TyKind::Slice(substs)
- | TyKind::Array(substs)
- | TyKind::Raw(_, substs)
- | TyKind::Ref(_, substs)
| TyKind::FnDef(_, substs)
| TyKind::Function(FnPointer { substs, .. })
| TyKind::Tuple(_, substs)
p.walk(f);
}
}
+ TyKind::Slice(ty) | TyKind::Array(ty) | TyKind::Ref(_, ty) | TyKind::Raw(_, ty) => {
+ ty.walk(f);
+ }
_ => {
if let Some(substs) = self.substs() {
for t in substs.iter() {
TyKind::Alias(AliasTy::Opaque(o_ty)) => {
o_ty.substitution.walk_mut_binders(f, binders);
}
+ TyKind::Slice(ty) | TyKind::Array(ty) | TyKind::Ref(_, ty) | TyKind::Raw(_, ty) => {
+ ty.walk_mut_binders(f, binders);
+ }
_ => {
if let Some(substs) = self.substs_mut() {
substs.walk_mut_binders(f, binders);
}
TypeRef::RawPtr(inner, mutability) => {
let inner_ty = self.lower_ty(inner);
- TyKind::Raw(lower_to_chalk_mutability(*mutability), Substs::single(inner_ty))
- .intern(&Interner)
+ TyKind::Raw(lower_to_chalk_mutability(*mutability), inner_ty).intern(&Interner)
}
TypeRef::Array(inner) => {
let inner_ty = self.lower_ty(inner);
- TyKind::Array(Substs::single(inner_ty)).intern(&Interner)
+ TyKind::Array(inner_ty).intern(&Interner)
}
TypeRef::Slice(inner) => {
let inner_ty = self.lower_ty(inner);
- TyKind::Slice(Substs::single(inner_ty)).intern(&Interner)
+ TyKind::Slice(inner_ty).intern(&Interner)
}
TypeRef::Reference(inner, _, mutability) => {
let inner_ty = self.lower_ty(inner);
- TyKind::Ref(lower_to_chalk_mutability(*mutability), Substs::single(inner_ty))
- .intern(&Interner)
+ TyKind::Ref(lower_to_chalk_mutability(*mutability), inner_ty).intern(&Interner)
}
TypeRef::Placeholder => TyKind::Unknown.intern(&Interner),
TypeRef::Fn(params, is_varargs) => {
}
let refed = Canonical {
kinds: deref_chain[0].kinds.clone(),
- value: TyKind::Ref(Mutability::Not, Substs::single(deref_chain[0].value.clone()))
- .intern(&Interner),
+ value: TyKind::Ref(Mutability::Not, deref_chain[0].value.clone()).intern(&Interner),
};
if iterate_method_candidates_by_receiver(
&refed,
}
let ref_muted = Canonical {
kinds: deref_chain[0].kinds.clone(),
- value: TyKind::Ref(Mutability::Mut, Substs::single(deref_chain[0].value.clone()))
- .intern(&Interner),
+ value: TyKind::Ref(Mutability::Mut, deref_chain[0].value.clone()).intern(&Interner),
};
if iterate_method_candidates_by_receiver(
&ref_muted,
type Chalk = chalk_ir::Ty<Interner>;
fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty<Interner> {
match self.into_inner() {
- TyKind::Ref(m, parameters) => ref_to_chalk(db, m, parameters),
- TyKind::Array(parameters) => array_to_chalk(db, parameters),
+ TyKind::Ref(m, ty) => ref_to_chalk(db, m, ty),
+ TyKind::Array(ty) => array_to_chalk(db, ty),
TyKind::Function(FnPointer { sig, substs, .. }) => {
let substitution = chalk_ir::FnSubst(substs.to_chalk(db).shifted_in(&Interner));
chalk_ir::TyKind::Function(chalk_ir::FnPointer {
let substitution = substs.to_chalk(db);
chalk_ir::TyKind::Tuple(cardinality.into(), substitution).intern(&Interner)
}
- TyKind::Raw(mutability, substs) => {
- let ty = substs[0].clone().to_chalk(db);
+ TyKind::Raw(mutability, ty) => {
+ let ty = ty.to_chalk(db);
chalk_ir::TyKind::Raw(mutability, ty).intern(&Interner)
}
- TyKind::Slice(substs) => {
- chalk_ir::TyKind::Slice(substs[0].clone().to_chalk(db)).intern(&Interner)
- }
+ TyKind::Slice(ty) => chalk_ir::TyKind::Slice(ty.to_chalk(db)).intern(&Interner),
TyKind::Str => chalk_ir::TyKind::Str.intern(&Interner),
TyKind::FnDef(id, substs) => {
let substitution = substs.to_chalk(db);
fn from_chalk(db: &dyn HirDatabase, chalk: chalk_ir::Ty<Interner>) -> Self {
match chalk.data(&Interner).kind.clone() {
chalk_ir::TyKind::Error => TyKind::Unknown,
- chalk_ir::TyKind::Array(ty, _size) => TyKind::Array(Substs::single(from_chalk(db, ty))),
+ chalk_ir::TyKind::Array(ty, _size) => TyKind::Array(from_chalk(db, ty)),
chalk_ir::TyKind::Placeholder(idx) => TyKind::Placeholder(idx),
chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Projection(proj)) => {
let associated_ty = proj.associated_ty_id;
chalk_ir::TyKind::Tuple(cardinality, subst) => {
TyKind::Tuple(cardinality, from_chalk(db, subst))
}
- chalk_ir::TyKind::Raw(mutability, ty) => {
- TyKind::Raw(mutability, Substs::single(from_chalk(db, ty)))
- }
- chalk_ir::TyKind::Slice(ty) => TyKind::Slice(Substs::single(from_chalk(db, ty))),
+ chalk_ir::TyKind::Raw(mutability, ty) => TyKind::Raw(mutability, from_chalk(db, ty)),
+ chalk_ir::TyKind::Slice(ty) => TyKind::Slice(from_chalk(db, ty)),
chalk_ir::TyKind::Ref(mutability, _lifetime, ty) => {
- TyKind::Ref(mutability, Substs::single(from_chalk(db, ty)))
+ TyKind::Ref(mutability, from_chalk(db, ty))
}
chalk_ir::TyKind::Str => TyKind::Str,
chalk_ir::TyKind::Never => TyKind::Never,
fn ref_to_chalk(
db: &dyn HirDatabase,
mutability: chalk_ir::Mutability,
- subst: Substs,
+ ty: Ty,
) -> chalk_ir::Ty<Interner> {
- let arg = subst[0].clone().to_chalk(db);
+ let arg = ty.to_chalk(db);
let lifetime = LifetimeData::Static.intern(&Interner);
chalk_ir::TyKind::Ref(mutability, lifetime, arg).intern(&Interner)
}
/// We currently don't model constants, but Chalk does. So, we have to insert a
/// fake constant here, because Chalks built-in logic may expect it to be there.
-fn array_to_chalk(db: &dyn HirDatabase, subst: Substs) -> chalk_ir::Ty<Interner> {
- let arg = subst[0].clone().to_chalk(db);
+fn array_to_chalk(db: &dyn HirDatabase, ty: Ty) -> chalk_ir::Ty<Interner> {
+ let arg = ty.to_chalk(db);
let usize_ty = chalk_ir::TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner);
let const_ = chalk_ir::ConstData {
ty: usize_ty,