mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 14:21:44 +00:00
Make Ty wrap TyKind in an Arc
... like it will be in Chalk. We still keep `interned_mut` and `into_inner` methods that will probably not exist with Chalk. This worsens performance slightly (5ginstr inference on RA), but doesn't include other simplifications we can do yet.
This commit is contained in:
parent
1954147834
commit
af466f8542
8 changed files with 53 additions and 27 deletions
|
@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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, ..))
|
||||||
|
|
|
@ -800,7 +800,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()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -158,11 +158,11 @@ 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, Substs::single(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(
|
||||||
|
@ -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(),
|
||||||
|
|
|
@ -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);
|
||||||
|
@ -404,7 +404,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() {
|
||||||
|
|
|
@ -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.
|
||||||
|
@ -814,7 +822,7 @@ impl Ty {
|
||||||
/// `self` is `Option<_>` and the substs contain `u32`, we'll have
|
/// `self` is `Option<_>` and the substs contain `u32`, we'll have
|
||||||
/// `Option<u32>` afterwards.)
|
/// `Option<u32>` afterwards.)
|
||||||
pub fn apply_substs(mut self, new_substs: Substs) -> Ty {
|
pub fn apply_substs(mut self, new_substs: Substs) -> Ty {
|
||||||
match &mut self.0 {
|
match self.interned_mut() {
|
||||||
TyKind::Adt(_, substs)
|
TyKind::Adt(_, substs)
|
||||||
| TyKind::Slice(substs)
|
| TyKind::Slice(substs)
|
||||||
| TyKind::Array(substs)
|
| TyKind::Array(substs)
|
||||||
|
@ -854,7 +862,7 @@ impl Ty {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn substs_mut(&mut self) -> Option<&mut Substs> {
|
pub 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::Slice(substs)
|
||||||
| TyKind::Array(substs)
|
| TyKind::Array(substs)
|
||||||
|
@ -988,7 +996,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 +1009,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 +1030,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 +1047,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)
|
||||||
}
|
}
|
||||||
|
@ -1084,7 +1092,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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -993,7 +993,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
|
||||||
|
|
|
@ -24,7 +24,7 @@ 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, parameters) => ref_to_chalk(db, m, parameters),
|
||||||
TyKind::Array(parameters) => array_to_chalk(db, parameters),
|
TyKind::Array(parameters) => array_to_chalk(db, parameters),
|
||||||
TyKind::Function(FnPointer { sig, substs, .. }) => {
|
TyKind::Function(FnPointer { sig, substs, .. }) => {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue