8018: Make Ty wrap TyKind in an Arc r=flodiebold a=flodiebold

... to further move towards Chalk.

This is a bit of a slowdown (218ginstr vs 213ginstr for inference on RA), even though it allows us to unwrap the Substs in `TyKind::Ref` etc..

Co-authored-by: Florian Diebold <flodiebold@gmail.com>
This commit is contained in:
bors[bot] 2021-03-15 12:51:27 +00:00 committed by GitHub
commit 6139bd7649
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 155 additions and 142 deletions

View file

@ -1597,7 +1597,7 @@ impl Type {
pub fn remove_ref(&self) -> Option<Type> { pub fn remove_ref(&self) -> Option<Type> {
match &self.ty.value.interned(&Interner) { match &self.ty.value.interned(&Interner) {
TyKind::Ref(.., substs) => Some(self.derived(substs[0].clone())), TyKind::Ref(.., ty) => Some(self.derived(ty.clone())),
_ => None, _ => None,
} }
} }
@ -1751,10 +1751,30 @@ impl Type {
return go(&self.ty.value); return go(&self.ty.value);
fn go(ty: &Ty) -> bool { fn go(ty: &Ty) -> bool {
if ty.is_unknown() { match ty.interned(&Interner) {
true TyKind::Unknown => true,
} else {
ty.substs().map_or(false, |substs| substs.iter().any(go)) 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,
} }
} }
} }
@ -1989,6 +2009,10 @@ impl Type {
walk_bounds(db, &type_.derived(ty.clone()), bounds.as_ref(), cb); 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() { if let Some(substs) = ty.substs() {

View file

@ -276,20 +276,17 @@ impl HirDisplay for Ty {
&TyKind::Scalar(Scalar::Float(t)) => write!(f, "{}", primitive::float_ty_to_string(t))?, &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::Int(t)) => write!(f, "{}", primitive::int_ty_to_string(t))?,
&TyKind::Scalar(Scalar::Uint(t)) => write!(f, "{}", primitive::uint_ty_to_string(t))?, &TyKind::Scalar(Scalar::Uint(t)) => write!(f, "{}", primitive::uint_ty_to_string(t))?,
TyKind::Slice(parameters) => { TyKind::Slice(t) => {
let t = parameters.as_single();
write!(f, "[")?; write!(f, "[")?;
t.hir_fmt(f)?; t.hir_fmt(f)?;
write!(f, "]")?; write!(f, "]")?;
} }
TyKind::Array(parameters) => { TyKind::Array(t) => {
let t = parameters.as_single();
write!(f, "[")?; write!(f, "[")?;
t.hir_fmt(f)?; t.hir_fmt(f)?;
write!(f, "; _]")?; write!(f, "; _]")?;
} }
TyKind::Raw(m, parameters) | TyKind::Ref(m, parameters) => { TyKind::Raw(m, t) | TyKind::Ref(m, t) => {
let t = parameters.as_single();
let ty_display = let ty_display =
t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target); t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target);

View file

@ -108,6 +108,17 @@ pub struct TypeMismatch {
pub actual: Ty, pub actual: Ty,
} }
#[derive(Clone, PartialEq, Eq, Debug)]
struct InternedStandardTypes {
unknown: Ty,
}
impl Default for InternedStandardTypes {
fn default() -> Self {
InternedStandardTypes { unknown: TyKind::Unknown.intern(&Interner) }
}
}
/// The result of type inference: A mapping from expressions and patterns to types. /// The result of type inference: A mapping from expressions and patterns to types.
#[derive(Clone, PartialEq, Eq, Debug, Default)] #[derive(Clone, PartialEq, Eq, Debug, Default)]
pub struct InferenceResult { pub struct InferenceResult {
@ -126,6 +137,8 @@ pub struct InferenceResult {
pub type_of_expr: ArenaMap<ExprId, Ty>, pub type_of_expr: ArenaMap<ExprId, Ty>,
pub type_of_pat: ArenaMap<PatId, Ty>, pub type_of_pat: ArenaMap<PatId, Ty>,
pub(super) type_mismatches: ArenaMap<ExprId, TypeMismatch>, pub(super) type_mismatches: ArenaMap<ExprId, TypeMismatch>,
/// Interned Unknown to return references to.
standard_types: InternedStandardTypes,
} }
impl InferenceResult { impl InferenceResult {
@ -170,7 +183,7 @@ impl Index<ExprId> for InferenceResult {
type Output = Ty; type Output = Ty;
fn index(&self, expr: ExprId) -> &Ty { fn index(&self, expr: ExprId) -> &Ty {
self.type_of_expr.get(expr).unwrap_or(&Ty(TyKind::Unknown)) self.type_of_expr.get(expr).unwrap_or(&self.standard_types.unknown)
} }
} }
@ -178,7 +191,7 @@ impl Index<PatId> for InferenceResult {
type Output = Ty; type Output = Ty;
fn index(&self, pat: PatId) -> &Ty { fn index(&self, pat: PatId) -> &Ty {
self.type_of_pat.get(pat).unwrap_or(&Ty(TyKind::Unknown)) self.type_of_pat.get(pat).unwrap_or(&self.standard_types.unknown)
} }
} }
@ -723,14 +736,19 @@ impl Expectation {
/// This expresses no expectation on the type. /// This expresses no expectation on the type.
fn none() -> Self { fn none() -> Self {
Expectation { ty: TyKind::Unknown.intern(&Interner), rvalue_hint: false } Expectation {
// FIXME
ty: TyKind::Unknown.intern(&Interner),
rvalue_hint: false,
}
} }
fn coercion_target(&self) -> &Ty { fn coercion_target(&self) -> Ty {
if self.rvalue_hint { if self.rvalue_hint {
&Ty(TyKind::Unknown) // FIXME
TyKind::Unknown.intern(&Interner)
} else { } else {
&self.ty self.ty.clone()
} }
} }
} }

View file

@ -71,7 +71,7 @@ impl<'a> InferenceContext<'a> {
} }
// Pointer weakening and function to pointer // Pointer weakening and function to pointer
match (&mut from_ty.0, to_ty.interned(&Interner)) { match (from_ty.interned_mut(), to_ty.interned(&Interner)) {
// `*mut T` -> `*const T` // `*mut T` -> `*const T`
// `&mut T` -> `&T` // `&mut T` -> `&T`
(TyKind::Raw(m1, ..), TyKind::Raw(m2 @ Mutability::Not, ..)) (TyKind::Raw(m1, ..), TyKind::Raw(m2 @ Mutability::Not, ..))
@ -111,9 +111,7 @@ impl<'a> InferenceContext<'a> {
// Auto Deref if cannot coerce // Auto Deref if cannot coerce
match (from_ty.interned(&Interner), to_ty.interned(&Interner)) { match (from_ty.interned(&Interner), to_ty.interned(&Interner)) {
// FIXME: DerefMut // FIXME: DerefMut
(TyKind::Ref(_, st1), TyKind::Ref(_, st2)) => { (TyKind::Ref(_, st1), TyKind::Ref(_, st2)) => self.unify_autoderef_behind_ref(st1, st2),
self.unify_autoderef_behind_ref(&st1[0], &st2[0])
}
// Otherwise, normal unify // Otherwise, normal unify
_ => self.unify(&from_ty, to_ty), _ => self.unify(&from_ty, to_ty),
@ -178,11 +176,7 @@ impl<'a> InferenceContext<'a> {
// Stop when constructor matches. // Stop when constructor matches.
if from_ty.equals_ctor(&to_ty) { if from_ty.equals_ctor(&to_ty) {
// It will not recurse to `coerce`. // It will not recurse to `coerce`.
return match (from_ty.substs(), to_ty.substs()) { return self.table.unify(&from_ty, &to_ty);
(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) { } else if self.table.unify_inner_trivial(&derefed_ty, &to_ty, 0) {
return true; return true;
} }

View file

@ -503,8 +503,8 @@ impl<'a> InferenceContext<'a> {
}; };
let inner_ty = self.infer_expr_inner(*expr, &expectation); let inner_ty = self.infer_expr_inner(*expr, &expectation);
match rawness { match rawness {
Rawness::RawPtr => TyKind::Raw(mutability, Substs::single(inner_ty)), Rawness::RawPtr => TyKind::Raw(mutability, inner_ty),
Rawness::Ref => TyKind::Ref(mutability, Substs::single(inner_ty)), Rawness::Ref => TyKind::Ref(mutability, inner_ty),
} }
.intern(&Interner) .intern(&Interner)
} }
@ -685,7 +685,7 @@ impl<'a> InferenceContext<'a> {
} }
Expr::Array(array) => { Expr::Array(array) => {
let elem_ty = match expected.ty.interned(&Interner) { 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(), _ => self.table.new_type_var(),
}; };
@ -709,18 +709,17 @@ impl<'a> InferenceContext<'a> {
} }
} }
TyKind::Array(Substs::single(elem_ty)).intern(&Interner) TyKind::Array(elem_ty).intern(&Interner)
} }
Expr::Literal(lit) => match lit { Expr::Literal(lit) => match lit {
Literal::Bool(..) => TyKind::Scalar(Scalar::Bool).intern(&Interner), Literal::Bool(..) => TyKind::Scalar(Scalar::Bool).intern(&Interner),
Literal::String(..) => { Literal::String(..) => {
TyKind::Ref(Mutability::Not, Substs::single(TyKind::Str.intern(&Interner))) TyKind::Ref(Mutability::Not, TyKind::Str.intern(&Interner)).intern(&Interner)
.intern(&Interner)
} }
Literal::ByteString(..) => { Literal::ByteString(..) => {
let byte_type = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(&Interner); let byte_type = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(&Interner);
let array_type = TyKind::Array(Substs::single(byte_type)).intern(&Interner); let array_type = TyKind::Array(byte_type).intern(&Interner);
TyKind::Ref(Mutability::Not, Substs::single(array_type)).intern(&Interner) TyKind::Ref(Mutability::Not, array_type).intern(&Interner)
} }
Literal::Char(..) => TyKind::Scalar(Scalar::Char).intern(&Interner), Literal::Char(..) => TyKind::Scalar(Scalar::Char).intern(&Interner),
Literal::Int(_v, ty) => match ty { Literal::Int(_v, ty) => match ty {
@ -799,7 +798,7 @@ impl<'a> InferenceContext<'a> {
// we don't even make an attempt at coercion // we don't even make an attempt at coercion
self.table.new_maybe_never_var() self.table.new_maybe_never_var()
} else { } else {
self.coerce(&Ty::unit(), expected.coercion_target()); self.coerce(&Ty::unit(), &expected.coercion_target());
Ty::unit() Ty::unit()
} }
}; };
@ -854,9 +853,7 @@ impl<'a> InferenceContext<'a> {
// Apply autoref so the below unification works correctly // Apply autoref so the below unification works correctly
// FIXME: return correct autorefs from lookup_method // FIXME: return correct autorefs from lookup_method
let actual_receiver_ty = match expected_receiver_ty.as_reference() { let actual_receiver_ty = match expected_receiver_ty.as_reference() {
Some((_, mutability)) => { Some((_, mutability)) => TyKind::Ref(mutability, derefed_receiver_ty).intern(&Interner),
TyKind::Ref(mutability, Substs::single(derefed_receiver_ty)).intern(&Interner)
}
_ => derefed_receiver_ty, _ => derefed_receiver_ty,
}; };
self.unify(&expected_receiver_ty, &actual_receiver_ty); self.unify(&expected_receiver_ty, &actual_receiver_ty);

View file

@ -158,12 +158,12 @@ impl<'a> InferenceContext<'a> {
if mutability != exp_mut { if mutability != exp_mut {
// FIXME: emit type error? // FIXME: emit type error?
} }
inner_ty inner_ty.clone()
} }
_ => &Ty(TyKind::Unknown), _ => self.result.standard_types.unknown.clone(),
}; };
let subty = self.infer_pat(*pat, expectation, default_bm); 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( Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat(
p.as_ref(), p.as_ref(),
@ -196,7 +196,7 @@ impl<'a> InferenceContext<'a> {
let bound_ty = match mode { let bound_ty = match mode {
BindingMode::Ref(mutability) => { 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(), BindingMode::Move => inner_ty.clone(),
}; };
@ -206,8 +206,8 @@ impl<'a> InferenceContext<'a> {
} }
Pat::Slice { prefix, slice, suffix } => { Pat::Slice { prefix, slice, suffix } => {
let (container_ty, elem_ty): (fn(_) -> _, _) = match expected.interned(&Interner) { let (container_ty, elem_ty): (fn(_) -> _, _) = match expected.interned(&Interner) {
TyKind::Array(st) => (TyKind::Array, st.as_single().clone()), TyKind::Array(st) => (TyKind::Array, st.clone()),
TyKind::Slice(st) => (TyKind::Slice, st.as_single().clone()), TyKind::Slice(st) => (TyKind::Slice, st.clone()),
_ => (TyKind::Slice, self.err_ty()), _ => (TyKind::Slice, self.err_ty()),
}; };
@ -215,7 +215,7 @@ impl<'a> InferenceContext<'a> {
self.infer_pat(*pat_id, &elem_ty, default_bm); 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 { if let Some(slice_pat_id) = slice {
self.infer_pat(*slice_pat_id, &pat_ty, default_bm); self.infer_pat(*slice_pat_id, &pat_ty, default_bm);
} }
@ -232,11 +232,11 @@ impl<'a> InferenceContext<'a> {
Pat::Box { inner } => match self.resolve_boxed_box() { Pat::Box { inner } => match self.resolve_boxed_box() {
Some(box_adt) => { Some(box_adt) => {
let inner_expected = match expected.as_adt() { let inner_expected = match expected.as_adt() {
Some((adt, substs)) if adt == box_adt => substs.as_single(), Some((adt, substs)) if adt == box_adt => substs.as_single().clone(),
_ => &Ty(TyKind::Unknown), _ => self.result.standard_types.unknown.clone(),
}; };
let inner_ty = self.infer_pat(*inner, inner_expected, default_bm); let inner_ty = self.infer_pat(*inner, &inner_expected, default_bm);
Ty::adt_ty(box_adt, Substs::single(inner_ty)) Ty::adt_ty(box_adt, Substs::single(inner_ty))
} }
None => self.err_ty(), None => self.err_ty(),

View file

@ -7,8 +7,8 @@ use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
use super::{InferenceContext, Obligation}; use super::{InferenceContext, Obligation};
use crate::{ use crate::{
BoundVar, Canonical, DebruijnIndex, GenericPredicate, InEnvironment, InferenceVar, Interner, BoundVar, Canonical, DebruijnIndex, FnPointer, GenericPredicate, InEnvironment, InferenceVar,
Scalar, Substs, Ty, TyKind, TypeWalk, Interner, Scalar, Substs, Ty, TyKind, TypeWalk,
}; };
impl<'a> InferenceContext<'a> { impl<'a> InferenceContext<'a> {
@ -108,7 +108,7 @@ impl<T> Canonicalized<T> {
pub(super) fn decanonicalize_ty(&self, mut ty: Ty) -> Ty { pub(super) fn decanonicalize_ty(&self, mut ty: Ty) -> Ty {
ty.walk_mut_binders( ty.walk_mut_binders(
&mut |ty, binders| { &mut |ty, binders| {
if let &mut TyKind::BoundVar(bound) = &mut ty.0 { if let &mut TyKind::BoundVar(bound) = ty.interned_mut() {
if bound.debruijn >= binders { if bound.debruijn >= binders {
let (v, k) = self.free_vars[bound.index]; let (v, k) = self.free_vars[bound.index];
*ty = TyKind::InferenceVar(v, k).intern(&Interner); *ty = TyKind::InferenceVar(v, k).intern(&Interner);
@ -283,9 +283,23 @@ impl InferenceTable {
let ty1 = self.resolve_ty_shallow(ty1); let ty1 = self.resolve_ty_shallow(ty1);
let ty2 = self.resolve_ty_shallow(ty2); let ty2 = self.resolve_ty_shallow(ty2);
if ty1.equals_ctor(&ty2) { if ty1.equals_ctor(&ty2) {
match (ty1.substs(), ty2.substs()) { match (ty1.interned(&Interner), ty2.interned(&Interner)) {
(Some(st1), Some(st2)) => self.unify_substs(st1, st2, depth + 1), (TyKind::Adt(_, substs1), TyKind::Adt(_, substs2))
(None, None) => true, | (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, _ => false,
} }
} else { } else {
@ -404,7 +418,7 @@ impl InferenceTable {
if i > 0 { if i > 0 {
cov_mark::hit!(type_var_resolves_to_int_var); cov_mark::hit!(type_var_resolves_to_int_var);
} }
match &ty.0 { match ty.interned(&Interner) {
TyKind::InferenceVar(tv, _) => { TyKind::InferenceVar(tv, _) => {
let inner = tv.to_inner(); let inner = tv.to_inner();
match self.var_unification_table.inlined_probe_value(inner).known() { match self.var_unification_table.inlined_probe_value(inner).known() {

View file

@ -151,17 +151,17 @@ pub enum TyKind {
Tuple(usize, Substs), Tuple(usize, Substs),
/// An array with the given length. Written as `[T; n]`. /// An array with the given length. Written as `[T; n]`.
Array(Substs), Array(Ty),
/// The pointee of an array slice. Written as `[T]`. /// The pointee of an array slice. Written as `[T]`.
Slice(Substs), Slice(Ty),
/// A raw pointer. Written as `*mut T` or `*const T` /// 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 reference; a pointer with an associated lifetime. Written as
/// `&'a mut T` or `&'a T`. /// `&'a mut T` or `&'a T`.
Ref(Mutability, Substs), Ref(Mutability, Ty),
/// This represents a placeholder for an opaque type in situations where we /// 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 /// don't know the hidden type (i.e. currently almost always). This is
@ -248,11 +248,11 @@ pub enum TyKind {
} }
#[derive(Clone, PartialEq, Eq, Debug, Hash)] #[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct Ty(TyKind); pub struct Ty(Arc<TyKind>);
impl TyKind { impl TyKind {
pub fn intern(self, _interner: &Interner) -> Ty { pub fn intern(self, _interner: &Interner) -> Ty {
Ty(self) Ty(Arc::new(self))
} }
} }
@ -260,6 +260,14 @@ impl Ty {
pub fn interned(&self, _interner: &Interner) -> &TyKind { pub fn interned(&self, _interner: &Interner) -> &TyKind {
&self.0 &self.0
} }
pub fn interned_mut(&mut self) -> &mut TyKind {
Arc::make_mut(&mut self.0)
}
pub fn into_inner(self) -> TyKind {
Arc::try_unwrap(self.0).unwrap_or_else(|a| (*a).clone())
}
} }
/// A list of substitutions for generic parameters. /// A list of substitutions for generic parameters.
@ -665,19 +673,15 @@ impl Ty {
pub fn as_reference(&self) -> Option<(&Ty, Mutability)> { pub fn as_reference(&self) -> Option<(&Ty, Mutability)> {
match self.interned(&Interner) { match self.interned(&Interner) {
TyKind::Ref(mutability, parameters) => Some((parameters.as_single(), *mutability)), TyKind::Ref(mutability, ty) => Some((ty, *mutability)),
_ => None, _ => None,
} }
} }
pub fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)> { pub fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)> {
match self.interned(&Interner) { match self.interned(&Interner) {
TyKind::Ref(mutability, parameters) => { TyKind::Ref(mutability, ty) => Some((ty, Rawness::Ref, *mutability)),
Some((parameters.as_single(), Rawness::Ref, *mutability)) TyKind::Raw(mutability, ty) => Some((ty, Rawness::RawPtr, *mutability)),
}
TyKind::Raw(mutability, parameters) => {
Some((parameters.as_single(), Rawness::RawPtr, *mutability))
}
_ => None, _ => None,
} }
} }
@ -685,8 +689,8 @@ impl Ty {
pub fn strip_references(&self) -> &Ty { pub fn strip_references(&self) -> &Ty {
let mut t: &Ty = self; let mut t: &Ty = self;
while let TyKind::Ref(_mutability, parameters) = t.interned(&Interner) { while let TyKind::Ref(_mutability, ty) = t.interned(&Interner) {
t = parameters.as_single(); t = ty;
} }
t t
@ -772,8 +776,8 @@ impl Ty {
fn builtin_deref(&self) -> Option<Ty> { fn builtin_deref(&self) -> Option<Ty> {
match self.interned(&Interner) { match self.interned(&Interner) {
TyKind::Ref(.., parameters) => Some(Ty::clone(parameters.as_single())), TyKind::Ref(.., ty) => Some(ty.clone()),
TyKind::Raw(.., parameters) => Some(Ty::clone(parameters.as_single())), TyKind::Raw(.., ty) => Some(ty.clone()),
_ => None, _ => None,
} }
} }
@ -809,40 +813,11 @@ impl Ty {
} }
} }
/// 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 &mut self.0 {
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 /// 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`. /// 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.interned(&Interner) { match self.interned(&Interner) {
TyKind::Adt(_, substs) TyKind::Adt(_, substs)
| TyKind::Slice(substs)
| TyKind::Array(substs)
| TyKind::Raw(_, substs)
| TyKind::Ref(_, substs)
| TyKind::FnDef(_, substs) | TyKind::FnDef(_, substs)
| TyKind::Function(FnPointer { substs, .. }) | TyKind::Function(FnPointer { substs, .. })
| TyKind::Tuple(_, substs) | TyKind::Tuple(_, substs)
@ -853,13 +828,9 @@ impl Ty {
} }
} }
pub fn substs_mut(&mut self) -> Option<&mut Substs> { fn substs_mut(&mut self) -> Option<&mut Substs> {
match &mut self.0 { match self.interned_mut() {
TyKind::Adt(_, substs) TyKind::Adt(_, substs)
| TyKind::Slice(substs)
| TyKind::Array(substs)
| TyKind::Raw(_, substs)
| TyKind::Ref(_, substs)
| TyKind::FnDef(_, substs) | TyKind::FnDef(_, substs)
| TyKind::Function(FnPointer { substs, .. }) | TyKind::Function(FnPointer { substs, .. })
| TyKind::Tuple(_, substs) | TyKind::Tuple(_, substs)
@ -988,7 +959,7 @@ pub trait TypeWalk {
{ {
self.walk_mut_binders( self.walk_mut_binders(
&mut |ty_mut, binders| { &mut |ty_mut, binders| {
let ty = mem::replace(ty_mut, Ty(TyKind::Unknown)); let ty = mem::replace(ty_mut, TyKind::Unknown.intern(&Interner));
*ty_mut = f(ty, binders); *ty_mut = f(ty, binders);
}, },
binders, binders,
@ -1001,7 +972,7 @@ pub trait TypeWalk {
Self: Sized, Self: Sized,
{ {
self.walk_mut(&mut |ty_mut| { self.walk_mut(&mut |ty_mut| {
let ty = mem::replace(ty_mut, Ty(TyKind::Unknown)); let ty = mem::replace(ty_mut, TyKind::Unknown.intern(&Interner));
*ty_mut = f(ty); *ty_mut = f(ty);
}); });
self self
@ -1022,7 +993,7 @@ pub trait TypeWalk {
{ {
self.walk_mut_binders( self.walk_mut_binders(
&mut |ty, binders| { &mut |ty, binders| {
if let &mut TyKind::BoundVar(bound) = &mut ty.0 { if let &mut TyKind::BoundVar(bound) = ty.interned_mut() {
if bound.debruijn >= binders { if bound.debruijn >= binders {
*ty = substs.0[bound.index].clone().shift_bound_vars(binders); *ty = substs.0[bound.index].clone().shift_bound_vars(binders);
} }
@ -1039,7 +1010,7 @@ pub trait TypeWalk {
Self: Sized, Self: Sized,
{ {
self.fold_binders( self.fold_binders(
&mut |ty, binders| match &ty.0 { &mut |ty, binders| match ty.interned(&Interner) {
TyKind::BoundVar(bound) if bound.debruijn >= binders => { TyKind::BoundVar(bound) if bound.debruijn >= binders => {
TyKind::BoundVar(bound.shifted_in_from(n)).intern(&Interner) TyKind::BoundVar(bound.shifted_in_from(n)).intern(&Interner)
} }
@ -1068,6 +1039,9 @@ impl TypeWalk for Ty {
p.walk(f); p.walk(f);
} }
} }
TyKind::Slice(ty) | TyKind::Array(ty) | TyKind::Ref(_, ty) | TyKind::Raw(_, ty) => {
ty.walk(f);
}
_ => { _ => {
if let Some(substs) = self.substs() { if let Some(substs) = self.substs() {
for t in substs.iter() { for t in substs.iter() {
@ -1084,7 +1058,7 @@ impl TypeWalk for Ty {
f: &mut impl FnMut(&mut Ty, DebruijnIndex), f: &mut impl FnMut(&mut Ty, DebruijnIndex),
binders: DebruijnIndex, binders: DebruijnIndex,
) { ) {
match &mut self.0 { match self.interned_mut() {
TyKind::Alias(AliasTy::Projection(p_ty)) => { TyKind::Alias(AliasTy::Projection(p_ty)) => {
p_ty.substitution.walk_mut_binders(f, binders); p_ty.substitution.walk_mut_binders(f, binders);
} }
@ -1096,6 +1070,9 @@ impl TypeWalk for Ty {
TyKind::Alias(AliasTy::Opaque(o_ty)) => { TyKind::Alias(AliasTy::Opaque(o_ty)) => {
o_ty.substitution.walk_mut_binders(f, binders); 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() { if let Some(substs) = self.substs_mut() {
substs.walk_mut_binders(f, binders); substs.walk_mut_binders(f, binders);

View file

@ -160,21 +160,19 @@ impl<'a> TyLoweringContext<'a> {
} }
TypeRef::RawPtr(inner, mutability) => { TypeRef::RawPtr(inner, mutability) => {
let inner_ty = self.lower_ty(inner); let inner_ty = self.lower_ty(inner);
TyKind::Raw(lower_to_chalk_mutability(*mutability), Substs::single(inner_ty)) TyKind::Raw(lower_to_chalk_mutability(*mutability), inner_ty).intern(&Interner)
.intern(&Interner)
} }
TypeRef::Array(inner) => { TypeRef::Array(inner) => {
let inner_ty = self.lower_ty(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) => { TypeRef::Slice(inner) => {
let inner_ty = self.lower_ty(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) => { TypeRef::Reference(inner, _, mutability) => {
let inner_ty = self.lower_ty(inner); let inner_ty = self.lower_ty(inner);
TyKind::Ref(lower_to_chalk_mutability(*mutability), Substs::single(inner_ty)) TyKind::Ref(lower_to_chalk_mutability(*mutability), inner_ty).intern(&Interner)
.intern(&Interner)
} }
TypeRef::Placeholder => TyKind::Unknown.intern(&Interner), TypeRef::Placeholder => TyKind::Unknown.intern(&Interner),
TypeRef::Fn(params, is_varargs) => { TypeRef::Fn(params, is_varargs) => {
@ -993,7 +991,7 @@ pub(crate) fn generic_defaults_query(
// Each default can only refer to previous parameters. // Each default can only refer to previous parameters.
ty.walk_mut_binders( ty.walk_mut_binders(
&mut |ty, binders| match &mut ty.0 { &mut |ty, binders| match ty.interned_mut() {
TyKind::BoundVar(BoundVar { debruijn, index }) if *debruijn == binders => { TyKind::BoundVar(BoundVar { debruijn, index }) if *debruijn == binders => {
if *index >= idx { if *index >= idx {
// type variable default referring to parameter coming // type variable default referring to parameter coming

View file

@ -435,8 +435,7 @@ fn iterate_method_candidates_with_autoref(
} }
let refed = Canonical { let refed = Canonical {
kinds: deref_chain[0].kinds.clone(), kinds: deref_chain[0].kinds.clone(),
value: TyKind::Ref(Mutability::Not, Substs::single(deref_chain[0].value.clone())) value: TyKind::Ref(Mutability::Not, deref_chain[0].value.clone()).intern(&Interner),
.intern(&Interner),
}; };
if iterate_method_candidates_by_receiver( if iterate_method_candidates_by_receiver(
&refed, &refed,
@ -452,8 +451,7 @@ fn iterate_method_candidates_with_autoref(
} }
let ref_muted = Canonical { let ref_muted = Canonical {
kinds: deref_chain[0].kinds.clone(), kinds: deref_chain[0].kinds.clone(),
value: TyKind::Ref(Mutability::Mut, Substs::single(deref_chain[0].value.clone())) value: TyKind::Ref(Mutability::Mut, deref_chain[0].value.clone()).intern(&Interner),
.intern(&Interner),
}; };
if iterate_method_candidates_by_receiver( if iterate_method_candidates_by_receiver(
&ref_muted, &ref_muted,

View file

@ -24,9 +24,9 @@ use super::*;
impl ToChalk for Ty { impl ToChalk for Ty {
type Chalk = chalk_ir::Ty<Interner>; type Chalk = chalk_ir::Ty<Interner>;
fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty<Interner> { fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty<Interner> {
match self.0 { match self.into_inner() {
TyKind::Ref(m, parameters) => ref_to_chalk(db, m, parameters), TyKind::Ref(m, ty) => ref_to_chalk(db, m, ty),
TyKind::Array(parameters) => array_to_chalk(db, parameters), TyKind::Array(ty) => array_to_chalk(db, ty),
TyKind::Function(FnPointer { sig, substs, .. }) => { TyKind::Function(FnPointer { sig, substs, .. }) => {
let substitution = chalk_ir::FnSubst(substs.to_chalk(db).shifted_in(&Interner)); let substitution = chalk_ir::FnSubst(substs.to_chalk(db).shifted_in(&Interner));
chalk_ir::TyKind::Function(chalk_ir::FnPointer { chalk_ir::TyKind::Function(chalk_ir::FnPointer {
@ -54,13 +54,11 @@ impl ToChalk for Ty {
let substitution = substs.to_chalk(db); let substitution = substs.to_chalk(db);
chalk_ir::TyKind::Tuple(cardinality.into(), substitution).intern(&Interner) chalk_ir::TyKind::Tuple(cardinality.into(), substitution).intern(&Interner)
} }
TyKind::Raw(mutability, substs) => { TyKind::Raw(mutability, ty) => {
let ty = substs[0].clone().to_chalk(db); let ty = ty.to_chalk(db);
chalk_ir::TyKind::Raw(mutability, ty).intern(&Interner) chalk_ir::TyKind::Raw(mutability, ty).intern(&Interner)
} }
TyKind::Slice(substs) => { TyKind::Slice(ty) => chalk_ir::TyKind::Slice(ty.to_chalk(db)).intern(&Interner),
chalk_ir::TyKind::Slice(substs[0].clone().to_chalk(db)).intern(&Interner)
}
TyKind::Str => chalk_ir::TyKind::Str.intern(&Interner), TyKind::Str => chalk_ir::TyKind::Str.intern(&Interner),
TyKind::FnDef(id, substs) => { TyKind::FnDef(id, substs) => {
let substitution = substs.to_chalk(db); let substitution = substs.to_chalk(db);
@ -114,7 +112,7 @@ impl ToChalk for Ty {
fn from_chalk(db: &dyn HirDatabase, chalk: chalk_ir::Ty<Interner>) -> Self { fn from_chalk(db: &dyn HirDatabase, chalk: chalk_ir::Ty<Interner>) -> Self {
match chalk.data(&Interner).kind.clone() { match chalk.data(&Interner).kind.clone() {
chalk_ir::TyKind::Error => TyKind::Unknown, 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::Placeholder(idx) => TyKind::Placeholder(idx),
chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Projection(proj)) => { chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Projection(proj)) => {
let associated_ty = proj.associated_ty_id; let associated_ty = proj.associated_ty_id;
@ -168,12 +166,10 @@ impl ToChalk for Ty {
chalk_ir::TyKind::Tuple(cardinality, subst) => { chalk_ir::TyKind::Tuple(cardinality, subst) => {
TyKind::Tuple(cardinality, from_chalk(db, subst)) TyKind::Tuple(cardinality, from_chalk(db, subst))
} }
chalk_ir::TyKind::Raw(mutability, ty) => { chalk_ir::TyKind::Raw(mutability, ty) => TyKind::Raw(mutability, from_chalk(db, ty)),
TyKind::Raw(mutability, Substs::single(from_chalk(db, ty))) chalk_ir::TyKind::Slice(ty) => TyKind::Slice(from_chalk(db, ty)),
}
chalk_ir::TyKind::Slice(ty) => TyKind::Slice(Substs::single(from_chalk(db, ty))),
chalk_ir::TyKind::Ref(mutability, _lifetime, 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::Str => TyKind::Str,
chalk_ir::TyKind::Never => TyKind::Never, chalk_ir::TyKind::Never => TyKind::Never,
@ -197,17 +193,17 @@ impl ToChalk for Ty {
fn ref_to_chalk( fn ref_to_chalk(
db: &dyn HirDatabase, db: &dyn HirDatabase,
mutability: chalk_ir::Mutability, mutability: chalk_ir::Mutability,
subst: Substs, ty: Ty,
) -> chalk_ir::Ty<Interner> { ) -> chalk_ir::Ty<Interner> {
let arg = subst[0].clone().to_chalk(db); let arg = ty.to_chalk(db);
let lifetime = LifetimeData::Static.intern(&Interner); let lifetime = LifetimeData::Static.intern(&Interner);
chalk_ir::TyKind::Ref(mutability, lifetime, arg).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 /// 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. /// 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> { fn array_to_chalk(db: &dyn HirDatabase, ty: Ty) -> chalk_ir::Ty<Interner> {
let arg = subst[0].clone().to_chalk(db); let arg = ty.to_chalk(db);
let usize_ty = chalk_ir::TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner); let usize_ty = chalk_ir::TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner);
let const_ = chalk_ir::ConstData { let const_ = chalk_ir::ConstData {
ty: usize_ty, ty: usize_ty,