Separate Ty and TyKind like in Chalk

Currently `Ty` just wraps `TyKind`, but this allows us to change most
places to already use `intern` / `interned`.
This commit is contained in:
Florian Diebold 2021-03-13 14:44:51 +01:00
parent 7accf6bc37
commit 6c32bbf3ca
20 changed files with 756 additions and 620 deletions

View file

@ -54,8 +54,8 @@ use hir_ty::{
method_resolution, method_resolution,
traits::{FnTrait, Solution, SolutionVariables}, traits::{FnTrait, Solution, SolutionVariables},
AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, DebruijnIndex, GenericPredicate, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, DebruijnIndex, GenericPredicate,
InEnvironment, Obligation, ProjectionPredicate, ProjectionTy, Scalar, Substs, TraitEnvironment, InEnvironment, Interner, Obligation, ProjectionPredicate, ProjectionTy, Scalar, Substs,
Ty, TyDefId, TyVariableKind, TraitEnvironment, Ty, TyDefId, TyKind, TyVariableKind,
}; };
use rustc_hash::FxHashSet; use rustc_hash::FxHashSet;
use stdx::{format_to, impl_from}; use stdx::{format_to, impl_from};
@ -677,7 +677,7 @@ impl_from!(Struct, Union, Enum for Adt);
impl Adt { impl Adt {
pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool { pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool {
let subst = db.generic_defaults(self.into()); let subst = db.generic_defaults(self.into());
subst.iter().any(|ty| &ty.value == &Ty::Unknown) subst.iter().any(|ty| ty.value.is_unknown())
} }
/// Turns this ADT into a type. Any type parameters of the ADT will be /// Turns this ADT into a type. Any type parameters of the ADT will be
@ -1012,7 +1012,7 @@ pub struct TypeAlias {
impl TypeAlias { impl TypeAlias {
pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool { pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool {
let subst = db.generic_defaults(self.id.into()); let subst = db.generic_defaults(self.id.into());
subst.iter().any(|ty| &ty.value == &Ty::Unknown) subst.iter().any(|ty| ty.value.is_unknown())
} }
pub fn module(self, db: &dyn HirDatabase) -> Module { pub fn module(self, db: &dyn HirDatabase) -> Module {
@ -1384,7 +1384,7 @@ impl TypeParam {
pub fn ty(self, db: &dyn HirDatabase) -> Type { pub fn ty(self, db: &dyn HirDatabase) -> Type {
let resolver = self.id.parent.resolver(db.upcast()); let resolver = self.id.parent.resolver(db.upcast());
let krate = self.id.parent.module(db.upcast()).krate(); let krate = self.id.parent.module(db.upcast()).krate();
let ty = Ty::Placeholder(self.id); let ty = TyKind::Placeholder(self.id).intern(&Interner);
Type::new_with_resolver_inner(db, krate, &resolver, ty) Type::new_with_resolver_inner(db, krate, &resolver, ty)
} }
@ -1584,25 +1584,25 @@ impl Type {
} }
pub fn is_unit(&self) -> bool { pub fn is_unit(&self) -> bool {
matches!(self.ty.value, Ty::Tuple(0, ..)) matches!(self.ty.value.interned(&Interner), TyKind::Tuple(0, ..))
} }
pub fn is_bool(&self) -> bool { pub fn is_bool(&self) -> bool {
matches!(self.ty.value, Ty::Scalar(Scalar::Bool)) matches!(self.ty.value.interned(&Interner), TyKind::Scalar(Scalar::Bool))
} }
pub fn is_mutable_reference(&self) -> bool { pub fn is_mutable_reference(&self) -> bool {
matches!(self.ty.value, Ty::Ref(hir_ty::Mutability::Mut, ..)) matches!(self.ty.value.interned(&Interner), TyKind::Ref(hir_ty::Mutability::Mut, ..))
} }
pub fn remove_ref(&self) -> Option<Type> { pub fn remove_ref(&self) -> Option<Type> {
match &self.ty.value { match &self.ty.value.interned(&Interner) {
Ty::Ref(.., substs) => Some(self.derived(substs[0].clone())), TyKind::Ref(.., substs) => Some(self.derived(substs[0].clone())),
_ => None, _ => None,
} }
} }
pub fn is_unknown(&self) -> bool { pub fn is_unknown(&self) -> bool {
matches!(self.ty.value, Ty::Unknown) self.ty.value.is_unknown()
} }
/// Checks that particular type `ty` implements `std::future::Future`. /// Checks that particular type `ty` implements `std::future::Future`.
@ -1684,7 +1684,7 @@ impl Type {
.build(); .build();
let predicate = ProjectionPredicate { let predicate = ProjectionPredicate {
projection_ty: ProjectionTy { associated_ty: alias.id, parameters: subst }, projection_ty: ProjectionTy { associated_ty: alias.id, parameters: subst },
ty: Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)), ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner),
}; };
let goal = Canonical { let goal = Canonical {
value: InEnvironment::new( value: InEnvironment::new(
@ -1712,8 +1712,8 @@ impl Type {
} }
pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> { pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> {
let def = match self.ty.value { let def = match self.ty.value.interned(&Interner) {
Ty::FnDef(def, _) => Some(def), &TyKind::FnDef(def, _) => Some(def),
_ => None, _ => None,
}; };
@ -1722,16 +1722,16 @@ impl Type {
} }
pub fn is_closure(&self) -> bool { pub fn is_closure(&self) -> bool {
matches!(&self.ty.value, Ty::Closure { .. }) matches!(&self.ty.value.interned(&Interner), TyKind::Closure { .. })
} }
pub fn is_fn(&self) -> bool { pub fn is_fn(&self) -> bool {
matches!(&self.ty.value, Ty::FnDef(..) | Ty::Function { .. }) matches!(&self.ty.value.interned(&Interner), TyKind::FnDef(..) | TyKind::Function { .. })
} }
pub fn is_packed(&self, db: &dyn HirDatabase) -> bool { pub fn is_packed(&self, db: &dyn HirDatabase) -> bool {
let adt_id = match self.ty.value { let adt_id = match self.ty.value.interned(&Interner) {
Ty::Adt(hir_ty::AdtId(adt_id), ..) => adt_id, &TyKind::Adt(hir_ty::AdtId(adt_id), ..) => adt_id,
_ => return false, _ => return false,
}; };
@ -1743,24 +1743,25 @@ impl Type {
} }
pub fn is_raw_ptr(&self) -> bool { pub fn is_raw_ptr(&self) -> bool {
matches!(&self.ty.value, Ty::Raw(..)) matches!(&self.ty.value.interned(&Interner), TyKind::Raw(..))
} }
pub fn contains_unknown(&self) -> bool { pub fn contains_unknown(&self) -> bool {
return go(&self.ty.value); return go(&self.ty.value);
fn go(ty: &Ty) -> bool { fn go(ty: &Ty) -> bool {
match ty { if ty.is_unknown() {
Ty::Unknown => true, true
_ => ty.substs().map_or(false, |substs| substs.iter().any(go)), } else {
ty.substs().map_or(false, |substs| substs.iter().any(go))
} }
} }
} }
pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> { pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> {
let (variant_id, substs) = match self.ty.value { let (variant_id, substs) = match self.ty.value.interned(&Interner) {
Ty::Adt(hir_ty::AdtId(AdtId::StructId(s)), ref substs) => (s.into(), substs), &TyKind::Adt(hir_ty::AdtId(AdtId::StructId(s)), ref substs) => (s.into(), substs),
Ty::Adt(hir_ty::AdtId(AdtId::UnionId(u)), ref substs) => (u.into(), substs), &TyKind::Adt(hir_ty::AdtId(AdtId::UnionId(u)), ref substs) => (u.into(), substs),
_ => return Vec::new(), _ => return Vec::new(),
}; };
@ -1775,7 +1776,7 @@ impl Type {
} }
pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec<Type> { pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec<Type> {
if let Ty::Tuple(_, substs) = &self.ty.value { if let TyKind::Tuple(_, substs) = &self.ty.value.interned(&Interner) {
substs.iter().map(|ty| self.derived(ty.clone())).collect() substs.iter().map(|ty| self.derived(ty.clone())).collect()
} else { } else {
Vec::new() Vec::new()
@ -1957,33 +1958,33 @@ impl Type {
fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) { fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) {
let ty = type_.ty.value.strip_references(); let ty = type_.ty.value.strip_references();
match ty { match ty.interned(&Interner) {
Ty::Adt(..) => { TyKind::Adt(..) => {
cb(type_.derived(ty.clone())); cb(type_.derived(ty.clone()));
} }
Ty::AssociatedType(..) => { TyKind::AssociatedType(..) => {
if let Some(_) = ty.associated_type_parent_trait(db) { if let Some(_) = ty.associated_type_parent_trait(db) {
cb(type_.derived(ty.clone())); cb(type_.derived(ty.clone()));
} }
} }
Ty::OpaqueType(..) => { TyKind::OpaqueType(..) => {
if let Some(bounds) = ty.impl_trait_bounds(db) { if let Some(bounds) = ty.impl_trait_bounds(db) {
walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
} }
} }
Ty::Alias(AliasTy::Opaque(opaque_ty)) => { TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
if let Some(bounds) = ty.impl_trait_bounds(db) { if let Some(bounds) = ty.impl_trait_bounds(db) {
walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
} }
walk_substs(db, type_, &opaque_ty.parameters, cb); walk_substs(db, type_, &opaque_ty.parameters, cb);
} }
Ty::Placeholder(_) => { TyKind::Placeholder(_) => {
if let Some(bounds) = ty.impl_trait_bounds(db) { if let Some(bounds) = ty.impl_trait_bounds(db) {
walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
} }
} }
Ty::Dyn(bounds) => { TyKind::Dyn(bounds) => {
walk_bounds(db, &type_.derived(ty.clone()), bounds.as_ref(), cb); walk_bounds(db, &type_.derived(ty.clone()), bounds.as_ref(), cb);
} }

View file

@ -14,7 +14,7 @@ use crate::{
db::HirDatabase, db::HirDatabase,
traits::{InEnvironment, Solution}, traits::{InEnvironment, Solution},
utils::generics, utils::generics,
BoundVar, Canonical, DebruijnIndex, Obligation, Substs, TraitRef, Ty, BoundVar, Canonical, DebruijnIndex, Interner, Obligation, Substs, TraitRef, Ty, TyKind,
}; };
const AUTODEREF_RECURSION_LIMIT: usize = 10; const AUTODEREF_RECURSION_LIMIT: usize = 10;
@ -81,7 +81,8 @@ fn deref_by_trait(
// Now do the assoc type projection // Now do the assoc type projection
let projection = super::traits::ProjectionPredicate { let projection = super::traits::ProjectionPredicate {
ty: Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, ty.value.kinds.len())), ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, ty.value.kinds.len()))
.intern(&Interner),
projection_ty: super::ProjectionTy { associated_ty: target, parameters }, projection_ty: super::ProjectionTy { associated_ty: target, parameters },
}; };
@ -114,8 +115,8 @@ fn deref_by_trait(
// new variables in that case // new variables in that case
for i in 1..vars.0.kinds.len() { for i in 1..vars.0.kinds.len() {
if vars.0.value[i - 1] if vars.0.value[i - 1].interned(&Interner)
!= Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1)) != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1))
{ {
warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.value, solution); warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.value, solution);
return None; return None;

View file

@ -15,7 +15,7 @@ use crate::{
MissingPatFields, RemoveThisSemicolon, MissingPatFields, RemoveThisSemicolon,
}, },
utils::variant_data, utils::variant_data,
AdtId, InferenceResult, Ty, AdtId, InferenceResult, Interner, Ty, TyKind,
}; };
pub(crate) use hir_def::{ pub(crate) use hir_def::{
@ -289,11 +289,10 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
let (body, source_map): (Arc<Body>, Arc<BodySourceMap>) = let (body, source_map): (Arc<Body>, Arc<BodySourceMap>) =
db.body_with_source_map(self.owner.into()); db.body_with_source_map(self.owner.into());
let match_expr_ty = match infer.type_of_expr.get(match_expr) { let match_expr_ty = if infer.type_of_expr[match_expr].is_unknown() {
// If we can't resolve the type of the match expression return;
// we cannot perform exhaustiveness checks. } else {
None | Some(Ty::Unknown) => return, &infer.type_of_expr[match_expr]
Some(ty) => ty,
}; };
let cx = MatchCheckCtx { match_expr, body, infer: infer.clone(), db }; let cx = MatchCheckCtx { match_expr, body, infer: infer.clone(), db };
@ -379,14 +378,14 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
_ => return, _ => return,
}; };
let (params, required) = match mismatch.expected { let (params, required) = match mismatch.expected.interned(&Interner) {
Ty::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ref parameters) TyKind::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ref parameters)
if enum_id == core_result_enum => if *enum_id == core_result_enum =>
{ {
(parameters, "Ok".to_string()) (parameters, "Ok".to_string())
} }
Ty::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ref parameters) TyKind::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ref parameters)
if enum_id == core_option_enum => if *enum_id == core_option_enum =>
{ {
(parameters, "Some".to_string()) (parameters, "Some".to_string())
} }

View file

@ -227,7 +227,7 @@ use hir_def::{
use la_arena::Idx; use la_arena::Idx;
use smallvec::{smallvec, SmallVec}; use smallvec::{smallvec, SmallVec};
use crate::{db::HirDatabase, AdtId, InferenceResult, Ty}; use crate::{db::HirDatabase, AdtId, InferenceResult, Interner, TyKind};
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
/// Either a pattern from the source code being analyzed, represented as /// Either a pattern from the source code being analyzed, represented as
@ -626,13 +626,13 @@ pub(super) fn is_useful(
// - enum with no variants // - enum with no variants
// - `!` type // - `!` type
// In those cases, no match arm is useful. // In those cases, no match arm is useful.
match cx.infer[cx.match_expr].strip_references() { match cx.infer[cx.match_expr].strip_references().interned(&Interner) {
Ty::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ..) => { TyKind::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ..) => {
if cx.db.enum_data(*enum_id).variants.is_empty() { if cx.db.enum_data(*enum_id).variants.is_empty() {
return Ok(Usefulness::NotUseful); return Ok(Usefulness::NotUseful);
} }
} }
Ty::Never => return Ok(Usefulness::NotUseful), TyKind::Never => return Ok(Usefulness::NotUseful),
_ => (), _ => (),
} }

View file

@ -11,7 +11,7 @@ use hir_def::{
}; };
use hir_expand::diagnostics::DiagnosticSink; use hir_expand::diagnostics::DiagnosticSink;
use crate::{db::HirDatabase, diagnostics::MissingUnsafe, InferenceResult, Ty}; use crate::{db::HirDatabase, diagnostics::MissingUnsafe, InferenceResult, Interner, TyKind};
pub(super) struct UnsafeValidator<'a, 'b: 'a> { pub(super) struct UnsafeValidator<'a, 'b: 'a> {
owner: DefWithBodyId, owner: DefWithBodyId,
@ -110,7 +110,7 @@ fn walk_unsafe(
} }
} }
Expr::UnaryOp { expr, op: UnaryOp::Deref } => { Expr::UnaryOp { expr, op: UnaryOp::Deref } => {
if let Ty::Raw(..) = &infer[*expr] { if let TyKind::Raw(..) = &infer[*expr].interned(&Interner) {
unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block });
} }
} }

View file

@ -12,8 +12,8 @@ use hir_expand::name::Name;
use crate::{ use crate::{
db::HirDatabase, primitive, utils::generics, AdtId, AliasTy, CallableDefId, CallableSig, db::HirDatabase, primitive, utils::generics, AdtId, AliasTy, CallableDefId, CallableSig,
GenericPredicate, Lifetime, Obligation, OpaqueTy, OpaqueTyId, ProjectionTy, Scalar, Substs, GenericPredicate, Interner, Lifetime, Obligation, OpaqueTy, OpaqueTyId, ProjectionTy, Scalar,
TraitRef, Ty, Substs, TraitRef, Ty, TyKind,
}; };
pub struct HirFormatter<'a> { pub struct HirFormatter<'a> {
@ -267,32 +267,32 @@ impl HirDisplay for Ty {
return write!(f, "{}", TYPE_HINT_TRUNCATION); return write!(f, "{}", TYPE_HINT_TRUNCATION);
} }
match self { match self.interned(&Interner) {
Ty::Never => write!(f, "!")?, TyKind::Never => write!(f, "!")?,
Ty::Str => write!(f, "str")?, TyKind::Str => write!(f, "str")?,
Ty::Scalar(Scalar::Bool) => write!(f, "bool")?, TyKind::Scalar(Scalar::Bool) => write!(f, "bool")?,
Ty::Scalar(Scalar::Char) => write!(f, "char")?, TyKind::Scalar(Scalar::Char) => write!(f, "char")?,
&Ty::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))?,
&Ty::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))?,
&Ty::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))?,
Ty::Slice(parameters) => { TyKind::Slice(parameters) => {
let t = parameters.as_single(); let t = parameters.as_single();
write!(f, "[")?; write!(f, "[")?;
t.hir_fmt(f)?; t.hir_fmt(f)?;
write!(f, "]")?; write!(f, "]")?;
} }
Ty::Array(parameters) => { TyKind::Array(parameters) => {
let t = parameters.as_single(); let t = parameters.as_single();
write!(f, "[")?; write!(f, "[")?;
t.hir_fmt(f)?; t.hir_fmt(f)?;
write!(f, "; _]")?; write!(f, "; _]")?;
} }
Ty::Raw(m, parameters) | Ty::Ref(m, parameters) => { TyKind::Raw(m, parameters) | TyKind::Ref(m, parameters) => {
let t = parameters.as_single(); 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);
if matches!(self, Ty::Raw(..)) { if matches!(self.interned(&Interner), TyKind::Raw(..)) {
write!( write!(
f, f,
"*{}", "*{}",
@ -313,11 +313,11 @@ impl HirDisplay for Ty {
} }
let datas; let datas;
let predicates = match t { let predicates = match t.interned(&Interner) {
Ty::Dyn(predicates) if predicates.len() > 1 => { TyKind::Dyn(predicates) if predicates.len() > 1 => {
Cow::Borrowed(predicates.as_ref()) Cow::Borrowed(predicates.as_ref())
} }
&Ty::Alias(AliasTy::Opaque(OpaqueTy { &TyKind::Alias(AliasTy::Opaque(OpaqueTy {
opaque_ty_id: OpaqueTyId::ReturnTypeImplTrait(func, idx), opaque_ty_id: OpaqueTyId::ReturnTypeImplTrait(func, idx),
ref parameters, ref parameters,
})) => { })) => {
@ -347,7 +347,7 @@ impl HirDisplay for Ty {
write!(f, "{}", ty_display)?; write!(f, "{}", ty_display)?;
} }
} }
Ty::Tuple(_, substs) => { TyKind::Tuple(_, substs) => {
if substs.len() == 1 { if substs.len() == 1 {
write!(f, "(")?; write!(f, "(")?;
substs[0].hir_fmt(f)?; substs[0].hir_fmt(f)?;
@ -358,11 +358,11 @@ impl HirDisplay for Ty {
write!(f, ")")?; write!(f, ")")?;
} }
} }
Ty::Function(fn_ptr) => { TyKind::Function(fn_ptr) => {
let sig = CallableSig::from_fn_ptr(fn_ptr); let sig = CallableSig::from_fn_ptr(fn_ptr);
sig.hir_fmt(f)?; sig.hir_fmt(f)?;
} }
Ty::FnDef(def, parameters) => { TyKind::FnDef(def, parameters) => {
let def = *def; let def = *def;
let sig = f.db.callable_item_signature(def).subst(parameters); let sig = f.db.callable_item_signature(def).subst(parameters);
match def { match def {
@ -401,7 +401,7 @@ impl HirDisplay for Ty {
write!(f, " -> {}", ret_display)?; write!(f, " -> {}", ret_display)?;
} }
} }
Ty::Adt(AdtId(def_id), parameters) => { TyKind::Adt(AdtId(def_id), parameters) => {
match f.display_target { match f.display_target {
DisplayTarget::Diagnostics | DisplayTarget::Test => { DisplayTarget::Diagnostics | DisplayTarget::Test => {
let name = match *def_id { let name = match *def_id {
@ -427,37 +427,39 @@ impl HirDisplay for Ty {
} }
if parameters.len() > 0 { if parameters.len() > 0 {
let parameters_to_write = let parameters_to_write = if f.display_target.is_source_code()
if f.display_target.is_source_code() || f.omit_verbose_types() { || f.omit_verbose_types()
match self {
.as_generic_def() match self
.map(|generic_def_id| f.db.generic_defaults(generic_def_id)) .as_generic_def()
.filter(|defaults| !defaults.is_empty()) .map(|generic_def_id| f.db.generic_defaults(generic_def_id))
{ .filter(|defaults| !defaults.is_empty())
None => parameters.0.as_ref(), {
Some(default_parameters) => { None => parameters.0.as_ref(),
let mut default_from = 0; Some(default_parameters) => {
for (i, parameter) in parameters.iter().enumerate() { let mut default_from = 0;
match (parameter, default_parameters.get(i)) { for (i, parameter) in parameters.iter().enumerate() {
(&Ty::Unknown, _) | (_, None) => { match (parameter.interned(&Interner), default_parameters.get(i))
{
(&TyKind::Unknown, _) | (_, None) => {
default_from = i + 1;
}
(_, Some(default_parameter)) => {
let actual_default = default_parameter
.clone()
.subst(&parameters.prefix(i));
if parameter != &actual_default {
default_from = i + 1; default_from = i + 1;
} }
(_, Some(default_parameter)) => {
let actual_default = default_parameter
.clone()
.subst(&parameters.prefix(i));
if parameter != &actual_default {
default_from = i + 1;
}
}
} }
} }
&parameters.0[0..default_from]
} }
&parameters.0[0..default_from]
} }
} else { }
parameters.0.as_ref() } else {
}; parameters.0.as_ref()
};
if !parameters_to_write.is_empty() { if !parameters_to_write.is_empty() {
write!(f, "<")?; write!(f, "<")?;
f.write_joined(parameters_to_write, ", ")?; f.write_joined(parameters_to_write, ", ")?;
@ -465,7 +467,7 @@ impl HirDisplay for Ty {
} }
} }
} }
Ty::AssociatedType(type_alias, parameters) => { TyKind::AssociatedType(type_alias, parameters) => {
let trait_ = match type_alias.lookup(f.db.upcast()).container { let trait_ = match type_alias.lookup(f.db.upcast()).container {
AssocContainerId::TraitId(it) => it, AssocContainerId::TraitId(it) => it,
_ => panic!("not an associated type"), _ => panic!("not an associated type"),
@ -488,11 +490,11 @@ impl HirDisplay for Ty {
projection_ty.hir_fmt(f)?; projection_ty.hir_fmt(f)?;
} }
} }
Ty::ForeignType(type_alias) => { TyKind::ForeignType(type_alias) => {
let type_alias = f.db.type_alias_data(*type_alias); let type_alias = f.db.type_alias_data(*type_alias);
write!(f, "{}", type_alias.name)?; write!(f, "{}", type_alias.name)?;
} }
Ty::OpaqueType(opaque_ty_id, parameters) => { TyKind::OpaqueType(opaque_ty_id, parameters) => {
match opaque_ty_id { match opaque_ty_id {
&OpaqueTyId::ReturnTypeImplTrait(func, idx) => { &OpaqueTyId::ReturnTypeImplTrait(func, idx) => {
let datas = let datas =
@ -511,7 +513,7 @@ impl HirDisplay for Ty {
} }
} }
} }
Ty::Closure(.., substs) => { TyKind::Closure(.., substs) => {
let sig = substs[0].callable_sig(f.db); let sig = substs[0].callable_sig(f.db);
if let Some(sig) = sig { if let Some(sig) = sig {
if sig.params().is_empty() { if sig.params().is_empty() {
@ -535,7 +537,7 @@ impl HirDisplay for Ty {
write!(f, "{{closure}}")?; write!(f, "{{closure}}")?;
} }
} }
Ty::Placeholder(id) => { TyKind::Placeholder(id) => {
let generics = generics(f.db.upcast(), id.parent); let generics = generics(f.db.upcast(), id.parent);
let param_data = &generics.params.types[id.local_id]; let param_data = &generics.params.types[id.local_id];
match param_data.provenance { match param_data.provenance {
@ -553,12 +555,12 @@ impl HirDisplay for Ty {
} }
} }
} }
Ty::BoundVar(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?, TyKind::BoundVar(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?,
Ty::Dyn(predicates) => { TyKind::Dyn(predicates) => {
write_bounds_like_dyn_trait_with_prefix("dyn", predicates, f)?; write_bounds_like_dyn_trait_with_prefix("dyn", predicates, f)?;
} }
Ty::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?, TyKind::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?,
Ty::Alias(AliasTy::Opaque(opaque_ty)) => { TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
match opaque_ty.opaque_ty_id { match opaque_ty.opaque_ty_id {
OpaqueTyId::ReturnTypeImplTrait(func, idx) => { OpaqueTyId::ReturnTypeImplTrait(func, idx) => {
let datas = let datas =
@ -574,7 +576,7 @@ impl HirDisplay for Ty {
} }
}; };
} }
Ty::Unknown => { TyKind::Unknown => {
if f.display_target.is_source_code() { if f.display_target.is_source_code() {
return Err(HirDisplayError::DisplaySourceCodeError( return Err(HirDisplayError::DisplaySourceCodeError(
DisplaySourceCodeError::UnknownType, DisplaySourceCodeError::UnknownType,
@ -582,7 +584,7 @@ impl HirDisplay for Ty {
} }
write!(f, "{{unknown}}")?; write!(f, "{{unknown}}")?;
} }
Ty::InferenceVar(..) => write!(f, "_")?, TyKind::InferenceVar(..) => write!(f, "_")?,
} }
Ok(()) Ok(())
} }

View file

@ -41,7 +41,8 @@ use super::{
InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeWalk, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeWalk,
}; };
use crate::{ use crate::{
db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, AliasTy, db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode,
AliasTy, Interner, TyKind,
}; };
pub(crate) use unify::unify; pub(crate) use unify::unify;
@ -169,7 +170,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::Unknown) self.type_of_expr.get(expr).unwrap_or(&Ty(TyKind::Unknown))
} }
} }
@ -177,7 +178,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::Unknown) self.type_of_pat.get(pat).unwrap_or(&Ty(TyKind::Unknown))
} }
} }
@ -226,7 +227,7 @@ impl<'a> InferenceContext<'a> {
result: InferenceResult::default(), result: InferenceResult::default(),
table: unify::InferenceTable::new(), table: unify::InferenceTable::new(),
obligations: Vec::default(), obligations: Vec::default(),
return_ty: Ty::Unknown, // set in collect_fn_signature return_ty: TyKind::Unknown.intern(&Interner), // set in collect_fn_signature
trait_env: TraitEnvironment::lower(db, &resolver), trait_env: TraitEnvironment::lower(db, &resolver),
db, db,
owner, owner,
@ -237,15 +238,19 @@ impl<'a> InferenceContext<'a> {
} }
} }
fn err_ty(&self) -> Ty {
TyKind::Unknown.intern(&Interner)
}
fn resolve_all(mut self) -> InferenceResult { fn resolve_all(mut self) -> InferenceResult {
// FIXME resolve obligations as well (use Guidance if necessary) // FIXME resolve obligations as well (use Guidance if necessary)
let mut result = std::mem::take(&mut self.result); let mut result = std::mem::take(&mut self.result);
for ty in result.type_of_expr.values_mut() { for ty in result.type_of_expr.values_mut() {
let resolved = self.table.resolve_ty_completely(mem::replace(ty, Ty::Unknown)); let resolved = self.table.resolve_ty_completely(ty.clone());
*ty = resolved; *ty = resolved;
} }
for ty in result.type_of_pat.values_mut() { for ty in result.type_of_pat.values_mut() {
let resolved = self.table.resolve_ty_completely(mem::replace(ty, Ty::Unknown)); let resolved = self.table.resolve_ty_completely(ty.clone());
*ty = resolved; *ty = resolved;
} }
result result
@ -298,8 +303,8 @@ impl<'a> InferenceContext<'a> {
/// Replaces Ty::Unknown by a new type var, so we can maybe still infer it. /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it.
fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty { fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty {
match ty { match ty.interned(&Interner) {
Ty::Unknown => self.table.new_type_var(), TyKind::Unknown => self.table.new_type_var(),
_ => ty, _ => ty,
} }
} }
@ -383,7 +388,7 @@ impl<'a> InferenceContext<'a> {
self.obligations.push(Obligation::Projection(projection)); self.obligations.push(Obligation::Projection(projection));
self.resolve_ty_as_possible(ty) self.resolve_ty_as_possible(ty)
} }
None => Ty::Unknown, None => self.err_ty(),
} }
} }
@ -395,8 +400,10 @@ impl<'a> InferenceContext<'a> {
/// to do it as well. /// to do it as well.
fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty { fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty {
let ty = self.resolve_ty_as_possible(ty); let ty = self.resolve_ty_as_possible(ty);
ty.fold(&mut |ty| match ty { ty.fold(&mut |ty| match ty.interned(&Interner) {
Ty::Alias(AliasTy::Projection(proj_ty)) => self.normalize_projection_ty(proj_ty), TyKind::Alias(AliasTy::Projection(proj_ty)) => {
self.normalize_projection_ty(proj_ty.clone())
}
_ => ty, _ => ty,
}) })
} }
@ -412,7 +419,7 @@ impl<'a> InferenceContext<'a> {
fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantId>) { fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantId>) {
let path = match path { let path = match path {
Some(path) => path, Some(path) => path,
None => return (Ty::Unknown, None), None => return (self.err_ty(), None),
}; };
let resolver = &self.resolver; let resolver = &self.resolver;
let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver); let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver);
@ -421,7 +428,7 @@ impl<'a> InferenceContext<'a> {
let (resolution, unresolved) = let (resolution, unresolved) =
match resolver.resolve_path_in_type_ns(self.db.upcast(), path.mod_path()) { match resolver.resolve_path_in_type_ns(self.db.upcast(), path.mod_path()) {
Some(it) => it, Some(it) => it,
None => return (Ty::Unknown, None), None => return (self.err_ty(), None),
}; };
return match resolution { return match resolution {
TypeNs::AdtId(AdtId::StructId(strukt)) => { TypeNs::AdtId(AdtId::StructId(strukt)) => {
@ -462,11 +469,11 @@ impl<'a> InferenceContext<'a> {
} }
} }
// FIXME potentially resolve assoc type // FIXME potentially resolve assoc type
(Ty::Unknown, None) (self.err_ty(), None)
} }
Some(_) => { Some(_) => {
// FIXME diagnostic // FIXME diagnostic
(Ty::Unknown, None) (self.err_ty(), None)
} }
} }
} }
@ -480,15 +487,15 @@ impl<'a> InferenceContext<'a> {
} }
TypeNs::AdtSelfType(_) => { TypeNs::AdtSelfType(_) => {
// FIXME this could happen in array size expressions, once we're checking them // FIXME this could happen in array size expressions, once we're checking them
(Ty::Unknown, None) (self.err_ty(), None)
} }
TypeNs::GenericParam(_) => { TypeNs::GenericParam(_) => {
// FIXME potentially resolve assoc type // FIXME potentially resolve assoc type
(Ty::Unknown, None) (self.err_ty(), None)
} }
TypeNs::AdtId(AdtId::EnumId(_)) | TypeNs::BuiltinType(_) | TypeNs::TraitId(_) => { TypeNs::AdtId(AdtId::EnumId(_)) | TypeNs::BuiltinType(_) | TypeNs::TraitId(_) => {
// FIXME diagnostic // FIXME diagnostic
(Ty::Unknown, None) (self.err_ty(), None)
} }
}; };
@ -500,7 +507,7 @@ impl<'a> InferenceContext<'a> {
result result
} else { } else {
// FIXME diagnostic // FIXME diagnostic
(Ty::Unknown, None) (TyKind::Unknown.intern(&Interner), None)
} }
} }
@ -711,12 +718,12 @@ impl Expectation {
/// This expresses no expectation on the type. /// This expresses no expectation on the type.
fn none() -> Self { fn none() -> Self {
Expectation { ty: Ty::Unknown, rvalue_hint: false } Expectation { 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::Unknown &Ty(TyKind::Unknown)
} else { } else {
&self.ty &self.ty
} }

View file

@ -7,7 +7,7 @@
use chalk_ir::{Mutability, TyVariableKind}; use chalk_ir::{Mutability, TyVariableKind};
use hir_def::lang_item::LangItemTarget; use hir_def::lang_item::LangItemTarget;
use crate::{autoderef, traits::Solution, Obligation, Substs, TraitRef, Ty}; use crate::{autoderef, traits::Solution, Interner, Obligation, Substs, TraitRef, Ty, TyKind};
use super::{InEnvironment, InferenceContext}; use super::{InEnvironment, InferenceContext};
@ -33,7 +33,9 @@ impl<'a> InferenceContext<'a> {
} else if self.coerce(ty2, ty1) { } else if self.coerce(ty2, ty1) {
ty1.clone() ty1.clone()
} else { } else {
if let (Ty::FnDef(..), Ty::FnDef(..)) = (ty1, ty2) { if let (TyKind::FnDef(..), TyKind::FnDef(..)) =
(ty1.interned(&Interner), ty2.interned(&Interner))
{
cov_mark::hit!(coerce_fn_reification); cov_mark::hit!(coerce_fn_reification);
// Special case: two function types. Try to coerce both to // Special case: two function types. Try to coerce both to
// pointers to have a chance at getting a match. See // pointers to have a chance at getting a match. See
@ -51,13 +53,13 @@ impl<'a> InferenceContext<'a> {
} }
fn coerce_inner(&mut self, mut from_ty: Ty, to_ty: &Ty) -> bool { fn coerce_inner(&mut self, mut from_ty: Ty, to_ty: &Ty) -> bool {
match (&from_ty, to_ty) { match (from_ty.interned(&Interner), to_ty.interned(&Interner)) {
// Never type will make type variable to fallback to Never Type instead of Unknown. // Never type will make type variable to fallback to Never Type instead of Unknown.
(Ty::Never, Ty::InferenceVar(tv, TyVariableKind::General)) => { (TyKind::Never, TyKind::InferenceVar(tv, TyVariableKind::General)) => {
self.table.type_variable_table.set_diverging(*tv, true); self.table.type_variable_table.set_diverging(*tv, true);
return true; return true;
} }
(Ty::Never, _) => return true, (TyKind::Never, _) => return true,
// Trivial cases, this should go after `never` check to // Trivial cases, this should go after `never` check to
// avoid infer result type to be never // avoid infer result type to be never
@ -69,33 +71,33 @@ impl<'a> InferenceContext<'a> {
} }
// Pointer weakening and function to pointer // Pointer weakening and function to pointer
match (&mut from_ty, to_ty) { match (&mut from_ty.0, to_ty.interned(&Interner)) {
// `*mut T` -> `*const T` // `*mut T` -> `*const T`
// `&mut T` -> `&T` // `&mut T` -> `&T`
(Ty::Raw(m1, ..), Ty::Raw(m2 @ Mutability::Not, ..)) (TyKind::Raw(m1, ..), TyKind::Raw(m2 @ Mutability::Not, ..))
| (Ty::Ref(m1, ..), Ty::Ref(m2 @ Mutability::Not, ..)) => { | (TyKind::Ref(m1, ..), TyKind::Ref(m2 @ Mutability::Not, ..)) => {
*m1 = *m2; *m1 = *m2;
} }
// `&T` -> `*const T` // `&T` -> `*const T`
// `&mut T` -> `*mut T`/`*const T` // `&mut T` -> `*mut T`/`*const T`
(Ty::Ref(.., substs), &Ty::Raw(m2 @ Mutability::Not, ..)) (TyKind::Ref(.., substs), &TyKind::Raw(m2 @ Mutability::Not, ..))
| (Ty::Ref(Mutability::Mut, substs), &Ty::Raw(m2, ..)) => { | (TyKind::Ref(Mutability::Mut, substs), &TyKind::Raw(m2, ..)) => {
from_ty = Ty::Raw(m2, substs.clone()); from_ty = TyKind::Raw(m2, substs.clone()).intern(&Interner);
} }
// Illegal mutability conversion // Illegal mutability conversion
(Ty::Raw(Mutability::Not, ..), Ty::Raw(Mutability::Mut, ..)) (TyKind::Raw(Mutability::Not, ..), TyKind::Raw(Mutability::Mut, ..))
| (Ty::Ref(Mutability::Not, ..), Ty::Ref(Mutability::Mut, ..)) => return false, | (TyKind::Ref(Mutability::Not, ..), TyKind::Ref(Mutability::Mut, ..)) => return false,
// `{function_type}` -> `fn()` // `{function_type}` -> `fn()`
(Ty::FnDef(..), Ty::Function { .. }) => match from_ty.callable_sig(self.db) { (TyKind::FnDef(..), TyKind::Function { .. }) => match from_ty.callable_sig(self.db) {
None => return false, None => return false,
Some(sig) => { Some(sig) => {
from_ty = Ty::fn_ptr(sig); from_ty = Ty::fn_ptr(sig);
} }
}, },
(Ty::Closure(.., substs), Ty::Function { .. }) => { (TyKind::Closure(.., substs), TyKind::Function { .. }) => {
from_ty = substs[0].clone(); from_ty = substs[0].clone();
} }
@ -107,9 +109,11 @@ impl<'a> InferenceContext<'a> {
} }
// Auto Deref if cannot coerce // Auto Deref if cannot coerce
match (&from_ty, to_ty) { match (from_ty.interned(&Interner), to_ty.interned(&Interner)) {
// FIXME: DerefMut // FIXME: DerefMut
(Ty::Ref(_, st1), Ty::Ref(_, st2)) => self.unify_autoderef_behind_ref(&st1[0], &st2[0]), (TyKind::Ref(_, st1), TyKind::Ref(_, 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),

View file

@ -20,8 +20,8 @@ use crate::{
primitive::{self, UintTy}, primitive::{self, UintTy},
traits::{FnTrait, InEnvironment}, traits::{FnTrait, InEnvironment},
utils::{generics, variant_data, Generics}, utils::{generics, variant_data, Generics},
AdtId, Binders, CallableDefId, FnPointer, FnSig, Obligation, OpaqueTyId, Rawness, Scalar, AdtId, Binders, CallableDefId, FnPointer, FnSig, Interner, Obligation, OpaqueTyId, Rawness,
Substs, TraitRef, Ty, Scalar, Substs, TraitRef, Ty, TyKind,
}; };
use super::{ use super::{
@ -57,7 +57,7 @@ impl<'a> InferenceContext<'a> {
// Return actual type when type mismatch. // Return actual type when type mismatch.
// This is needed for diagnostic when return type mismatch. // This is needed for diagnostic when return type mismatch.
ty ty
} else if expected.coercion_target() == &Ty::Unknown { } else if expected.coercion_target().is_unknown() {
ty ty
} else { } else {
expected.ty.clone() expected.ty.clone()
@ -84,7 +84,7 @@ impl<'a> InferenceContext<'a> {
arg_tys.push(arg); arg_tys.push(arg);
} }
let parameters = param_builder.build(); let parameters = param_builder.build();
let arg_ty = Ty::Tuple(num_args, parameters); let arg_ty = TyKind::Tuple(num_args, parameters).intern(&Interner);
let substs = let substs =
Substs::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build(); Substs::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build();
@ -116,10 +116,13 @@ impl<'a> InferenceContext<'a> {
fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
let body = Arc::clone(&self.body); // avoid borrow checker problem let body = Arc::clone(&self.body); // avoid borrow checker problem
let ty = match &body[tgt_expr] { let ty = match &body[tgt_expr] {
Expr::Missing => Ty::Unknown, Expr::Missing => self.err_ty(),
Expr::If { condition, then_branch, else_branch } => { Expr::If { condition, then_branch, else_branch } => {
// if let is desugared to match, so this is always simple if // if let is desugared to match, so this is always simple if
self.infer_expr(*condition, &Expectation::has_type(Ty::Scalar(Scalar::Bool))); self.infer_expr(
*condition,
&Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(&Interner)),
);
let condition_diverges = mem::replace(&mut self.diverges, Diverges::Maybe); let condition_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
let mut both_arms_diverge = Diverges::Always; let mut both_arms_diverge = Diverges::Always;
@ -167,14 +170,14 @@ impl<'a> InferenceContext<'a> {
Expr::TryBlock { body } => { Expr::TryBlock { body } => {
let _inner = self.infer_expr(*body, expected); let _inner = self.infer_expr(*body, expected);
// FIXME should be std::result::Result<{inner}, _> // FIXME should be std::result::Result<{inner}, _>
Ty::Unknown self.err_ty()
} }
Expr::Async { body } => { Expr::Async { body } => {
// Use the first type parameter as the output type of future. // Use the first type parameter as the output type of future.
// existenail type AsyncBlockImplTrait<InnerType>: Future<Output = InnerType> // existenail type AsyncBlockImplTrait<InnerType>: Future<Output = InnerType>
let inner_ty = self.infer_expr(*body, &Expectation::none()); let inner_ty = self.infer_expr(*body, &Expectation::none());
let opaque_ty_id = OpaqueTyId::AsyncBlockTypeImplTrait(self.owner, *body); let opaque_ty_id = OpaqueTyId::AsyncBlockTypeImplTrait(self.owner, *body);
Ty::OpaqueType(opaque_ty_id, Substs::single(inner_ty)) TyKind::OpaqueType(opaque_ty_id, Substs::single(inner_ty)).intern(&Interner)
} }
Expr::Loop { body, label } => { Expr::Loop { body, label } => {
self.breakables.push(BreakableContext { self.breakables.push(BreakableContext {
@ -192,17 +195,20 @@ impl<'a> InferenceContext<'a> {
if ctxt.may_break { if ctxt.may_break {
ctxt.break_ty ctxt.break_ty
} else { } else {
Ty::Never TyKind::Never.intern(&Interner)
} }
} }
Expr::While { condition, body, label } => { Expr::While { condition, body, label } => {
self.breakables.push(BreakableContext { self.breakables.push(BreakableContext {
may_break: false, may_break: false,
break_ty: Ty::Unknown, break_ty: self.err_ty(),
label: label.map(|label| self.body[label].name.clone()), label: label.map(|label| self.body[label].name.clone()),
}); });
// while let is desugared to a match loop, so this is always simple while // while let is desugared to a match loop, so this is always simple while
self.infer_expr(*condition, &Expectation::has_type(Ty::Scalar(Scalar::Bool))); self.infer_expr(
*condition,
&Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(&Interner)),
);
self.infer_expr(*body, &Expectation::has_type(Ty::unit())); self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
let _ctxt = self.breakables.pop().expect("breakable stack broken"); let _ctxt = self.breakables.pop().expect("breakable stack broken");
// the body may not run, so it diverging doesn't mean we diverge // the body may not run, so it diverging doesn't mean we diverge
@ -214,7 +220,7 @@ impl<'a> InferenceContext<'a> {
self.breakables.push(BreakableContext { self.breakables.push(BreakableContext {
may_break: false, may_break: false,
break_ty: Ty::Unknown, break_ty: self.err_ty(),
label: label.map(|label| self.body[label].name.clone()), label: label.map(|label| self.body[label].name.clone()),
}); });
let pat_ty = let pat_ty =
@ -249,12 +255,14 @@ impl<'a> InferenceContext<'a> {
None => self.table.new_type_var(), None => self.table.new_type_var(),
}; };
sig_tys.push(ret_ty.clone()); sig_tys.push(ret_ty.clone());
let sig_ty = Ty::Function(FnPointer { let sig_ty = TyKind::Function(FnPointer {
num_args: sig_tys.len() - 1, num_args: sig_tys.len() - 1,
sig: FnSig { variadic: false }, sig: FnSig { variadic: false },
substs: Substs(sig_tys.clone().into()), substs: Substs(sig_tys.clone().into()),
}); })
let closure_ty = Ty::Closure(self.owner, tgt_expr, Substs::single(sig_ty)); .intern(&Interner);
let closure_ty =
TyKind::Closure(self.owner, tgt_expr, Substs::single(sig_ty)).intern(&Interner);
// Eagerly try to relate the closure type with the expected // Eagerly try to relate the closure type with the expected
// type, otherwise we often won't have enough information to // type, otherwise we often won't have enough information to
@ -295,7 +303,7 @@ impl<'a> InferenceContext<'a> {
args.len(), args.len(),
) )
}) })
.unwrap_or((Vec::new(), Ty::Unknown)); .unwrap_or((Vec::new(), self.err_ty()));
self.register_obligations_for_call(&callee_ty); self.register_obligations_for_call(&callee_ty);
self.check_call_arguments(args, &param_tys); self.check_call_arguments(args, &param_tys);
self.normalize_associated_types_in(ret_ty) self.normalize_associated_types_in(ret_ty)
@ -305,8 +313,11 @@ impl<'a> InferenceContext<'a> {
Expr::Match { expr, arms } => { Expr::Match { expr, arms } => {
let input_ty = self.infer_expr(*expr, &Expectation::none()); let input_ty = self.infer_expr(*expr, &Expectation::none());
let mut result_ty = let mut result_ty = if arms.is_empty() {
if arms.is_empty() { Ty::Never } else { self.table.new_type_var() }; TyKind::Never.intern(&Interner)
} else {
self.table.new_type_var()
};
let matchee_diverges = self.diverges; let matchee_diverges = self.diverges;
let mut all_arms_diverge = Diverges::Always; let mut all_arms_diverge = Diverges::Always;
@ -317,7 +328,7 @@ impl<'a> InferenceContext<'a> {
if let Some(guard_expr) = arm.guard { if let Some(guard_expr) = arm.guard {
self.infer_expr( self.infer_expr(
guard_expr, guard_expr,
&Expectation::has_type(Ty::Scalar(Scalar::Bool)), &Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(&Interner)),
); );
} }
@ -333,9 +344,9 @@ impl<'a> InferenceContext<'a> {
Expr::Path(p) => { Expr::Path(p) => {
// FIXME this could be more efficient... // FIXME this could be more efficient...
let resolver = resolver_for_expr(self.db.upcast(), self.owner, tgt_expr); let resolver = resolver_for_expr(self.db.upcast(), self.owner, tgt_expr);
self.infer_path(&resolver, p, tgt_expr.into()).unwrap_or(Ty::Unknown) self.infer_path(&resolver, p, tgt_expr.into()).unwrap_or(self.err_ty())
} }
Expr::Continue { .. } => Ty::Never, Expr::Continue { .. } => TyKind::Never.intern(&Interner),
Expr::Break { expr, label } => { Expr::Break { expr, label } => {
let val_ty = if let Some(expr) = expr { let val_ty = if let Some(expr) = expr {
self.infer_expr(*expr, &Expectation::none()) self.infer_expr(*expr, &Expectation::none())
@ -347,7 +358,7 @@ impl<'a> InferenceContext<'a> {
if let Some(ctxt) = find_breakable(&mut self.breakables, label.as_ref()) { if let Some(ctxt) = find_breakable(&mut self.breakables, label.as_ref()) {
ctxt.break_ty.clone() ctxt.break_ty.clone()
} else { } else {
Ty::Unknown self.err_ty()
}; };
let merged_type = self.coerce_merge_branch(&last_ty, &val_ty); let merged_type = self.coerce_merge_branch(&last_ty, &val_ty);
@ -360,7 +371,7 @@ impl<'a> InferenceContext<'a> {
expr: tgt_expr, expr: tgt_expr,
}); });
} }
Ty::Never TyKind::Never.intern(&Interner)
} }
Expr::Return { expr } => { Expr::Return { expr } => {
if let Some(expr) = expr { if let Some(expr) = expr {
@ -369,14 +380,14 @@ impl<'a> InferenceContext<'a> {
let unit = Ty::unit(); let unit = Ty::unit();
self.coerce(&unit, &self.return_ty.clone()); self.coerce(&unit, &self.return_ty.clone());
} }
Ty::Never TyKind::Never.intern(&Interner)
} }
Expr::Yield { expr } => { Expr::Yield { expr } => {
// FIXME: track yield type for coercion // FIXME: track yield type for coercion
if let Some(expr) = expr { if let Some(expr) = expr {
self.infer_expr(*expr, &Expectation::none()); self.infer_expr(*expr, &Expectation::none());
} }
Ty::Never TyKind::Never.intern(&Interner)
} }
Expr::RecordLit { path, fields, spread } => { Expr::RecordLit { path, fields, spread } => {
let (ty, def_id) = self.resolve_variant(path.as_ref()); let (ty, def_id) = self.resolve_variant(path.as_ref());
@ -404,8 +415,9 @@ impl<'a> InferenceContext<'a> {
if let Some(field_def) = field_def { if let Some(field_def) = field_def {
self.result.record_field_resolutions.insert(field.expr, field_def); self.result.record_field_resolutions.insert(field.expr, field_def);
} }
let field_ty = field_def let field_ty = field_def.map_or(self.err_ty(), |it| {
.map_or(Ty::Unknown, |it| field_types[it.local_id].clone().subst(&substs)); field_types[it.local_id].clone().subst(&substs)
});
self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty)); self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty));
} }
if let Some(expr) = spread { if let Some(expr) = spread {
@ -424,27 +436,33 @@ impl<'a> InferenceContext<'a> {
environment: self.trait_env.clone(), environment: self.trait_env.clone(),
}, },
) )
.find_map(|derefed_ty| match canonicalized.decanonicalize_ty(derefed_ty.value) { .find_map(|derefed_ty| {
Ty::Tuple(_, substs) => { match canonicalized.decanonicalize_ty(derefed_ty.value).interned(&Interner) {
name.as_tuple_index().and_then(|idx| substs.0.get(idx).cloned()) TyKind::Tuple(_, substs) => {
name.as_tuple_index().and_then(|idx| substs.0.get(idx).cloned())
}
TyKind::Adt(AdtId(hir_def::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(&parameters)
})
}
TyKind::Adt(AdtId(hir_def::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(&parameters)
})
}
_ => None,
} }
Ty::Adt(AdtId(hir_def::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(&parameters)
})
}
Ty::Adt(AdtId(hir_def::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(&parameters)
})
}
_ => None,
}) })
.unwrap_or(Ty::Unknown); .unwrap_or(self.err_ty());
let ty = self.insert_type_vars(ty); let ty = self.insert_type_vars(ty);
self.normalize_associated_types_in(ty) self.normalize_associated_types_in(ty)
} }
@ -481,9 +499,10 @@ 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 => Ty::Raw(mutability, Substs::single(inner_ty)), Rawness::RawPtr => TyKind::Raw(mutability, Substs::single(inner_ty)),
Rawness::Ref => Ty::Ref(mutability, Substs::single(inner_ty)), Rawness::Ref => TyKind::Ref(mutability, Substs::single(inner_ty)),
} }
.intern(&Interner)
} }
Expr::Box { expr } => { Expr::Box { expr } => {
let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
@ -499,7 +518,7 @@ impl<'a> InferenceContext<'a> {
sb = sb.fill(repeat_with(|| self.table.new_type_var())); sb = sb.fill(repeat_with(|| self.table.new_type_var()));
Ty::adt_ty(box_, sb.build()) Ty::adt_ty(box_, sb.build())
} else { } else {
Ty::Unknown self.err_ty()
} }
} }
Expr::UnaryOp { expr, op } => { Expr::UnaryOp { expr, op } => {
@ -519,31 +538,31 @@ impl<'a> InferenceContext<'a> {
Some(derefed_ty) => { Some(derefed_ty) => {
canonicalized.decanonicalize_ty(derefed_ty.value) canonicalized.decanonicalize_ty(derefed_ty.value)
} }
None => Ty::Unknown, None => self.err_ty(),
} }
} }
None => Ty::Unknown, None => self.err_ty(),
}, },
UnaryOp::Neg => { UnaryOp::Neg => {
match &inner_ty { match inner_ty.interned(&Interner) {
// Fast path for builtins // Fast path for builtins
Ty::Scalar(Scalar::Int(_)) TyKind::Scalar(Scalar::Int(_))
| Ty::Scalar(Scalar::Uint(_)) | TyKind::Scalar(Scalar::Uint(_))
| Ty::Scalar(Scalar::Float(_)) | TyKind::Scalar(Scalar::Float(_))
| Ty::InferenceVar(_, TyVariableKind::Integer) | TyKind::InferenceVar(_, TyVariableKind::Integer)
| Ty::InferenceVar(_, TyVariableKind::Float) => inner_ty, | TyKind::InferenceVar(_, TyVariableKind::Float) => inner_ty,
// Otherwise we resolve via the std::ops::Neg trait // Otherwise we resolve via the std::ops::Neg trait
_ => self _ => self
.resolve_associated_type(inner_ty, self.resolve_ops_neg_output()), .resolve_associated_type(inner_ty, self.resolve_ops_neg_output()),
} }
} }
UnaryOp::Not => { UnaryOp::Not => {
match &inner_ty { match inner_ty.interned(&Interner) {
// Fast path for builtins // Fast path for builtins
Ty::Scalar(Scalar::Bool) TyKind::Scalar(Scalar::Bool)
| Ty::Scalar(Scalar::Int(_)) | TyKind::Scalar(Scalar::Int(_))
| Ty::Scalar(Scalar::Uint(_)) | TyKind::Scalar(Scalar::Uint(_))
| Ty::InferenceVar(_, TyVariableKind::Integer) => inner_ty, | TyKind::InferenceVar(_, TyVariableKind::Integer) => inner_ty,
// Otherwise we resolve via the std::ops::Not trait // Otherwise we resolve via the std::ops::Not trait
_ => self _ => self
.resolve_associated_type(inner_ty, self.resolve_ops_not_output()), .resolve_associated_type(inner_ty, self.resolve_ops_not_output()),
@ -554,7 +573,9 @@ impl<'a> InferenceContext<'a> {
Expr::BinaryOp { lhs, rhs, op } => match op { Expr::BinaryOp { lhs, rhs, op } => match op {
Some(op) => { Some(op) => {
let lhs_expectation = match op { let lhs_expectation = match op {
BinaryOp::LogicOp(..) => Expectation::has_type(Ty::Scalar(Scalar::Bool)), BinaryOp::LogicOp(..) => {
Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(&Interner))
}
_ => Expectation::none(), _ => Expectation::none(),
}; };
let lhs_ty = self.infer_expr(*lhs, &lhs_expectation); let lhs_ty = self.infer_expr(*lhs, &lhs_expectation);
@ -563,7 +584,7 @@ impl<'a> InferenceContext<'a> {
let ret = op::binary_op_return_ty(*op, lhs_ty.clone(), rhs_ty.clone()); let ret = op::binary_op_return_ty(*op, lhs_ty.clone(), rhs_ty.clone());
if ret == Ty::Unknown { if ret.is_unknown() {
cov_mark::hit!(infer_expr_inner_binary_operator_overload); cov_mark::hit!(infer_expr_inner_binary_operator_overload);
self.resolve_associated_type_with_params( self.resolve_associated_type_with_params(
@ -575,7 +596,7 @@ impl<'a> InferenceContext<'a> {
ret ret
} }
} }
_ => Ty::Unknown, _ => self.err_ty(),
}, },
Expr::Range { lhs, rhs, range_type } => { Expr::Range { lhs, rhs, range_type } => {
let lhs_ty = lhs.map(|e| self.infer_expr_inner(e, &Expectation::none())); let lhs_ty = lhs.map(|e| self.infer_expr_inner(e, &Expectation::none()));
@ -586,33 +607,33 @@ impl<'a> InferenceContext<'a> {
match (range_type, lhs_ty, rhs_ty) { match (range_type, lhs_ty, rhs_ty) {
(RangeOp::Exclusive, None, None) => match self.resolve_range_full() { (RangeOp::Exclusive, None, None) => match self.resolve_range_full() {
Some(adt) => Ty::adt_ty(adt, Substs::empty()), Some(adt) => Ty::adt_ty(adt, Substs::empty()),
None => Ty::Unknown, None => self.err_ty(),
}, },
(RangeOp::Exclusive, None, Some(ty)) => match self.resolve_range_to() { (RangeOp::Exclusive, None, Some(ty)) => match self.resolve_range_to() {
Some(adt) => Ty::adt_ty(adt, Substs::single(ty)), Some(adt) => Ty::adt_ty(adt, Substs::single(ty)),
None => Ty::Unknown, None => self.err_ty(),
}, },
(RangeOp::Inclusive, None, Some(ty)) => { (RangeOp::Inclusive, None, Some(ty)) => {
match self.resolve_range_to_inclusive() { match self.resolve_range_to_inclusive() {
Some(adt) => Ty::adt_ty(adt, Substs::single(ty)), Some(adt) => Ty::adt_ty(adt, Substs::single(ty)),
None => Ty::Unknown, None => self.err_ty(),
} }
} }
(RangeOp::Exclusive, Some(_), Some(ty)) => match self.resolve_range() { (RangeOp::Exclusive, Some(_), Some(ty)) => match self.resolve_range() {
Some(adt) => Ty::adt_ty(adt, Substs::single(ty)), Some(adt) => Ty::adt_ty(adt, Substs::single(ty)),
None => Ty::Unknown, None => self.err_ty(),
}, },
(RangeOp::Inclusive, Some(_), Some(ty)) => { (RangeOp::Inclusive, Some(_), Some(ty)) => {
match self.resolve_range_inclusive() { match self.resolve_range_inclusive() {
Some(adt) => Ty::adt_ty(adt, Substs::single(ty)), Some(adt) => Ty::adt_ty(adt, Substs::single(ty)),
None => Ty::Unknown, None => self.err_ty(),
} }
} }
(RangeOp::Exclusive, Some(ty), None) => match self.resolve_range_from() { (RangeOp::Exclusive, Some(ty), None) => match self.resolve_range_from() {
Some(adt) => Ty::adt_ty(adt, Substs::single(ty)), Some(adt) => Ty::adt_ty(adt, Substs::single(ty)),
None => Ty::Unknown, None => self.err_ty(),
}, },
(RangeOp::Inclusive, _, None) => Ty::Unknown, (RangeOp::Inclusive, _, None) => self.err_ty(),
} }
} }
Expr::Index { base, index } => { Expr::Index { base, index } => {
@ -631,19 +652,19 @@ impl<'a> InferenceContext<'a> {
index_trait, index_trait,
); );
let self_ty = let self_ty =
self_ty.map_or(Ty::Unknown, |t| canonicalized.decanonicalize_ty(t.value)); self_ty.map_or(self.err_ty(), |t| canonicalized.decanonicalize_ty(t.value));
self.resolve_associated_type_with_params( self.resolve_associated_type_with_params(
self_ty, self_ty,
self.resolve_ops_index_output(), self.resolve_ops_index_output(),
&[index_ty], &[index_ty],
) )
} else { } else {
Ty::Unknown self.err_ty()
} }
} }
Expr::Tuple { exprs } => { Expr::Tuple { exprs } => {
let mut tys = match &expected.ty { let mut tys = match expected.ty.interned(&Interner) {
Ty::Tuple(_, substs) => substs TyKind::Tuple(_, substs) => substs
.iter() .iter()
.cloned() .cloned()
.chain(repeat_with(|| self.table.new_type_var())) .chain(repeat_with(|| self.table.new_type_var()))
@ -656,11 +677,11 @@ impl<'a> InferenceContext<'a> {
self.infer_expr_coerce(*expr, &Expectation::has_type(ty.clone())); self.infer_expr_coerce(*expr, &Expectation::has_type(ty.clone()));
} }
Ty::Tuple(tys.len(), Substs(tys.into())) TyKind::Tuple(tys.len(), Substs(tys.into())).intern(&Interner)
} }
Expr::Array(array) => { Expr::Array(array) => {
let elem_ty = match &expected.ty { let elem_ty = match expected.ty.interned(&Interner) {
Ty::Array(st) | Ty::Slice(st) => st.as_single().clone(), TyKind::Array(st) | TyKind::Slice(st) => st.as_single().clone(),
_ => self.table.new_type_var(), _ => self.table.new_type_var(),
}; };
@ -677,43 +698,51 @@ impl<'a> InferenceContext<'a> {
); );
self.infer_expr( self.infer_expr(
*repeat, *repeat,
&Expectation::has_type(Ty::Scalar(Scalar::Uint(UintTy::Usize))), &Expectation::has_type(
TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner),
),
); );
} }
} }
Ty::Array(Substs::single(elem_ty)) TyKind::Array(Substs::single(elem_ty)).intern(&Interner)
} }
Expr::Literal(lit) => match lit { Expr::Literal(lit) => match lit {
Literal::Bool(..) => Ty::Scalar(Scalar::Bool), Literal::Bool(..) => TyKind::Scalar(Scalar::Bool).intern(&Interner),
Literal::String(..) => Ty::Ref(Mutability::Not, Substs::single(Ty::Str)), Literal::String(..) => {
Literal::ByteString(..) => { TyKind::Ref(Mutability::Not, Substs::single(TyKind::Str.intern(&Interner)))
let byte_type = Ty::Scalar(Scalar::Uint(UintTy::U8)); .intern(&Interner)
let array_type = Ty::Array(Substs::single(byte_type));
Ty::Ref(Mutability::Not, Substs::single(array_type))
} }
Literal::Char(..) => Ty::Scalar(Scalar::Char), 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)
}
Literal::Char(..) => TyKind::Scalar(Scalar::Char).intern(&Interner),
Literal::Int(_v, ty) => match ty { Literal::Int(_v, ty) => match ty {
Some(int_ty) => { Some(int_ty) => {
Ty::Scalar(Scalar::Int(primitive::int_ty_from_builtin(*int_ty))) TyKind::Scalar(Scalar::Int(primitive::int_ty_from_builtin(*int_ty)))
.intern(&Interner)
} }
None => self.table.new_integer_var(), None => self.table.new_integer_var(),
}, },
Literal::Uint(_v, ty) => match ty { Literal::Uint(_v, ty) => match ty {
Some(int_ty) => { Some(int_ty) => {
Ty::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(*int_ty))) TyKind::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(*int_ty)))
.intern(&Interner)
} }
None => self.table.new_integer_var(), None => self.table.new_integer_var(),
}, },
Literal::Float(_v, ty) => match ty { Literal::Float(_v, ty) => match ty {
Some(float_ty) => { Some(float_ty) => {
Ty::Scalar(Scalar::Float(primitive::float_ty_from_builtin(*float_ty))) TyKind::Scalar(Scalar::Float(primitive::float_ty_from_builtin(*float_ty)))
.intern(&Interner)
} }
None => self.table.new_float_var(), None => self.table.new_float_var(),
}, },
}, },
}; };
// use a new type variable if we got Ty::Unknown here // use a new type variable if we got unknown here
let ty = self.insert_type_vars_shallow(ty); let ty = self.insert_type_vars_shallow(ty);
let ty = self.resolve_ty_as_possible(ty); let ty = self.resolve_ty_as_possible(ty);
self.write_expr_ty(tgt_expr, ty.clone()); self.write_expr_ty(tgt_expr, ty.clone());
@ -730,7 +759,7 @@ impl<'a> InferenceContext<'a> {
match stmt { match stmt {
Statement::Let { pat, type_ref, initializer } => { Statement::Let { pat, type_ref, initializer } => {
let decl_ty = let decl_ty =
type_ref.as_ref().map(|tr| self.make_ty(tr)).unwrap_or(Ty::Unknown); type_ref.as_ref().map(|tr| self.make_ty(tr)).unwrap_or(self.err_ty());
// Always use the declared type when specified // Always use the declared type when specified
let mut ty = decl_ty.clone(); let mut ty = decl_ty.clone();
@ -738,7 +767,7 @@ impl<'a> InferenceContext<'a> {
if let Some(expr) = initializer { if let Some(expr) = initializer {
let actual_ty = let actual_ty =
self.infer_expr_coerce(*expr, &Expectation::has_type(decl_ty.clone())); self.infer_expr_coerce(*expr, &Expectation::has_type(decl_ty.clone()));
if decl_ty == Ty::Unknown { if decl_ty.is_unknown() {
ty = actual_ty; ty = actual_ty;
} }
} }
@ -802,7 +831,7 @@ impl<'a> InferenceContext<'a> {
self.write_method_resolution(tgt_expr, func); self.write_method_resolution(tgt_expr, func);
(ty, self.db.value_ty(func.into()), Some(generics(self.db.upcast(), func.into()))) (ty, self.db.value_ty(func.into()), Some(generics(self.db.upcast(), func.into())))
} }
None => (receiver_ty, Binders::new(0, Ty::Unknown), None), None => (receiver_ty, Binders::new(0, self.err_ty()), None),
}; };
let substs = self.substs_for_method_call(def_generics, generic_args, &derefed_receiver_ty); let substs = self.substs_for_method_call(def_generics, generic_args, &derefed_receiver_ty);
let method_ty = method_ty.subst(&substs); let method_ty = method_ty.subst(&substs);
@ -813,15 +842,17 @@ impl<'a> InferenceContext<'a> {
if !sig.params().is_empty() { if !sig.params().is_empty() {
(sig.params()[0].clone(), sig.params()[1..].to_vec(), sig.ret().clone()) (sig.params()[0].clone(), sig.params()[1..].to_vec(), sig.ret().clone())
} else { } else {
(Ty::Unknown, Vec::new(), sig.ret().clone()) (self.err_ty(), Vec::new(), sig.ret().clone())
} }
} }
None => (Ty::Unknown, Vec::new(), Ty::Unknown), None => (self.err_ty(), Vec::new(), self.err_ty()),
}; };
// 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)) => Ty::Ref(mutability, Substs::single(derefed_receiver_ty)), Some((_, mutability)) => {
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);
@ -837,7 +868,7 @@ impl<'a> InferenceContext<'a> {
// that we have more information about the types of arguments when we // that we have more information about the types of arguments when we
// type-check the functions. This isn't really the right way to do this. // type-check the functions. This isn't really the right way to do this.
for &check_closures in &[false, true] { for &check_closures in &[false, true] {
let param_iter = param_tys.iter().cloned().chain(repeat(Ty::Unknown)); let param_iter = param_tys.iter().cloned().chain(repeat(self.err_ty()));
for (&arg, param_ty) in args.iter().zip(param_iter) { for (&arg, param_ty) in args.iter().zip(param_iter) {
let is_closure = matches!(&self.body[arg], Expr::Lambda { .. }); let is_closure = matches!(&self.body[arg], Expr::Lambda { .. });
if is_closure != check_closures { if is_closure != check_closures {
@ -867,7 +898,7 @@ impl<'a> InferenceContext<'a> {
if param.provenance == hir_def::generics::TypeParamProvenance::TraitSelf { if param.provenance == hir_def::generics::TypeParamProvenance::TraitSelf {
substs.push(receiver_ty.clone()); substs.push(receiver_ty.clone());
} else { } else {
substs.push(Ty::Unknown); substs.push(self.err_ty());
} }
} }
} }
@ -891,15 +922,15 @@ impl<'a> InferenceContext<'a> {
}; };
let supplied_params = substs.len(); let supplied_params = substs.len();
for _ in supplied_params..total_len { for _ in supplied_params..total_len {
substs.push(Ty::Unknown); substs.push(self.err_ty());
} }
assert_eq!(substs.len(), total_len); assert_eq!(substs.len(), total_len);
Substs(substs.into()) Substs(substs.into())
} }
fn register_obligations_for_call(&mut self, callable_ty: &Ty) { fn register_obligations_for_call(&mut self, callable_ty: &Ty) {
if let &Ty::FnDef(def, ref parameters) = callable_ty { if let TyKind::FnDef(def, parameters) = callable_ty.interned(&Interner) {
let generic_predicates = self.db.generic_predicates(def.into()); let generic_predicates = self.db.generic_predicates((*def).into());
for predicate in generic_predicates.iter() { for predicate in generic_predicates.iter() {
let predicate = predicate.clone().subst(parameters); let predicate = predicate.clone().subst(parameters);
if let Some(obligation) = Obligation::from_predicate(predicate) { if let Some(obligation) = Obligation::from_predicate(predicate) {

View file

@ -12,7 +12,7 @@ use hir_def::{
use hir_expand::name::Name; use hir_expand::name::Name;
use super::{BindingMode, Expectation, InferenceContext}; use super::{BindingMode, Expectation, InferenceContext};
use crate::{lower::lower_to_chalk_mutability, utils::variant_data, Substs, Ty}; use crate::{lower::lower_to_chalk_mutability, utils::variant_data, Interner, Substs, Ty, TyKind};
impl<'a> InferenceContext<'a> { impl<'a> InferenceContext<'a> {
fn infer_tuple_struct_pat( fn infer_tuple_struct_pat(
@ -46,7 +46,7 @@ impl<'a> InferenceContext<'a> {
let expected_ty = var_data let expected_ty = var_data
.as_ref() .as_ref()
.and_then(|d| d.field(&Name::new_tuple_field(i))) .and_then(|d| d.field(&Name::new_tuple_field(i)))
.map_or(Ty::Unknown, |field| field_tys[field].clone().subst(&substs)); .map_or(self.err_ty(), |field| field_tys[field].clone().subst(&substs));
let expected_ty = self.normalize_associated_types_in(expected_ty); let expected_ty = self.normalize_associated_types_in(expected_ty);
self.infer_pat(subpat, &expected_ty, default_bm); self.infer_pat(subpat, &expected_ty, default_bm);
} }
@ -80,8 +80,8 @@ impl<'a> InferenceContext<'a> {
self.result.record_pat_field_resolutions.insert(subpat.pat, field_def); self.result.record_pat_field_resolutions.insert(subpat.pat, field_def);
} }
let expected_ty = let expected_ty = matching_field
matching_field.map_or(Ty::Unknown, |field| field_tys[field].clone().subst(&substs)); .map_or(self.err_ty(), |field| field_tys[field].clone().subst(&substs));
let expected_ty = self.normalize_associated_types_in(expected_ty); let expected_ty = self.normalize_associated_types_in(expected_ty);
self.infer_pat(subpat.pat, &expected_ty, default_bm); self.infer_pat(subpat.pat, &expected_ty, default_bm);
} }
@ -129,7 +129,8 @@ impl<'a> InferenceContext<'a> {
None => (&args[..], &[][..]), None => (&args[..], &[][..]),
}; };
let n_uncovered_patterns = expectations.len().saturating_sub(args.len()); let n_uncovered_patterns = expectations.len().saturating_sub(args.len());
let mut expectations_iter = expectations.iter().chain(repeat(&Ty::Unknown)); let err_ty = self.err_ty();
let mut expectations_iter = expectations.iter().chain(repeat(&err_ty));
let mut infer_pat = |(&pat, ty)| self.infer_pat(pat, ty, default_bm); let mut infer_pat = |(&pat, ty)| self.infer_pat(pat, ty, default_bm);
let mut inner_tys = Vec::with_capacity(n_uncovered_patterns + args.len()); let mut inner_tys = Vec::with_capacity(n_uncovered_patterns + args.len());
@ -137,7 +138,7 @@ impl<'a> InferenceContext<'a> {
inner_tys.extend(expectations_iter.by_ref().take(n_uncovered_patterns).cloned()); inner_tys.extend(expectations_iter.by_ref().take(n_uncovered_patterns).cloned());
inner_tys.extend(post.iter().zip(expectations_iter).map(infer_pat)); inner_tys.extend(post.iter().zip(expectations_iter).map(infer_pat));
Ty::Tuple(inner_tys.len(), Substs(inner_tys.into())) TyKind::Tuple(inner_tys.len(), Substs(inner_tys.into())).intern(&Interner)
} }
Pat::Or(ref pats) => { Pat::Or(ref pats) => {
if let Some((first_pat, rest)) = pats.split_first() { if let Some((first_pat, rest)) = pats.split_first() {
@ -147,7 +148,7 @@ impl<'a> InferenceContext<'a> {
} }
ty ty
} else { } else {
Ty::Unknown self.err_ty()
} }
} }
Pat::Ref { pat, mutability } => { Pat::Ref { pat, mutability } => {
@ -159,10 +160,10 @@ impl<'a> InferenceContext<'a> {
} }
inner_ty inner_ty
} }
_ => &Ty::Unknown, _ => &Ty(TyKind::Unknown),
}; };
let subty = self.infer_pat(*pat, expectation, default_bm); let subty = self.infer_pat(*pat, expectation, default_bm);
Ty::Ref(mutability, Substs::single(subty)) 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(
p.as_ref(), p.as_ref(),
@ -178,7 +179,7 @@ impl<'a> InferenceContext<'a> {
Pat::Path(path) => { Pat::Path(path) => {
// FIXME use correct resolver for the surrounding expression // FIXME use correct resolver for the surrounding expression
let resolver = self.resolver.clone(); let resolver = self.resolver.clone();
self.infer_path(&resolver, &path, pat.into()).unwrap_or(Ty::Unknown) self.infer_path(&resolver, &path, pat.into()).unwrap_or(self.err_ty())
} }
Pat::Bind { mode, name: _, subpat } => { Pat::Bind { mode, name: _, subpat } => {
let mode = if mode == &BindingAnnotation::Unannotated { let mode = if mode == &BindingAnnotation::Unannotated {
@ -195,7 +196,7 @@ impl<'a> InferenceContext<'a> {
let bound_ty = match mode { let bound_ty = match mode {
BindingMode::Ref(mutability) => { BindingMode::Ref(mutability) => {
Ty::Ref(mutability, Substs::single(inner_ty.clone())) TyKind::Ref(mutability, Substs::single(inner_ty.clone())).intern(&Interner)
} }
BindingMode::Move => inner_ty.clone(), BindingMode::Move => inner_ty.clone(),
}; };
@ -204,17 +205,17 @@ impl<'a> InferenceContext<'a> {
return inner_ty; return inner_ty;
} }
Pat::Slice { prefix, slice, suffix } => { Pat::Slice { prefix, slice, suffix } => {
let (container_ty, elem_ty): (fn(_) -> _, _) = match &expected { let (container_ty, elem_ty): (fn(_) -> _, _) = match expected.interned(&Interner) {
Ty::Array(st) => (Ty::Array, st.as_single().clone()), TyKind::Array(st) => (TyKind::Array, st.as_single().clone()),
Ty::Slice(st) => (Ty::Slice, st.as_single().clone()), TyKind::Slice(st) => (TyKind::Slice, st.as_single().clone()),
_ => (Ty::Slice, Ty::Unknown), _ => (TyKind::Slice, self.err_ty()),
}; };
for pat_id in prefix.iter().chain(suffix) { for pat_id in prefix.iter().chain(suffix) {
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)); let pat_ty = container_ty(Substs::single(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,20 +233,20 @@ impl<'a> InferenceContext<'a> {
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(),
_ => &Ty::Unknown, _ => &Ty(TyKind::Unknown),
}; };
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 => Ty::Unknown, None => self.err_ty(),
}, },
Pat::ConstBlock(expr) => { Pat::ConstBlock(expr) => {
self.infer_expr(*expr, &Expectation::has_type(expected.clone())) self.infer_expr(*expr, &Expectation::has_type(expected.clone()))
} }
Pat::Missing => Ty::Unknown, Pat::Missing => self.err_ty(),
}; };
// use a new type variable if we got Ty::Unknown here // use a new type variable if we got error type here
let ty = self.insert_type_vars_shallow(ty); let ty = self.insert_type_vars_shallow(ty);
if !self.unify(&ty, expected) { if !self.unify(&ty, expected) {
// FIXME record mismatch, we need to change the type of self.type_mismatches for that // FIXME record mismatch, we need to change the type of self.type_mismatches for that

View file

@ -9,7 +9,7 @@ use hir_def::{
}; };
use hir_expand::name::Name; use hir_expand::name::Name;
use crate::{method_resolution, Substs, Ty, ValueTyDefId}; use crate::{method_resolution, Interner, Substs, Ty, TyKind, ValueTyDefId};
use super::{ExprOrPatId, InferenceContext, TraitRef}; use super::{ExprOrPatId, InferenceContext, TraitRef};
@ -144,7 +144,7 @@ impl<'a> InferenceContext<'a> {
remaining_segments_for_ty, remaining_segments_for_ty,
true, true,
); );
if let Ty::Unknown = ty { if let TyKind::Unknown = ty.interned(&Interner) {
return None; return None;
} }
@ -209,7 +209,7 @@ impl<'a> InferenceContext<'a> {
name: &Name, name: &Name,
id: ExprOrPatId, id: ExprOrPatId,
) -> Option<(ValueNs, Option<Substs>)> { ) -> Option<(ValueNs, Option<Substs>)> {
if let Ty::Unknown = ty { if let TyKind::Unknown = ty.interned(&Interner) {
return None; return None;
} }

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, Scalar, BoundVar, Canonical, DebruijnIndex, GenericPredicate, InEnvironment, InferenceVar, Interner,
Substs, Ty, TypeWalk, Scalar, Substs, Ty, TyKind, TypeWalk,
}; };
impl<'a> InferenceContext<'a> { impl<'a> InferenceContext<'a> {
@ -49,8 +49,8 @@ impl<'a, 'b> Canonicalizer<'a, 'b> {
fn do_canonicalize<T: TypeWalk>(&mut self, t: T, binders: DebruijnIndex) -> T { fn do_canonicalize<T: TypeWalk>(&mut self, t: T, binders: DebruijnIndex) -> T {
t.fold_binders( t.fold_binders(
&mut |ty, binders| match ty { &mut |ty, binders| match ty.interned(&Interner) {
Ty::InferenceVar(var, kind) => { &TyKind::InferenceVar(var, kind) => {
let inner = var.to_inner(); let inner = var.to_inner();
if self.var_stack.contains(&inner) { if self.var_stack.contains(&inner) {
// recursive type // recursive type
@ -66,7 +66,7 @@ impl<'a, 'b> Canonicalizer<'a, 'b> {
} else { } else {
let root = self.ctx.table.var_unification_table.find(inner); let root = self.ctx.table.var_unification_table.find(inner);
let position = self.add(InferenceVar::from_inner(root), kind); let position = self.add(InferenceVar::from_inner(root), kind);
Ty::BoundVar(BoundVar::new(binders, position)) TyKind::BoundVar(BoundVar::new(binders, position)).intern(&Interner)
} }
} }
_ => ty, _ => ty,
@ -108,10 +108,10 @@ 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 Ty::BoundVar(bound) = ty { if let &mut TyKind::BoundVar(bound) = &mut ty.0 {
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 = Ty::InferenceVar(v, k); *ty = TyKind::InferenceVar(v, k).intern(&Interner);
} }
} }
}, },
@ -142,7 +142,7 @@ impl<T> Canonicalized<T> {
// eagerly replace projections in the type; we may be getting types // eagerly replace projections in the type; we may be getting types
// e.g. from where clauses where this hasn't happened yet // e.g. from where clauses where this hasn't happened yet
let ty = ctx.normalize_associated_types_in(ty.clone().subst_bound_vars(&new_vars)); let ty = ctx.normalize_associated_types_in(ty.clone().subst_bound_vars(&new_vars));
ctx.table.unify(&Ty::InferenceVar(v, k), &ty); ctx.table.unify(&TyKind::InferenceVar(v, k).intern(&Interner), &ty);
} }
} }
} }
@ -166,7 +166,10 @@ pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substs> {
// (kind of hacky) // (kind of hacky)
for (i, var) in vars.iter().enumerate() { for (i, var) in vars.iter().enumerate() {
if &*table.resolve_ty_shallow(var) == var { if &*table.resolve_ty_shallow(var) == var {
table.unify(var, &Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i))); table.unify(
var,
&TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i)).intern(&Interner),
);
} }
} }
Some( Some(
@ -196,11 +199,12 @@ impl TypeVariableTable {
fn fallback_value(&self, iv: InferenceVar, kind: TyVariableKind) -> Ty { fn fallback_value(&self, iv: InferenceVar, kind: TyVariableKind) -> Ty {
match kind { match kind {
_ if self.inner[iv.to_inner().0 as usize].diverging => Ty::Never, _ if self.inner[iv.to_inner().0 as usize].diverging => TyKind::Never,
TyVariableKind::General => Ty::Unknown, TyVariableKind::General => TyKind::Unknown,
TyVariableKind::Integer => Ty::Scalar(Scalar::Int(IntTy::I32)), TyVariableKind::Integer => TyKind::Scalar(Scalar::Int(IntTy::I32)),
TyVariableKind::Float => Ty::Scalar(Scalar::Float(FloatTy::F64)), TyVariableKind::Float => TyKind::Scalar(Scalar::Float(FloatTy::F64)),
} }
.intern(&Interner)
} }
} }
@ -227,7 +231,7 @@ impl InferenceTable {
self.type_variable_table.push(TypeVariableData { diverging }); self.type_variable_table.push(TypeVariableData { diverging });
let key = self.var_unification_table.new_key(TypeVarValue::Unknown); let key = self.var_unification_table.new_key(TypeVarValue::Unknown);
assert_eq!(key.0 as usize, self.type_variable_table.inner.len() - 1); assert_eq!(key.0 as usize, self.type_variable_table.inner.len() - 1);
Ty::InferenceVar(InferenceVar::from_inner(key), kind) TyKind::InferenceVar(InferenceVar::from_inner(key), kind).intern(&Interner)
} }
pub(crate) fn new_type_var(&mut self) -> Ty { pub(crate) fn new_type_var(&mut self) -> Ty {
@ -290,12 +294,12 @@ impl InferenceTable {
} }
pub(super) fn unify_inner_trivial(&mut self, ty1: &Ty, ty2: &Ty, depth: usize) -> bool { pub(super) fn unify_inner_trivial(&mut self, ty1: &Ty, ty2: &Ty, depth: usize) -> bool {
match (ty1, ty2) { match (ty1.interned(&Interner), ty2.interned(&Interner)) {
(Ty::Unknown, _) | (_, Ty::Unknown) => true, (TyKind::Unknown, _) | (_, TyKind::Unknown) => true,
(Ty::Placeholder(p1), Ty::Placeholder(p2)) if *p1 == *p2 => true, (TyKind::Placeholder(p1), TyKind::Placeholder(p2)) if *p1 == *p2 => true,
(Ty::Dyn(dyn1), Ty::Dyn(dyn2)) if dyn1.len() == dyn2.len() => { (TyKind::Dyn(dyn1), TyKind::Dyn(dyn2)) if dyn1.len() == dyn2.len() => {
for (pred1, pred2) in dyn1.iter().zip(dyn2.iter()) { for (pred1, pred2) in dyn1.iter().zip(dyn2.iter()) {
if !self.unify_preds(pred1, pred2, depth + 1) { if !self.unify_preds(pred1, pred2, depth + 1) {
return false; return false;
@ -305,16 +309,16 @@ impl InferenceTable {
} }
( (
Ty::InferenceVar(tv1, TyVariableKind::General), TyKind::InferenceVar(tv1, TyVariableKind::General),
Ty::InferenceVar(tv2, TyVariableKind::General), TyKind::InferenceVar(tv2, TyVariableKind::General),
) )
| ( | (
Ty::InferenceVar(tv1, TyVariableKind::Integer), TyKind::InferenceVar(tv1, TyVariableKind::Integer),
Ty::InferenceVar(tv2, TyVariableKind::Integer), TyKind::InferenceVar(tv2, TyVariableKind::Integer),
) )
| ( | (
Ty::InferenceVar(tv1, TyVariableKind::Float), TyKind::InferenceVar(tv1, TyVariableKind::Float),
Ty::InferenceVar(tv2, TyVariableKind::Float), TyKind::InferenceVar(tv2, TyVariableKind::Float),
) if self.type_variable_table.is_diverging(*tv1) ) if self.type_variable_table.is_diverging(*tv1)
== self.type_variable_table.is_diverging(*tv2) => == self.type_variable_table.is_diverging(*tv2) =>
{ {
@ -326,24 +330,37 @@ impl InferenceTable {
// The order of MaybeNeverTypeVar matters here. // The order of MaybeNeverTypeVar matters here.
// Unifying MaybeNeverTypeVar and TypeVar will let the latter become MaybeNeverTypeVar. // Unifying MaybeNeverTypeVar and TypeVar will let the latter become MaybeNeverTypeVar.
// Unifying MaybeNeverTypeVar and other concrete type will let the former become it. // Unifying MaybeNeverTypeVar and other concrete type will let the former become it.
(Ty::InferenceVar(tv, TyVariableKind::General), other) (TyKind::InferenceVar(tv, TyVariableKind::General), other)
| (other, Ty::InferenceVar(tv, TyVariableKind::General)) | (other, TyKind::InferenceVar(tv, TyVariableKind::General))
| (Ty::InferenceVar(tv, TyVariableKind::Integer), other @ Ty::Scalar(Scalar::Int(_)))
| (other @ Ty::Scalar(Scalar::Int(_)), Ty::InferenceVar(tv, TyVariableKind::Integer))
| ( | (
Ty::InferenceVar(tv, TyVariableKind::Integer), TyKind::InferenceVar(tv, TyVariableKind::Integer),
other @ Ty::Scalar(Scalar::Uint(_)), other @ TyKind::Scalar(Scalar::Int(_)),
) )
| ( | (
other @ Ty::Scalar(Scalar::Uint(_)), other @ TyKind::Scalar(Scalar::Int(_)),
Ty::InferenceVar(tv, TyVariableKind::Integer), TyKind::InferenceVar(tv, TyVariableKind::Integer),
) )
| (Ty::InferenceVar(tv, TyVariableKind::Float), other @ Ty::Scalar(Scalar::Float(_))) | (
| (other @ Ty::Scalar(Scalar::Float(_)), Ty::InferenceVar(tv, TyVariableKind::Float)) => TyKind::InferenceVar(tv, TyVariableKind::Integer),
{ other @ TyKind::Scalar(Scalar::Uint(_)),
)
| (
other @ TyKind::Scalar(Scalar::Uint(_)),
TyKind::InferenceVar(tv, TyVariableKind::Integer),
)
| (
TyKind::InferenceVar(tv, TyVariableKind::Float),
other @ TyKind::Scalar(Scalar::Float(_)),
)
| (
other @ TyKind::Scalar(Scalar::Float(_)),
TyKind::InferenceVar(tv, TyVariableKind::Float),
) => {
// the type var is unknown since we tried to resolve it // the type var is unknown since we tried to resolve it
self.var_unification_table self.var_unification_table.union_value(
.union_value(tv.to_inner(), TypeVarValue::Known(other.clone())); tv.to_inner(),
TypeVarValue::Known(other.clone().intern(&Interner)),
);
true true
} }
@ -387,8 +404,8 @@ 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 { match &ty.0 {
Ty::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() {
Some(known_ty) => { Some(known_ty) => {
@ -410,8 +427,8 @@ impl InferenceTable {
/// be resolved as far as possible, i.e. contain no type variables with /// be resolved as far as possible, i.e. contain no type variables with
/// known type. /// known type.
fn resolve_ty_as_possible_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { fn resolve_ty_as_possible_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty {
ty.fold(&mut |ty| match ty { ty.fold(&mut |ty| match ty.interned(&Interner) {
Ty::InferenceVar(tv, kind) => { &TyKind::InferenceVar(tv, kind) => {
let inner = tv.to_inner(); let inner = tv.to_inner();
if tv_stack.contains(&inner) { if tv_stack.contains(&inner) {
cov_mark::hit!(type_var_cycles_resolve_as_possible); cov_mark::hit!(type_var_cycles_resolve_as_possible);
@ -435,10 +452,10 @@ impl InferenceTable {
} }
/// Resolves the type completely; type variables without known type are /// Resolves the type completely; type variables without known type are
/// replaced by Ty::Unknown. /// replaced by TyKind::Unknown.
fn resolve_ty_completely_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { fn resolve_ty_completely_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty {
ty.fold(&mut |ty| match ty { ty.fold(&mut |ty| match ty.interned(&Interner) {
Ty::InferenceVar(tv, kind) => { &TyKind::InferenceVar(tv, kind) => {
let inner = tv.to_inner(); let inner = tv.to_inner();
if tv_stack.contains(&inner) { if tv_stack.contains(&inner) {
cov_mark::hit!(type_var_cycles_resolve_completely); cov_mark::hit!(type_var_cycles_resolve_completely);

View file

@ -49,7 +49,7 @@ pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironmen
pub use chalk_ir::{AdtId, BoundVar, DebruijnIndex, Mutability, Scalar, TyVariableKind}; pub use chalk_ir::{AdtId, BoundVar, DebruijnIndex, Mutability, Scalar, TyVariableKind};
pub(crate) use crate::traits::chalk::Interner; pub use crate::traits::chalk::Interner;
#[derive(Clone, PartialEq, Eq, Debug, Hash)] #[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub enum Lifetime { pub enum Lifetime {
@ -131,7 +131,7 @@ pub enum AliasTy {
/// ///
/// This should be cheap to clone. /// This should be cheap to clone.
#[derive(Clone, PartialEq, Eq, Debug, Hash)] #[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub enum Ty { pub enum TyKind {
/// Structures, enumerations and unions. /// Structures, enumerations and unions.
Adt(AdtId<Interner>, Substs), Adt(AdtId<Interner>, Substs),
@ -244,6 +244,21 @@ pub enum Ty {
Unknown, Unknown,
} }
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct Ty(TyKind);
impl TyKind {
pub fn intern(self, _interner: &Interner) -> Ty {
Ty(self)
}
}
impl Ty {
pub fn interned(&self, _interner: &Interner) -> &TyKind {
&self.0
}
}
/// A list of substitutions for generic parameters. /// A list of substitutions for generic parameters.
#[derive(Clone, PartialEq, Eq, Debug, Hash)] #[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct Substs(Arc<[Ty]>); pub struct Substs(Arc<[Ty]>);
@ -292,7 +307,12 @@ impl Substs {
/// Return Substs that replace each parameter by itself (i.e. `Ty::Param`). /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`).
pub(crate) fn type_params_for_generics(generic_params: &Generics) -> Substs { pub(crate) fn type_params_for_generics(generic_params: &Generics) -> Substs {
Substs(generic_params.iter().map(|(id, _)| Ty::Placeholder(id)).collect()) Substs(
generic_params
.iter()
.map(|(id, _)| TyKind::Placeholder(id).intern(&Interner))
.collect(),
)
} }
/// Return Substs that replace each parameter by itself (i.e. `Ty::Param`). /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`).
@ -307,7 +327,7 @@ impl Substs {
generic_params generic_params
.iter() .iter()
.enumerate() .enumerate()
.map(|(idx, _)| Ty::BoundVar(BoundVar::new(debruijn, idx))) .map(|(idx, _)| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(&Interner))
.collect(), .collect(),
) )
} }
@ -355,11 +375,14 @@ impl SubstsBuilder {
} }
pub fn fill_with_bound_vars(self, debruijn: DebruijnIndex, starting_from: usize) -> Self { pub fn fill_with_bound_vars(self, debruijn: DebruijnIndex, starting_from: usize) -> Self {
self.fill((starting_from..).map(|idx| Ty::BoundVar(BoundVar::new(debruijn, idx)))) self.fill(
(starting_from..)
.map(|idx| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(&Interner)),
)
} }
pub fn fill_with_unknown(self) -> Self { pub fn fill_with_unknown(self) -> Self {
self.fill(iter::repeat(Ty::Unknown)) self.fill(iter::repeat(TyKind::Unknown.intern(&Interner)))
} }
pub fn fill(mut self, filler: impl Iterator<Item = Ty>) -> Self { pub fn fill(mut self, filler: impl Iterator<Item = Ty>) -> Self {
@ -601,45 +624,52 @@ impl TypeWalk for CallableSig {
impl Ty { impl Ty {
pub fn unit() -> Self { pub fn unit() -> Self {
Ty::Tuple(0, Substs::empty()) TyKind::Tuple(0, Substs::empty()).intern(&Interner)
} }
pub fn adt_ty(adt: hir_def::AdtId, substs: Substs) -> Ty { pub fn adt_ty(adt: hir_def::AdtId, substs: Substs) -> Ty {
Ty::Adt(AdtId(adt), substs) TyKind::Adt(AdtId(adt), substs).intern(&Interner)
} }
pub fn fn_ptr(sig: CallableSig) -> Self { pub fn fn_ptr(sig: CallableSig) -> Self {
Ty::Function(FnPointer { TyKind::Function(FnPointer {
num_args: sig.params().len(), num_args: sig.params().len(),
sig: FnSig { variadic: sig.is_varargs }, sig: FnSig { variadic: sig.is_varargs },
substs: Substs(sig.params_and_return), substs: Substs(sig.params_and_return),
}) })
.intern(&Interner)
} }
pub fn builtin(builtin: BuiltinType) -> Self { pub fn builtin(builtin: BuiltinType) -> Self {
match builtin { match builtin {
BuiltinType::Char => Ty::Scalar(Scalar::Char), BuiltinType::Char => TyKind::Scalar(Scalar::Char).intern(&Interner),
BuiltinType::Bool => Ty::Scalar(Scalar::Bool), BuiltinType::Bool => TyKind::Scalar(Scalar::Bool).intern(&Interner),
BuiltinType::Str => Ty::Str, BuiltinType::Str => TyKind::Str.intern(&Interner),
BuiltinType::Int(t) => Ty::Scalar(Scalar::Int(primitive::int_ty_from_builtin(t))), BuiltinType::Int(t) => {
BuiltinType::Uint(t) => Ty::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(t))), TyKind::Scalar(Scalar::Int(primitive::int_ty_from_builtin(t))).intern(&Interner)
BuiltinType::Float(t) => Ty::Scalar(Scalar::Float(primitive::float_ty_from_builtin(t))), }
BuiltinType::Uint(t) => {
TyKind::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(t))).intern(&Interner)
}
BuiltinType::Float(t) => {
TyKind::Scalar(Scalar::Float(primitive::float_ty_from_builtin(t))).intern(&Interner)
}
} }
} }
pub fn as_reference(&self) -> Option<(&Ty, Mutability)> { pub fn as_reference(&self) -> Option<(&Ty, Mutability)> {
match self { match self.interned(&Interner) {
Ty::Ref(mutability, parameters) => Some((parameters.as_single(), *mutability)), TyKind::Ref(mutability, parameters) => Some((parameters.as_single(), *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 { match self.interned(&Interner) {
Ty::Ref(mutability, parameters) => { TyKind::Ref(mutability, parameters) => {
Some((parameters.as_single(), Rawness::Ref, *mutability)) Some((parameters.as_single(), Rawness::Ref, *mutability))
} }
Ty::Raw(mutability, parameters) => { TyKind::Raw(mutability, parameters) => {
Some((parameters.as_single(), Rawness::RawPtr, *mutability)) Some((parameters.as_single(), Rawness::RawPtr, *mutability))
} }
_ => None, _ => None,
@ -649,7 +679,7 @@ 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 Ty::Ref(_mutability, parameters) = t { while let TyKind::Ref(_mutability, parameters) = t.interned(&Interner) {
t = parameters.as_single(); t = parameters.as_single();
} }
@ -657,65 +687,69 @@ impl Ty {
} }
pub fn as_adt(&self) -> Option<(hir_def::AdtId, &Substs)> { pub fn as_adt(&self) -> Option<(hir_def::AdtId, &Substs)> {
match self { match self.interned(&Interner) {
Ty::Adt(AdtId(adt), parameters) => Some((*adt, parameters)), TyKind::Adt(AdtId(adt), parameters) => Some((*adt, parameters)),
_ => None, _ => None,
} }
} }
pub fn as_tuple(&self) -> Option<&Substs> { pub fn as_tuple(&self) -> Option<&Substs> {
match self { match self.interned(&Interner) {
Ty::Tuple(_, substs) => Some(substs), TyKind::Tuple(_, substs) => Some(substs),
_ => None, _ => None,
} }
} }
pub fn as_generic_def(&self) -> Option<GenericDefId> { pub fn as_generic_def(&self) -> Option<GenericDefId> {
match *self { match *self.interned(&Interner) {
Ty::Adt(AdtId(adt), ..) => Some(adt.into()), TyKind::Adt(AdtId(adt), ..) => Some(adt.into()),
Ty::FnDef(callable, ..) => Some(callable.into()), TyKind::FnDef(callable, ..) => Some(callable.into()),
Ty::AssociatedType(type_alias, ..) => Some(type_alias.into()), TyKind::AssociatedType(type_alias, ..) => Some(type_alias.into()),
Ty::ForeignType(type_alias, ..) => Some(type_alias.into()), TyKind::ForeignType(type_alias, ..) => Some(type_alias.into()),
_ => None, _ => None,
} }
} }
pub fn is_never(&self) -> bool { pub fn is_never(&self) -> bool {
matches!(self, Ty::Never) matches!(self.interned(&Interner), TyKind::Never)
} }
pub fn is_unknown(&self) -> bool { pub fn is_unknown(&self) -> bool {
matches!(self, Ty::Unknown) matches!(self.interned(&Interner), TyKind::Unknown)
} }
pub fn equals_ctor(&self, other: &Ty) -> bool { pub fn equals_ctor(&self, other: &Ty) -> bool {
match (self, other) { match (self.interned(&Interner), other.interned(&Interner)) {
(Ty::Adt(adt, ..), Ty::Adt(adt2, ..)) => adt == adt2, (TyKind::Adt(adt, ..), TyKind::Adt(adt2, ..)) => adt == adt2,
(Ty::Slice(_), Ty::Slice(_)) | (Ty::Array(_), Ty::Array(_)) => true, (TyKind::Slice(_), TyKind::Slice(_)) | (TyKind::Array(_), TyKind::Array(_)) => true,
(Ty::FnDef(def_id, ..), Ty::FnDef(def_id2, ..)) => def_id == def_id2, (TyKind::FnDef(def_id, ..), TyKind::FnDef(def_id2, ..)) => def_id == def_id2,
(Ty::OpaqueType(ty_id, ..), Ty::OpaqueType(ty_id2, ..)) => ty_id == ty_id2, (TyKind::OpaqueType(ty_id, ..), TyKind::OpaqueType(ty_id2, ..)) => ty_id == ty_id2,
(Ty::AssociatedType(ty_id, ..), Ty::AssociatedType(ty_id2, ..)) (TyKind::AssociatedType(ty_id, ..), TyKind::AssociatedType(ty_id2, ..))
| (Ty::ForeignType(ty_id, ..), Ty::ForeignType(ty_id2, ..)) => ty_id == ty_id2, | (TyKind::ForeignType(ty_id, ..), TyKind::ForeignType(ty_id2, ..)) => ty_id == ty_id2,
(Ty::Closure(def, expr, _), Ty::Closure(def2, expr2, _)) => { (TyKind::Closure(def, expr, _), TyKind::Closure(def2, expr2, _)) => {
expr == expr2 && def == def2 expr == expr2 && def == def2
} }
(Ty::Ref(mutability, ..), Ty::Ref(mutability2, ..)) (TyKind::Ref(mutability, ..), TyKind::Ref(mutability2, ..))
| (Ty::Raw(mutability, ..), Ty::Raw(mutability2, ..)) => mutability == mutability2, | (TyKind::Raw(mutability, ..), TyKind::Raw(mutability2, ..)) => {
mutability == mutability2
}
( (
Ty::Function(FnPointer { num_args, sig, .. }), TyKind::Function(FnPointer { num_args, sig, .. }),
Ty::Function(FnPointer { num_args: num_args2, sig: sig2, .. }), TyKind::Function(FnPointer { num_args: num_args2, sig: sig2, .. }),
) => num_args == num_args2 && sig == sig2, ) => num_args == num_args2 && sig == sig2,
(Ty::Tuple(cardinality, _), Ty::Tuple(cardinality2, _)) => cardinality == cardinality2, (TyKind::Tuple(cardinality, _), TyKind::Tuple(cardinality2, _)) => {
(Ty::Str, Ty::Str) | (Ty::Never, Ty::Never) => true, cardinality == cardinality2
(Ty::Scalar(scalar), Ty::Scalar(scalar2)) => scalar == scalar2, }
(TyKind::Str, TyKind::Str) | (TyKind::Never, TyKind::Never) => true,
(TyKind::Scalar(scalar), TyKind::Scalar(scalar2)) => scalar == scalar2,
_ => false, _ => false,
} }
} }
/// If this is a `dyn Trait` type, this returns the `Trait` part. /// If this is a `dyn Trait` type, this returns the `Trait` part.
pub fn dyn_trait_ref(&self) -> Option<&TraitRef> { pub fn dyn_trait_ref(&self) -> Option<&TraitRef> {
match self { match self.interned(&Interner) {
Ty::Dyn(bounds) => bounds.get(0).and_then(|b| match b { TyKind::Dyn(bounds) => bounds.get(0).and_then(|b| match b {
GenericPredicate::Implemented(trait_ref) => Some(trait_ref), GenericPredicate::Implemented(trait_ref) => Some(trait_ref),
_ => None, _ => None,
}), }),
@ -729,28 +763,28 @@ impl Ty {
} }
fn builtin_deref(&self) -> Option<Ty> { fn builtin_deref(&self) -> Option<Ty> {
match self { match self.interned(&Interner) {
Ty::Ref(.., parameters) => Some(Ty::clone(parameters.as_single())), TyKind::Ref(.., parameters) => Some(Ty::clone(parameters.as_single())),
Ty::Raw(.., parameters) => Some(Ty::clone(parameters.as_single())), TyKind::Raw(.., parameters) => Some(Ty::clone(parameters.as_single())),
_ => None, _ => None,
} }
} }
pub fn as_fn_def(&self) -> Option<FunctionId> { pub fn as_fn_def(&self) -> Option<FunctionId> {
match self { match self.interned(&Interner) {
&Ty::FnDef(CallableDefId::FunctionId(func), ..) => Some(func), &TyKind::FnDef(CallableDefId::FunctionId(func), ..) => Some(func),
_ => None, _ => None,
} }
} }
pub fn callable_sig(&self, db: &dyn HirDatabase) -> Option<CallableSig> { pub fn callable_sig(&self, db: &dyn HirDatabase) -> Option<CallableSig> {
match self { match self.interned(&Interner) {
Ty::Function(fn_ptr) => Some(CallableSig::from_fn_ptr(fn_ptr)), TyKind::Function(fn_ptr) => Some(CallableSig::from_fn_ptr(fn_ptr)),
Ty::FnDef(def, parameters) => { TyKind::FnDef(def, parameters) => {
let sig = db.callable_item_signature(*def); let sig = db.callable_item_signature(*def);
Some(sig.subst(&parameters)) Some(sig.subst(&parameters))
} }
Ty::Closure(.., substs) => { TyKind::Closure(.., substs) => {
let sig_param = &substs[0]; let sig_param = &substs[0];
sig_param.callable_sig(db) sig_param.callable_sig(db)
} }
@ -763,18 +797,18 @@ 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 { match &mut self.0 {
Ty::Adt(_, substs) TyKind::Adt(_, substs)
| Ty::Slice(substs) | TyKind::Slice(substs)
| Ty::Array(substs) | TyKind::Array(substs)
| Ty::Raw(_, substs) | TyKind::Raw(_, substs)
| Ty::Ref(_, substs) | TyKind::Ref(_, substs)
| Ty::FnDef(_, substs) | TyKind::FnDef(_, substs)
| Ty::Function(FnPointer { substs, .. }) | TyKind::Function(FnPointer { substs, .. })
| Ty::Tuple(_, substs) | TyKind::Tuple(_, substs)
| Ty::OpaqueType(_, substs) | TyKind::OpaqueType(_, substs)
| Ty::AssociatedType(_, substs) | TyKind::AssociatedType(_, substs)
| Ty::Closure(.., substs) => { | TyKind::Closure(.., substs) => {
assert_eq!(substs.len(), new_substs.len()); assert_eq!(substs.len(), new_substs.len());
*substs = new_substs; *substs = new_substs;
} }
@ -786,42 +820,42 @@ impl Ty {
/// 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 { match self.interned(&Interner) {
Ty::Adt(_, substs) TyKind::Adt(_, substs)
| Ty::Slice(substs) | TyKind::Slice(substs)
| Ty::Array(substs) | TyKind::Array(substs)
| Ty::Raw(_, substs) | TyKind::Raw(_, substs)
| Ty::Ref(_, substs) | TyKind::Ref(_, substs)
| Ty::FnDef(_, substs) | TyKind::FnDef(_, substs)
| Ty::Function(FnPointer { substs, .. }) | TyKind::Function(FnPointer { substs, .. })
| Ty::Tuple(_, substs) | TyKind::Tuple(_, substs)
| Ty::OpaqueType(_, substs) | TyKind::OpaqueType(_, substs)
| Ty::AssociatedType(_, substs) | TyKind::AssociatedType(_, substs)
| Ty::Closure(.., substs) => Some(substs), | TyKind::Closure(.., substs) => Some(substs),
_ => None, _ => None,
} }
} }
pub fn substs_mut(&mut self) -> Option<&mut Substs> { pub fn substs_mut(&mut self) -> Option<&mut Substs> {
match self { match &mut self.0 {
Ty::Adt(_, substs) TyKind::Adt(_, substs)
| Ty::Slice(substs) | TyKind::Slice(substs)
| Ty::Array(substs) | TyKind::Array(substs)
| Ty::Raw(_, substs) | TyKind::Raw(_, substs)
| Ty::Ref(_, substs) | TyKind::Ref(_, substs)
| Ty::FnDef(_, substs) | TyKind::FnDef(_, substs)
| Ty::Function(FnPointer { substs, .. }) | TyKind::Function(FnPointer { substs, .. })
| Ty::Tuple(_, substs) | TyKind::Tuple(_, substs)
| Ty::OpaqueType(_, substs) | TyKind::OpaqueType(_, substs)
| Ty::AssociatedType(_, substs) | TyKind::AssociatedType(_, substs)
| Ty::Closure(.., substs) => Some(substs), | TyKind::Closure(.., substs) => Some(substs),
_ => None, _ => None,
} }
} }
pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<GenericPredicate>> { pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<GenericPredicate>> {
match self { match self.interned(&Interner) {
Ty::OpaqueType(opaque_ty_id, ..) => { TyKind::OpaqueType(opaque_ty_id, ..) => {
match opaque_ty_id { match opaque_ty_id {
OpaqueTyId::AsyncBlockTypeImplTrait(def, _expr) => { OpaqueTyId::AsyncBlockTypeImplTrait(def, _expr) => {
let krate = def.module(db.upcast()).krate(); let krate = def.module(db.upcast()).krate();
@ -844,7 +878,7 @@ impl Ty {
OpaqueTyId::ReturnTypeImplTrait(..) => None, OpaqueTyId::ReturnTypeImplTrait(..) => None,
} }
} }
Ty::Alias(AliasTy::Opaque(opaque_ty)) => { TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
let predicates = match opaque_ty.opaque_ty_id { let predicates = match opaque_ty.opaque_ty_id {
OpaqueTyId::ReturnTypeImplTrait(func, idx) => { OpaqueTyId::ReturnTypeImplTrait(func, idx) => {
db.return_type_impl_traits(func).map(|it| { db.return_type_impl_traits(func).map(|it| {
@ -860,7 +894,7 @@ impl Ty {
predicates.map(|it| it.value) predicates.map(|it| it.value)
} }
Ty::Placeholder(id) => { TyKind::Placeholder(id) => {
let generic_params = db.generic_params(id.parent); let generic_params = db.generic_params(id.parent);
let param_data = &generic_params.types[id.local_id]; let param_data = &generic_params.types[id.local_id];
match param_data.provenance { match param_data.provenance {
@ -881,14 +915,14 @@ impl Ty {
} }
pub fn associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<TraitId> { pub fn associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<TraitId> {
match self { match self.interned(&Interner) {
Ty::AssociatedType(type_alias_id, ..) => { TyKind::AssociatedType(type_alias_id, ..) => {
match type_alias_id.lookup(db.upcast()).container { match type_alias_id.lookup(db.upcast()).container {
AssocContainerId::TraitId(trait_id) => Some(trait_id), AssocContainerId::TraitId(trait_id) => Some(trait_id),
_ => None, _ => None,
} }
} }
Ty::Alias(AliasTy::Projection(projection_ty)) => { TyKind::Alias(AliasTy::Projection(projection_ty)) => {
match projection_ty.associated_ty.lookup(db.upcast()).container { match projection_ty.associated_ty.lookup(db.upcast()).container {
AssocContainerId::TraitId(trait_id) => Some(trait_id), AssocContainerId::TraitId(trait_id) => Some(trait_id),
_ => None, _ => None,
@ -908,13 +942,13 @@ pub trait TypeWalk {
} }
/// Walk the type, counting entered binders. /// Walk the type, counting entered binders.
/// ///
/// `Ty::Bound` variables use DeBruijn indexing, which means that 0 refers /// `TyKind::Bound` variables use DeBruijn indexing, which means that 0 refers
/// to the innermost binder, 1 to the next, etc.. So when we want to /// to the innermost binder, 1 to the next, etc.. So when we want to
/// substitute a certain bound variable, we can't just walk the whole type /// substitute a certain bound variable, we can't just walk the whole type
/// and blindly replace each instance of a certain index; when we 'enter' /// and blindly replace each instance of a certain index; when we 'enter'
/// things that introduce new bound variables, we have to keep track of /// things that introduce new bound variables, we have to keep track of
/// that. Currently, the only thing that introduces bound variables on our /// that. Currently, the only thing that introduces bound variables on our
/// side are `Ty::Dyn` and `Ty::Opaque`, which each introduce a bound /// side are `TyKind::Dyn` and `TyKind::Opaque`, which each introduce a bound
/// variable for the self type. /// variable for the self type.
fn walk_mut_binders( fn walk_mut_binders(
&mut self, &mut self,
@ -932,7 +966,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::Unknown); let ty = mem::replace(ty_mut, Ty(TyKind::Unknown));
*ty_mut = f(ty, binders); *ty_mut = f(ty, binders);
}, },
binders, binders,
@ -945,13 +979,13 @@ 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::Unknown); let ty = mem::replace(ty_mut, Ty(TyKind::Unknown));
*ty_mut = f(ty); *ty_mut = f(ty);
}); });
self self
} }
/// Substitutes `Ty::Bound` vars with the given substitution. /// Substitutes `TyKind::Bound` vars with the given substitution.
fn subst_bound_vars(self, substs: &Substs) -> Self fn subst_bound_vars(self, substs: &Substs) -> Self
where where
Self: Sized, Self: Sized,
@ -959,14 +993,14 @@ pub trait TypeWalk {
self.subst_bound_vars_at_depth(substs, DebruijnIndex::INNERMOST) self.subst_bound_vars_at_depth(substs, DebruijnIndex::INNERMOST)
} }
/// Substitutes `Ty::Bound` vars with the given substitution. /// Substitutes `TyKind::Bound` vars with the given substitution.
fn subst_bound_vars_at_depth(mut self, substs: &Substs, depth: DebruijnIndex) -> Self fn subst_bound_vars_at_depth(mut self, substs: &Substs, depth: DebruijnIndex) -> Self
where where
Self: Sized, Self: Sized,
{ {
self.walk_mut_binders( self.walk_mut_binders(
&mut |ty, binders| { &mut |ty, binders| {
if let &mut Ty::BoundVar(bound) = ty { if let &mut TyKind::BoundVar(bound) = &mut ty.0 {
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);
} }
@ -977,17 +1011,17 @@ pub trait TypeWalk {
self self
} }
/// Shifts up debruijn indices of `Ty::Bound` vars by `n`. /// Shifts up debruijn indices of `TyKind::Bound` vars by `n`.
fn shift_bound_vars(self, n: DebruijnIndex) -> Self fn shift_bound_vars(self, n: DebruijnIndex) -> Self
where where
Self: Sized, Self: Sized,
{ {
self.fold_binders( self.fold_binders(
&mut |ty, binders| match ty { &mut |ty, binders| match &ty.0 {
Ty::BoundVar(bound) if bound.debruijn >= binders => { TyKind::BoundVar(bound) if bound.debruijn >= binders => {
Ty::BoundVar(bound.shifted_in_from(n)) TyKind::BoundVar(bound.shifted_in_from(n)).intern(&Interner)
} }
ty => ty, _ => ty,
}, },
DebruijnIndex::INNERMOST, DebruijnIndex::INNERMOST,
) )
@ -996,18 +1030,18 @@ pub trait TypeWalk {
impl TypeWalk for Ty { impl TypeWalk for Ty {
fn walk(&self, f: &mut impl FnMut(&Ty)) { fn walk(&self, f: &mut impl FnMut(&Ty)) {
match self { match self.interned(&Interner) {
Ty::Alias(AliasTy::Projection(p_ty)) => { TyKind::Alias(AliasTy::Projection(p_ty)) => {
for t in p_ty.parameters.iter() { for t in p_ty.parameters.iter() {
t.walk(f); t.walk(f);
} }
} }
Ty::Alias(AliasTy::Opaque(o_ty)) => { TyKind::Alias(AliasTy::Opaque(o_ty)) => {
for t in o_ty.parameters.iter() { for t in o_ty.parameters.iter() {
t.walk(f); t.walk(f);
} }
} }
Ty::Dyn(predicates) => { TyKind::Dyn(predicates) => {
for p in predicates.iter() { for p in predicates.iter() {
p.walk(f); p.walk(f);
} }
@ -1028,16 +1062,16 @@ impl TypeWalk for Ty {
f: &mut impl FnMut(&mut Ty, DebruijnIndex), f: &mut impl FnMut(&mut Ty, DebruijnIndex),
binders: DebruijnIndex, binders: DebruijnIndex,
) { ) {
match self { match &mut self.0 {
Ty::Alias(AliasTy::Projection(p_ty)) => { TyKind::Alias(AliasTy::Projection(p_ty)) => {
p_ty.parameters.walk_mut_binders(f, binders); p_ty.parameters.walk_mut_binders(f, binders);
} }
Ty::Dyn(predicates) => { TyKind::Dyn(predicates) => {
for p in make_mut_slice(predicates) { for p in make_mut_slice(predicates) {
p.walk_mut_binders(f, binders.shifted_in()); p.walk_mut_binders(f, binders.shifted_in());
} }
} }
Ty::Alias(AliasTy::Opaque(o_ty)) => { TyKind::Alias(AliasTy::Opaque(o_ty)) => {
o_ty.parameters.walk_mut_binders(f, binders); o_ty.parameters.walk_mut_binders(f, binders);
} }
_ => { _ => {

View file

@ -34,7 +34,7 @@ use crate::{
}, },
AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, FnPointer, FnSig, GenericPredicate, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, FnPointer, FnSig, GenericPredicate,
OpaqueTy, OpaqueTyId, PolyFnSig, ProjectionPredicate, ProjectionTy, ReturnTypeImplTrait, OpaqueTy, OpaqueTyId, PolyFnSig, ProjectionPredicate, ProjectionTy, ReturnTypeImplTrait,
ReturnTypeImplTraits, Substs, TraitEnvironment, TraitRef, Ty, TypeWalk, ReturnTypeImplTraits, Substs, TraitEnvironment, TraitRef, Ty, TyKind, TypeWalk,
}; };
#[derive(Debug)] #[derive(Debug)]
@ -146,10 +146,10 @@ impl Ty {
pub fn from_hir_ext(ctx: &TyLoweringContext<'_>, type_ref: &TypeRef) -> (Self, Option<TypeNs>) { pub fn from_hir_ext(ctx: &TyLoweringContext<'_>, type_ref: &TypeRef) -> (Self, Option<TypeNs>) {
let mut res = None; let mut res = None;
let ty = match type_ref { let ty = match type_ref {
TypeRef::Never => Ty::Never, TypeRef::Never => TyKind::Never.intern(&Interner),
TypeRef::Tuple(inner) => { TypeRef::Tuple(inner) => {
let inner_tys: Arc<[Ty]> = inner.iter().map(|tr| Ty::from_hir(ctx, tr)).collect(); let inner_tys: Arc<[Ty]> = inner.iter().map(|tr| Ty::from_hir(ctx, tr)).collect();
Ty::Tuple(inner_tys.len(), Substs(inner_tys)) TyKind::Tuple(inner_tys.len(), Substs(inner_tys)).intern(&Interner)
} }
TypeRef::Path(path) => { TypeRef::Path(path) => {
let (ty, res_) = Ty::from_hir_path(ctx, path); let (ty, res_) = Ty::from_hir_path(ctx, path);
@ -158,38 +158,42 @@ impl Ty {
} }
TypeRef::RawPtr(inner, mutability) => { TypeRef::RawPtr(inner, mutability) => {
let inner_ty = Ty::from_hir(ctx, inner); let inner_ty = Ty::from_hir(ctx, inner);
Ty::Raw(lower_to_chalk_mutability(*mutability), Substs::single(inner_ty)) TyKind::Raw(lower_to_chalk_mutability(*mutability), Substs::single(inner_ty))
.intern(&Interner)
} }
TypeRef::Array(inner) => { TypeRef::Array(inner) => {
let inner_ty = Ty::from_hir(ctx, inner); let inner_ty = Ty::from_hir(ctx, inner);
Ty::Array(Substs::single(inner_ty)) TyKind::Array(Substs::single(inner_ty)).intern(&Interner)
} }
TypeRef::Slice(inner) => { TypeRef::Slice(inner) => {
let inner_ty = Ty::from_hir(ctx, inner); let inner_ty = Ty::from_hir(ctx, inner);
Ty::Slice(Substs::single(inner_ty)) TyKind::Slice(Substs::single(inner_ty)).intern(&Interner)
} }
TypeRef::Reference(inner, _, mutability) => { TypeRef::Reference(inner, _, mutability) => {
let inner_ty = Ty::from_hir(ctx, inner); let inner_ty = Ty::from_hir(ctx, inner);
Ty::Ref(lower_to_chalk_mutability(*mutability), Substs::single(inner_ty)) TyKind::Ref(lower_to_chalk_mutability(*mutability), Substs::single(inner_ty))
.intern(&Interner)
} }
TypeRef::Placeholder => Ty::Unknown, TypeRef::Placeholder => TyKind::Unknown.intern(&Interner),
TypeRef::Fn(params, is_varargs) => { TypeRef::Fn(params, is_varargs) => {
let substs = Substs(params.iter().map(|tr| Ty::from_hir(ctx, tr)).collect()); let substs = Substs(params.iter().map(|tr| Ty::from_hir(ctx, tr)).collect());
Ty::Function(FnPointer { TyKind::Function(FnPointer {
num_args: substs.len() - 1, num_args: substs.len() - 1,
sig: FnSig { variadic: *is_varargs }, sig: FnSig { variadic: *is_varargs },
substs, substs,
}) })
.intern(&Interner)
} }
TypeRef::DynTrait(bounds) => { TypeRef::DynTrait(bounds) => {
let self_ty = Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)); let self_ty =
TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner);
let predicates = ctx.with_shifted_in(DebruijnIndex::ONE, |ctx| { let predicates = ctx.with_shifted_in(DebruijnIndex::ONE, |ctx| {
bounds bounds
.iter() .iter()
.flat_map(|b| GenericPredicate::from_type_bound(ctx, b, self_ty.clone())) .flat_map(|b| GenericPredicate::from_type_bound(ctx, b, self_ty.clone()))
.collect() .collect()
}); });
Ty::Dyn(predicates) TyKind::Dyn(predicates).intern(&Interner)
} }
TypeRef::ImplTrait(bounds) => { TypeRef::ImplTrait(bounds) => {
match ctx.impl_trait_mode { match ctx.impl_trait_mode {
@ -226,10 +230,11 @@ impl Ty {
let impl_trait_id = OpaqueTyId::ReturnTypeImplTrait(func, idx); let impl_trait_id = OpaqueTyId::ReturnTypeImplTrait(func, idx);
let generics = generics(ctx.db.upcast(), func.into()); let generics = generics(ctx.db.upcast(), func.into());
let parameters = Substs::bound_vars(&generics, ctx.in_binders); let parameters = Substs::bound_vars(&generics, ctx.in_binders);
Ty::Alias(AliasTy::Opaque(OpaqueTy { TyKind::Alias(AliasTy::Opaque(OpaqueTy {
opaque_ty_id: impl_trait_id, opaque_ty_id: impl_trait_id,
parameters, parameters,
})) }))
.intern(&Interner)
} }
ImplTraitLoweringMode::Param => { ImplTraitLoweringMode::Param => {
let idx = ctx.impl_trait_counter.get(); let idx = ctx.impl_trait_counter.get();
@ -243,10 +248,10 @@ impl Ty {
data.provenance == TypeParamProvenance::ArgumentImplTrait data.provenance == TypeParamProvenance::ArgumentImplTrait
}) })
.nth(idx as usize) .nth(idx as usize)
.map_or(Ty::Unknown, |(id, _)| Ty::Placeholder(id)); .map_or(TyKind::Unknown, |(id, _)| TyKind::Placeholder(id));
param param.intern(&Interner)
} else { } else {
Ty::Unknown TyKind::Unknown.intern(&Interner)
} }
} }
ImplTraitLoweringMode::Variable => { ImplTraitLoweringMode::Variable => {
@ -260,18 +265,19 @@ impl Ty {
} else { } else {
(0, 0, 0, 0) (0, 0, 0, 0)
}; };
Ty::BoundVar(BoundVar::new( TyKind::BoundVar(BoundVar::new(
ctx.in_binders, ctx.in_binders,
idx as usize + parent_params + self_params + list_params, idx as usize + parent_params + self_params + list_params,
)) ))
.intern(&Interner)
} }
ImplTraitLoweringMode::Disallowed => { ImplTraitLoweringMode::Disallowed => {
// FIXME: report error // FIXME: report error
Ty::Unknown TyKind::Unknown.intern(&Interner)
} }
} }
} }
TypeRef::Error => Ty::Unknown, TypeRef::Error => TyKind::Unknown.intern(&Interner),
}; };
(ty, res) (ty, res)
} }
@ -315,7 +321,7 @@ impl Ty {
(Ty::select_associated_type(ctx, res, segment), None) (Ty::select_associated_type(ctx, res, segment), None)
} else if remaining_segments.len() > 1 { } else if remaining_segments.len() > 1 {
// FIXME report error (ambiguous associated type) // FIXME report error (ambiguous associated type)
(Ty::Unknown, None) (TyKind::Unknown.intern(&Interner), None)
} else { } else {
(ty, res) (ty, res)
} }
@ -332,7 +338,10 @@ impl Ty {
TypeNs::TraitId(trait_) => { TypeNs::TraitId(trait_) => {
// if this is a bare dyn Trait, we'll directly put the required ^0 for the self type in there // if this is a bare dyn Trait, we'll directly put the required ^0 for the self type in there
let self_ty = if remaining_segments.len() == 0 { let self_ty = if remaining_segments.len() == 0 {
Some(Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))) Some(
TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
.intern(&Interner),
)
} else { } else {
None None
}; };
@ -348,21 +357,23 @@ impl Ty {
match found { match found {
Some((super_trait_ref, associated_ty)) => { Some((super_trait_ref, associated_ty)) => {
// FIXME handle type parameters on the segment // FIXME handle type parameters on the segment
Ty::Alias(AliasTy::Projection(ProjectionTy { TyKind::Alias(AliasTy::Projection(ProjectionTy {
associated_ty, associated_ty,
parameters: super_trait_ref.substs, parameters: super_trait_ref.substs,
})) }))
.intern(&Interner)
} }
None => { None => {
// FIXME: report error (associated type not found) // FIXME: report error (associated type not found)
Ty::Unknown TyKind::Unknown.intern(&Interner)
} }
} }
} else if remaining_segments.len() > 1 { } else if remaining_segments.len() > 1 {
// FIXME report error (ambiguous associated type) // FIXME report error (ambiguous associated type)
Ty::Unknown TyKind::Unknown.intern(&Interner)
} else { } else {
Ty::Dyn(Arc::new([GenericPredicate::Implemented(trait_ref)])) TyKind::Dyn(Arc::new([GenericPredicate::Implemented(trait_ref)]))
.intern(&Interner)
}; };
return (ty, None); return (ty, None);
} }
@ -372,12 +383,13 @@ impl Ty {
ctx.resolver.generic_def().expect("generics in scope"), ctx.resolver.generic_def().expect("generics in scope"),
); );
match ctx.type_param_mode { match ctx.type_param_mode {
TypeParamLoweringMode::Placeholder => Ty::Placeholder(param_id), TypeParamLoweringMode::Placeholder => TyKind::Placeholder(param_id),
TypeParamLoweringMode::Variable => { TypeParamLoweringMode::Variable => {
let idx = generics.param_idx(param_id).expect("matching generics"); let idx = generics.param_idx(param_id).expect("matching generics");
Ty::BoundVar(BoundVar::new(ctx.in_binders, idx)) TyKind::BoundVar(BoundVar::new(ctx.in_binders, idx))
} }
} }
.intern(&Interner)
} }
TypeNs::SelfType(impl_id) => { TypeNs::SelfType(impl_id) => {
let generics = generics(ctx.db.upcast(), impl_id.into()); let generics = generics(ctx.db.upcast(), impl_id.into());
@ -414,7 +426,7 @@ impl Ty {
Ty::from_hir_path_inner(ctx, resolved_segment, it.into(), infer_args) Ty::from_hir_path_inner(ctx, resolved_segment, it.into(), infer_args)
} }
// FIXME: report error // FIXME: report error
TypeNs::EnumVariantId(_) => return (Ty::Unknown, None), TypeNs::EnumVariantId(_) => return (TyKind::Unknown.intern(&Interner), None),
}; };
Ty::from_type_relative_path(ctx, ty, Some(resolution), remaining_segments) Ty::from_type_relative_path(ctx, ty, Some(resolution), remaining_segments)
} }
@ -428,7 +440,7 @@ impl Ty {
let (resolution, remaining_index) = let (resolution, remaining_index) =
match ctx.resolver.resolve_path_in_type_ns(ctx.db.upcast(), path.mod_path()) { match ctx.resolver.resolve_path_in_type_ns(ctx.db.upcast(), path.mod_path()) {
Some(it) => it, Some(it) => it,
None => return (Ty::Unknown, None), None => return (TyKind::Unknown.intern(&Interner), None),
}; };
let (resolved_segment, remaining_segments) = match remaining_index { let (resolved_segment, remaining_segments) = match remaining_index {
None => ( None => (
@ -473,18 +485,21 @@ impl Ty {
// associated_type_shorthand_candidates does not do that // associated_type_shorthand_candidates does not do that
let substs = substs.shift_bound_vars(ctx.in_binders); let substs = substs.shift_bound_vars(ctx.in_binders);
// FIXME handle type parameters on the segment // FIXME handle type parameters on the segment
return Some(Ty::Alias(AliasTy::Projection(ProjectionTy { return Some(
associated_ty, TyKind::Alias(AliasTy::Projection(ProjectionTy {
parameters: substs, associated_ty,
}))); parameters: substs,
}))
.intern(&Interner),
);
} }
None None
}); });
ty.unwrap_or(Ty::Unknown) ty.unwrap_or(TyKind::Unknown.intern(&Interner))
} else { } else {
Ty::Unknown TyKind::Unknown.intern(&Interner)
} }
} }
@ -553,13 +568,13 @@ fn substs_from_path_segment(
def_generics.map_or((0, 0, 0, 0), |g| g.provenance_split()); def_generics.map_or((0, 0, 0, 0), |g| g.provenance_split());
let total_len = parent_params + self_params + type_params + impl_trait_params; let total_len = parent_params + self_params + type_params + impl_trait_params;
substs.extend(iter::repeat(Ty::Unknown).take(parent_params)); substs.extend(iter::repeat(TyKind::Unknown.intern(&Interner)).take(parent_params));
let mut had_explicit_type_args = false; let mut had_explicit_type_args = false;
if let Some(generic_args) = &segment.args_and_bindings { if let Some(generic_args) = &segment.args_and_bindings {
if !generic_args.has_self_type { if !generic_args.has_self_type {
substs.extend(iter::repeat(Ty::Unknown).take(self_params)); substs.extend(iter::repeat(TyKind::Unknown.intern(&Interner)).take(self_params));
} }
let expected_num = let expected_num =
if generic_args.has_self_type { self_params + type_params } else { type_params }; if generic_args.has_self_type { self_params + type_params } else { type_params };
@ -602,7 +617,7 @@ fn substs_from_path_segment(
// add placeholders for args that were not provided // add placeholders for args that were not provided
// FIXME: emit diagnostics in contexts where this is not allowed // FIXME: emit diagnostics in contexts where this is not allowed
for _ in substs.len()..total_len { for _ in substs.len()..total_len {
substs.push(Ty::Unknown); substs.push(TyKind::Unknown.intern(&Interner));
} }
assert_eq!(substs.len(), total_len); assert_eq!(substs.len(), total_len);
@ -674,12 +689,13 @@ impl GenericPredicate {
let param_id = let param_id =
hir_def::TypeParamId { parent: generic_def, local_id: *param_id }; hir_def::TypeParamId { parent: generic_def, local_id: *param_id };
match ctx.type_param_mode { match ctx.type_param_mode {
TypeParamLoweringMode::Placeholder => Ty::Placeholder(param_id), TypeParamLoweringMode::Placeholder => TyKind::Placeholder(param_id),
TypeParamLoweringMode::Variable => { TypeParamLoweringMode::Variable => {
let idx = generics.param_idx(param_id).expect("matching generics"); let idx = generics.param_idx(param_id).expect("matching generics");
Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, idx)) TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, idx))
} }
} }
.intern(&Interner)
} }
}; };
GenericPredicate::from_type_bound(ctx, bound, self_ty) GenericPredicate::from_type_bound(ctx, bound, self_ty)
@ -751,7 +767,7 @@ fn assoc_type_bindings_from_type_bound<'a>(
preds.extend(GenericPredicate::from_type_bound( preds.extend(GenericPredicate::from_type_bound(
ctx, ctx,
bound, bound,
Ty::Alias(AliasTy::Projection(projection_ty.clone())), TyKind::Alias(AliasTy::Projection(projection_ty.clone())).intern(&Interner),
)); ));
} }
preds preds
@ -761,7 +777,8 @@ fn assoc_type_bindings_from_type_bound<'a>(
impl ReturnTypeImplTrait { impl ReturnTypeImplTrait {
fn from_hir(ctx: &TyLoweringContext, bounds: &[TypeBound]) -> Self { fn from_hir(ctx: &TyLoweringContext, bounds: &[TypeBound]) -> Self {
cov_mark::hit!(lower_rpit); cov_mark::hit!(lower_rpit);
let self_ty = Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)); let self_ty =
TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner);
let predicates = ctx.with_shifted_in(DebruijnIndex::ONE, |ctx| { let predicates = ctx.with_shifted_in(DebruijnIndex::ONE, |ctx| {
bounds bounds
.iter() .iter()
@ -994,17 +1011,20 @@ pub(crate) fn generic_defaults_query(
.iter() .iter()
.enumerate() .enumerate()
.map(|(idx, (_, p))| { .map(|(idx, (_, p))| {
let mut ty = p.default.as_ref().map_or(Ty::Unknown, |t| Ty::from_hir(&ctx, t)); let mut ty = p
.default
.as_ref()
.map_or(TyKind::Unknown.intern(&Interner), |t| Ty::from_hir(&ctx, t));
// 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 ty { &mut |ty, binders| match &mut ty.0 {
Ty::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
// after it. This is forbidden (FIXME: report // after it. This is forbidden (FIXME: report
// diagnostic) // diagnostic)
*ty = Ty::Unknown; *ty = TyKind::Unknown.intern(&Interner);
} }
} }
_ => {} _ => {}
@ -1040,7 +1060,7 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig {
fn type_for_fn(db: &dyn HirDatabase, def: FunctionId) -> Binders<Ty> { fn type_for_fn(db: &dyn HirDatabase, def: FunctionId) -> Binders<Ty> {
let generics = generics(db.upcast(), def.into()); let generics = generics(db.upcast(), def.into());
let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST); let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST);
Binders::new(substs.len(), Ty::FnDef(def.into(), substs)) Binders::new(substs.len(), TyKind::FnDef(def.into(), substs).intern(&Interner))
} }
/// Build the declared type of a const. /// Build the declared type of a const.
@ -1083,7 +1103,7 @@ fn type_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> Binders<T
} }
let generics = generics(db.upcast(), def.into()); let generics = generics(db.upcast(), def.into());
let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST); let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST);
Binders::new(substs.len(), Ty::FnDef(def.into(), substs)) Binders::new(substs.len(), TyKind::FnDef(def.into(), substs).intern(&Interner))
} }
fn fn_sig_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) -> PolyFnSig { fn fn_sig_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) -> PolyFnSig {
@ -1108,7 +1128,7 @@ fn type_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) -
} }
let generics = generics(db.upcast(), def.parent.into()); let generics = generics(db.upcast(), def.parent.into());
let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST); let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST);
Binders::new(substs.len(), Ty::FnDef(def.into(), substs)) Binders::new(substs.len(), TyKind::FnDef(def.into(), substs).intern(&Interner))
} }
fn type_for_adt(db: &dyn HirDatabase, adt: AdtId) -> Binders<Ty> { fn type_for_adt(db: &dyn HirDatabase, adt: AdtId) -> Binders<Ty> {
@ -1123,7 +1143,7 @@ fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> {
let ctx = let ctx =
TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
if db.type_alias_data(t).is_extern { if db.type_alias_data(t).is_extern {
Binders::new(0, Ty::ForeignType(t)) Binders::new(0, TyKind::ForeignType(t).intern(&Interner))
} else { } else {
let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST); let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST);
let type_ref = &db.type_alias_data(t).type_ref; let type_ref = &db.type_alias_data(t).type_ref;
@ -1199,7 +1219,7 @@ pub(crate) fn ty_recover(db: &dyn HirDatabase, _cycle: &[String], def: &TyDefId)
TyDefId::AdtId(it) => generics(db.upcast(), it.into()).len(), TyDefId::AdtId(it) => generics(db.upcast(), it.into()).len(),
TyDefId::TypeAliasId(it) => generics(db.upcast(), it.into()).len(), TyDefId::TypeAliasId(it) => generics(db.upcast(), it.into()).len(),
}; };
Binders::new(num_binders, Ty::Unknown) Binders::new(num_binders, TyKind::Unknown.intern(&Interner))
} }
pub(crate) fn value_ty_query(db: &dyn HirDatabase, def: ValueTyDefId) -> Binders<Ty> { pub(crate) fn value_ty_query(db: &dyn HirDatabase, def: ValueTyDefId) -> Binders<Ty> {
@ -1237,7 +1257,7 @@ pub(crate) fn impl_self_ty_recover(
impl_id: &ImplId, impl_id: &ImplId,
) -> Binders<Ty> { ) -> Binders<Ty> {
let generics = generics(db.upcast(), (*impl_id).into()); let generics = generics(db.upcast(), (*impl_id).into());
Binders::new(generics.len(), Ty::Unknown) Binders::new(generics.len(), TyKind::Unknown.intern(&Interner))
} }
pub(crate) fn impl_trait_query(db: &dyn HirDatabase, impl_id: ImplId) -> Option<Binders<TraitRef>> { pub(crate) fn impl_trait_query(db: &dyn HirDatabase, impl_id: ImplId) -> Option<Binders<TraitRef>> {

View file

@ -19,8 +19,8 @@ use crate::{
db::HirDatabase, db::HirDatabase,
primitive::{self, FloatTy, IntTy, UintTy}, primitive::{self, FloatTy, IntTy, UintTy},
utils::all_super_traits, utils::all_super_traits,
AdtId, Canonical, DebruijnIndex, FnPointer, FnSig, InEnvironment, Scalar, Substs, AdtId, Canonical, DebruijnIndex, FnPointer, FnSig, InEnvironment, Interner, Scalar, Substs,
TraitEnvironment, TraitRef, Ty, TypeWalk, TraitEnvironment, TraitRef, Ty, TyKind, TypeWalk,
}; };
/// This is used as a key for indexing impls. /// This is used as a key for indexing impls.
@ -44,18 +44,20 @@ impl TyFingerprint {
/// have impls: if we have some `struct S`, we can have an `impl S`, but not /// 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. /// `impl &S`. Hence, this will return `None` for reference types and such.
pub(crate) fn for_impl(ty: &Ty) -> Option<TyFingerprint> { pub(crate) fn for_impl(ty: &Ty) -> Option<TyFingerprint> {
let fp = match ty { let fp = match *ty.interned(&Interner) {
&Ty::Str => TyFingerprint::Str, TyKind::Str => TyFingerprint::Str,
&Ty::Never => TyFingerprint::Never, TyKind::Never => TyFingerprint::Never,
&Ty::Slice(..) => TyFingerprint::Slice, TyKind::Slice(..) => TyFingerprint::Slice,
&Ty::Array(..) => TyFingerprint::Array, TyKind::Array(..) => TyFingerprint::Array,
&Ty::Scalar(scalar) => TyFingerprint::Scalar(scalar), TyKind::Scalar(scalar) => TyFingerprint::Scalar(scalar),
&Ty::Adt(AdtId(adt), _) => TyFingerprint::Adt(adt), TyKind::Adt(AdtId(adt), _) => TyFingerprint::Adt(adt),
&Ty::Tuple(cardinality, _) => TyFingerprint::Tuple(cardinality), TyKind::Tuple(cardinality, _) => TyFingerprint::Tuple(cardinality),
&Ty::Raw(mutability, ..) => TyFingerprint::RawPtr(mutability), TyKind::Raw(mutability, ..) => TyFingerprint::RawPtr(mutability),
&Ty::ForeignType(alias_id, ..) => TyFingerprint::ForeignType(alias_id), TyKind::ForeignType(alias_id, ..) => TyFingerprint::ForeignType(alias_id),
&Ty::Function(FnPointer { num_args, sig, .. }) => TyFingerprint::FnPtr(num_args, sig), TyKind::Function(FnPointer { num_args, sig, .. }) => {
Ty::Dyn(_) => ty.dyn_trait().map(|trait_| TyFingerprint::Dyn(trait_))?, TyFingerprint::FnPtr(num_args, sig)
}
TyKind::Dyn(_) => ty.dyn_trait().map(|trait_| TyFingerprint::Dyn(trait_))?,
_ => return None, _ => return None,
}; };
Some(fp) Some(fp)
@ -230,31 +232,31 @@ impl Ty {
let mod_to_crate_ids = |module: ModuleId| Some(std::iter::once(module.krate()).collect()); let mod_to_crate_ids = |module: ModuleId| Some(std::iter::once(module.krate()).collect());
let lang_item_targets = match self { let lang_item_targets = match self.interned(&Interner) {
Ty::Adt(AdtId(def_id), _) => { TyKind::Adt(AdtId(def_id), _) => {
return mod_to_crate_ids(def_id.module(db.upcast())); return mod_to_crate_ids(def_id.module(db.upcast()));
} }
Ty::ForeignType(type_alias_id) => { TyKind::ForeignType(type_alias_id) => {
return mod_to_crate_ids(type_alias_id.lookup(db.upcast()).module(db.upcast())); return mod_to_crate_ids(type_alias_id.lookup(db.upcast()).module(db.upcast()));
} }
Ty::Scalar(Scalar::Bool) => lang_item_crate!("bool"), TyKind::Scalar(Scalar::Bool) => lang_item_crate!("bool"),
Ty::Scalar(Scalar::Char) => lang_item_crate!("char"), TyKind::Scalar(Scalar::Char) => lang_item_crate!("char"),
Ty::Scalar(Scalar::Float(f)) => match f { TyKind::Scalar(Scalar::Float(f)) => match f {
// There are two lang items: one in libcore (fXX) and one in libstd (fXX_runtime) // There are two lang items: one in libcore (fXX) and one in libstd (fXX_runtime)
FloatTy::F32 => lang_item_crate!("f32", "f32_runtime"), FloatTy::F32 => lang_item_crate!("f32", "f32_runtime"),
FloatTy::F64 => lang_item_crate!("f64", "f64_runtime"), FloatTy::F64 => lang_item_crate!("f64", "f64_runtime"),
}, },
&Ty::Scalar(Scalar::Int(t)) => { &TyKind::Scalar(Scalar::Int(t)) => {
lang_item_crate!(primitive::int_ty_to_string(t)) lang_item_crate!(primitive::int_ty_to_string(t))
} }
&Ty::Scalar(Scalar::Uint(t)) => { &TyKind::Scalar(Scalar::Uint(t)) => {
lang_item_crate!(primitive::uint_ty_to_string(t)) lang_item_crate!(primitive::uint_ty_to_string(t))
} }
Ty::Str => lang_item_crate!("str_alloc", "str"), TyKind::Str => lang_item_crate!("str_alloc", "str"),
Ty::Slice(_) => lang_item_crate!("slice_alloc", "slice"), TyKind::Slice(_) => lang_item_crate!("slice_alloc", "slice"),
Ty::Raw(Mutability::Not, _) => lang_item_crate!("const_ptr"), TyKind::Raw(Mutability::Not, _) => lang_item_crate!("const_ptr"),
Ty::Raw(Mutability::Mut, _) => lang_item_crate!("mut_ptr"), TyKind::Raw(Mutability::Mut, _) => lang_item_crate!("mut_ptr"),
Ty::Dyn(_) => { TyKind::Dyn(_) => {
return self.dyn_trait().and_then(|trait_| { return self.dyn_trait().and_then(|trait_| {
mod_to_crate_ids(GenericDefId::TraitId(trait_).module(db.upcast())) mod_to_crate_ids(GenericDefId::TraitId(trait_).module(db.upcast()))
}); });
@ -430,7 +432,8 @@ 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: Ty::Ref(Mutability::Not, Substs::single(deref_chain[0].value.clone())), value: TyKind::Ref(Mutability::Not, Substs::single(deref_chain[0].value.clone()))
.intern(&Interner),
}; };
if iterate_method_candidates_by_receiver( if iterate_method_candidates_by_receiver(
&refed, &refed,
@ -446,7 +449,8 @@ 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: Ty::Ref(Mutability::Mut, Substs::single(deref_chain[0].value.clone())), value: TyKind::Ref(Mutability::Mut, Substs::single(deref_chain[0].value.clone()))
.intern(&Interner),
}; };
if iterate_method_candidates_by_receiver( if iterate_method_candidates_by_receiver(
&ref_muted, &ref_muted,
@ -526,7 +530,7 @@ fn iterate_trait_method_candidates(
// if ty is `dyn Trait`, the trait doesn't need to be in scope // if ty is `dyn Trait`, the trait doesn't need to be in scope
let inherent_trait = let inherent_trait =
self_ty.value.dyn_trait().into_iter().flat_map(|t| all_super_traits(db.upcast(), t)); self_ty.value.dyn_trait().into_iter().flat_map(|t| all_super_traits(db.upcast(), t));
let env_traits = if let Ty::Placeholder(_) = self_ty.value { let env_traits = if let TyKind::Placeholder(_) = self_ty.value.interned(&Interner) {
// if we have `T: Trait` in the param env, the trait doesn't need to be in scope // if we have `T: Trait` in the param env, the trait doesn't need to be in scope
env.traits_in_scope_from_clauses(&self_ty.value) env.traits_in_scope_from_clauses(&self_ty.value)
.flat_map(|t| all_super_traits(db.upcast(), t)) .flat_map(|t| all_super_traits(db.upcast(), t))
@ -679,13 +683,13 @@ pub(crate) fn inherent_impl_substs(
} }
/// This replaces any 'free' Bound vars in `s` (i.e. those with indices past /// This replaces any 'free' Bound vars in `s` (i.e. those with indices past
/// num_vars_to_keep) by `Ty::Unknown`. /// num_vars_to_keep) by `TyKind::Unknown`.
fn fallback_bound_vars(s: Substs, num_vars_to_keep: usize) -> Substs { fn fallback_bound_vars(s: Substs, num_vars_to_keep: usize) -> Substs {
s.fold_binders( s.fold_binders(
&mut |ty, binders| { &mut |ty, binders| {
if let Ty::BoundVar(bound) = &ty { if let TyKind::BoundVar(bound) = ty.interned(&Interner) {
if bound.index >= num_vars_to_keep && bound.debruijn >= binders { if bound.index >= num_vars_to_keep && bound.debruijn >= binders {
Ty::Unknown TyKind::Unknown.intern(&Interner)
} else { } else {
ty ty
} }
@ -772,9 +776,11 @@ fn autoderef_method_receiver(
) -> Vec<Canonical<Ty>> { ) -> Vec<Canonical<Ty>> {
let mut deref_chain: Vec<_> = autoderef::autoderef(db, Some(krate), ty).collect(); 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!) // As a last step, we can do array unsizing (that's the only unsizing that rustc does for method receivers!)
if let Some(Ty::Array(parameters)) = deref_chain.last().map(|ty| &ty.value) { if let Some(TyKind::Array(parameters)) =
deref_chain.last().map(|ty| ty.value.interned(&Interner))
{
let kinds = deref_chain.last().unwrap().kinds.clone(); let kinds = deref_chain.last().unwrap().kinds.clone();
let unsized_ty = Ty::Slice(parameters.clone()); let unsized_ty = TyKind::Slice(parameters.clone()).intern(&Interner);
deref_chain.push(Canonical { value: unsized_ty, kinds }) deref_chain.push(Canonical { value: unsized_ty, kinds })
} }
deref_chain deref_chain

View file

@ -2,51 +2,55 @@
use chalk_ir::TyVariableKind; use chalk_ir::TyVariableKind;
use hir_def::expr::{ArithOp, BinaryOp, CmpOp}; use hir_def::expr::{ArithOp, BinaryOp, CmpOp};
use crate::{Scalar, Ty}; use crate::{Interner, Scalar, Ty, TyKind};
pub(super) fn binary_op_return_ty(op: BinaryOp, lhs_ty: Ty, rhs_ty: Ty) -> Ty { pub(super) fn binary_op_return_ty(op: BinaryOp, lhs_ty: Ty, rhs_ty: Ty) -> Ty {
match op { match op {
BinaryOp::LogicOp(_) | BinaryOp::CmpOp(_) => Ty::Scalar(Scalar::Bool), BinaryOp::LogicOp(_) | BinaryOp::CmpOp(_) => TyKind::Scalar(Scalar::Bool).intern(&Interner),
BinaryOp::Assignment { .. } => Ty::unit(), BinaryOp::Assignment { .. } => Ty::unit(),
BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => match lhs_ty { BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => {
Ty::Scalar(Scalar::Int(_)) match lhs_ty.interned(&Interner) {
| Ty::Scalar(Scalar::Uint(_)) TyKind::Scalar(Scalar::Int(_))
| Ty::Scalar(Scalar::Float(_)) => lhs_ty, | TyKind::Scalar(Scalar::Uint(_))
Ty::InferenceVar(_, TyVariableKind::Integer) | TyKind::Scalar(Scalar::Float(_)) => lhs_ty,
| Ty::InferenceVar(_, TyVariableKind::Float) => lhs_ty, TyKind::InferenceVar(_, TyVariableKind::Integer)
_ => Ty::Unknown, | TyKind::InferenceVar(_, TyVariableKind::Float) => lhs_ty,
}, _ => TyKind::Unknown.intern(&Interner),
BinaryOp::ArithOp(_) => match rhs_ty { }
Ty::Scalar(Scalar::Int(_)) }
| Ty::Scalar(Scalar::Uint(_)) BinaryOp::ArithOp(_) => match rhs_ty.interned(&Interner) {
| Ty::Scalar(Scalar::Float(_)) => rhs_ty, TyKind::Scalar(Scalar::Int(_))
Ty::InferenceVar(_, TyVariableKind::Integer) | TyKind::Scalar(Scalar::Uint(_))
| Ty::InferenceVar(_, TyVariableKind::Float) => rhs_ty, | TyKind::Scalar(Scalar::Float(_)) => rhs_ty,
_ => Ty::Unknown, TyKind::InferenceVar(_, TyVariableKind::Integer)
| TyKind::InferenceVar(_, TyVariableKind::Float) => rhs_ty,
_ => TyKind::Unknown.intern(&Interner),
}, },
} }
} }
pub(super) fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty { pub(super) fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty {
match op { match op {
BinaryOp::LogicOp(..) => Ty::Scalar(Scalar::Bool), BinaryOp::LogicOp(..) => TyKind::Scalar(Scalar::Bool).intern(&Interner),
BinaryOp::Assignment { op: None } => lhs_ty, BinaryOp::Assignment { op: None } => lhs_ty,
BinaryOp::CmpOp(CmpOp::Eq { .. }) => match lhs_ty { BinaryOp::CmpOp(CmpOp::Eq { .. }) => match lhs_ty.interned(&Interner) {
Ty::Scalar(_) | Ty::Str => lhs_ty, TyKind::Scalar(_) | TyKind::Str => lhs_ty,
Ty::InferenceVar(_, TyVariableKind::Integer) TyKind::InferenceVar(_, TyVariableKind::Integer)
| Ty::InferenceVar(_, TyVariableKind::Float) => lhs_ty, | TyKind::InferenceVar(_, TyVariableKind::Float) => lhs_ty,
_ => Ty::Unknown, _ => TyKind::Unknown.intern(&Interner),
}, },
BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => Ty::Unknown, BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => {
TyKind::Unknown.intern(&Interner)
}
BinaryOp::CmpOp(CmpOp::Ord { .. }) BinaryOp::CmpOp(CmpOp::Ord { .. })
| BinaryOp::Assignment { op: Some(_) } | BinaryOp::Assignment { op: Some(_) }
| BinaryOp::ArithOp(_) => match lhs_ty { | BinaryOp::ArithOp(_) => match lhs_ty.interned(&Interner) {
Ty::Scalar(Scalar::Int(_)) TyKind::Scalar(Scalar::Int(_))
| Ty::Scalar(Scalar::Uint(_)) | TyKind::Scalar(Scalar::Uint(_))
| Ty::Scalar(Scalar::Float(_)) => lhs_ty, | TyKind::Scalar(Scalar::Float(_)) => lhs_ty,
Ty::InferenceVar(_, TyVariableKind::Integer) TyKind::InferenceVar(_, TyVariableKind::Integer)
| Ty::InferenceVar(_, TyVariableKind::Float) => lhs_ty, | TyKind::InferenceVar(_, TyVariableKind::Float) => lhs_ty,
_ => Ty::Unknown, _ => TyKind::Unknown.intern(&Interner),
}, },
} }
} }

View file

@ -10,7 +10,9 @@ use stdx::panic_context;
use crate::{db::HirDatabase, DebruijnIndex, Substs}; use crate::{db::HirDatabase, DebruijnIndex, Substs};
use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk}; use super::{
Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TyKind, TypeWalk,
};
use self::chalk::{from_chalk, Interner, ToChalk}; use self::chalk::{from_chalk, Interner, ToChalk};
@ -132,7 +134,7 @@ pub(crate) fn trait_solve_query(
log::info!("trait_solve_query({})", goal.value.value.display(db)); log::info!("trait_solve_query({})", goal.value.value.display(db));
if let Obligation::Projection(pred) = &goal.value.value { if let Obligation::Projection(pred) = &goal.value.value {
if let Ty::BoundVar(_) = &pred.projection_ty.parameters[0] { if let TyKind::BoundVar(_) = &pred.projection_ty.parameters[0].interned(&Interner) {
// Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible // Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible
return Some(Solution::Ambig(Guidance::Unknown)); return Some(Solution::Ambig(Guidance::Unknown));
} }

View file

@ -20,13 +20,14 @@ use crate::{
method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS}, method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS},
utils::generics, utils::generics,
BoundVar, CallableDefId, CallableSig, DebruijnIndex, GenericPredicate, ProjectionPredicate, BoundVar, CallableDefId, CallableSig, DebruijnIndex, GenericPredicate, ProjectionPredicate,
ProjectionTy, Substs, TraitRef, Ty, ProjectionTy, Substs, TraitRef, Ty, TyKind,
}; };
use mapping::{ use mapping::{
convert_where_clauses, generic_predicate_to_inline_bound, make_binders, TypeAliasAsAssocType, convert_where_clauses, generic_predicate_to_inline_bound, make_binders, TypeAliasAsAssocType,
TypeAliasAsValue, TypeAliasAsValue,
}; };
pub use self::interner::Interner;
pub(crate) use self::interner::*; pub(crate) use self::interner::*;
pub(super) mod tls; pub(super) mod tls;
@ -90,7 +91,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
ty: &Ty, ty: &Ty,
binders: &CanonicalVarKinds<Interner>, binders: &CanonicalVarKinds<Interner>,
) -> Option<chalk_ir::TyVariableKind> { ) -> Option<chalk_ir::TyVariableKind> {
if let Ty::BoundVar(bv) = ty { if let TyKind::BoundVar(bv) = ty.interned(&Interner) {
let binders = binders.as_slice(&Interner); let binders = binders.as_slice(&Interner);
if bv.debruijn == DebruijnIndex::INNERMOST { if bv.debruijn == DebruijnIndex::INNERMOST {
if let chalk_ir::VariableKind::Ty(tk) = binders[bv.index].kind { if let chalk_ir::VariableKind::Ty(tk) = binders[bv.index].kind {
@ -220,21 +221,25 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
let impl_bound = GenericPredicate::Implemented(TraitRef { let impl_bound = GenericPredicate::Implemented(TraitRef {
trait_: future_trait, trait_: future_trait,
// Self type as the first parameter. // Self type as the first parameter.
substs: Substs::single(Ty::BoundVar(BoundVar { substs: Substs::single(
debruijn: DebruijnIndex::INNERMOST, TyKind::BoundVar(BoundVar {
index: 0, debruijn: DebruijnIndex::INNERMOST,
})), index: 0,
})
.intern(&Interner),
),
}); });
let proj_bound = GenericPredicate::Projection(ProjectionPredicate { let proj_bound = GenericPredicate::Projection(ProjectionPredicate {
// The parameter of the opaque type. // The parameter of the opaque type.
ty: Ty::BoundVar(BoundVar { debruijn: DebruijnIndex::ONE, index: 0 }), ty: TyKind::BoundVar(BoundVar { debruijn: DebruijnIndex::ONE, index: 0 })
.intern(&Interner),
projection_ty: ProjectionTy { projection_ty: ProjectionTy {
associated_ty: future_output, associated_ty: future_output,
// Self type as the first parameter. // Self type as the first parameter.
parameters: Substs::single(Ty::BoundVar(BoundVar::new( parameters: Substs::single(
DebruijnIndex::INNERMOST, TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
0, .intern(&Interner),
))), ),
}, },
}); });
let bound = OpaqueTyDatumBound { let bound = OpaqueTyDatumBound {
@ -263,7 +268,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
fn hidden_opaque_type(&self, _id: chalk_ir::OpaqueTyId<Interner>) -> chalk_ir::Ty<Interner> { fn hidden_opaque_type(&self, _id: chalk_ir::OpaqueTyId<Interner>) -> chalk_ir::Ty<Interner> {
// FIXME: actually provide the hidden type; it is relevant for auto traits // FIXME: actually provide the hidden type; it is relevant for auto traits
Ty::Unknown.to_chalk(self.db) TyKind::Unknown.intern(&Interner).to_chalk(self.db)
} }
fn is_object_safe(&self, _trait_id: chalk_ir::TraitId<Interner>) -> bool { fn is_object_safe(&self, _trait_id: chalk_ir::TraitId<Interner>) -> bool {
@ -391,7 +396,8 @@ pub(crate) fn associated_ty_data_query(
let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db.upcast()); let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db.upcast());
let ctx = crate::TyLoweringContext::new(db, &resolver) let ctx = crate::TyLoweringContext::new(db, &resolver)
.with_type_param_mode(crate::lower::TypeParamLoweringMode::Variable); .with_type_param_mode(crate::lower::TypeParamLoweringMode::Variable);
let self_ty = Ty::BoundVar(crate::BoundVar::new(crate::DebruijnIndex::INNERMOST, 0)); let self_ty =
TyKind::BoundVar(BoundVar::new(crate::DebruijnIndex::INNERMOST, 0)).intern(&Interner);
let bounds = type_alias_data let bounds = type_alias_data
.bounds .bounds
.iter() .iter()

View file

@ -26,10 +26,10 @@ 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 { match self.0 {
Ty::Ref(m, parameters) => ref_to_chalk(db, m, parameters), TyKind::Ref(m, parameters) => ref_to_chalk(db, m, parameters),
Ty::Array(parameters) => array_to_chalk(db, parameters), TyKind::Array(parameters) => array_to_chalk(db, parameters),
Ty::Function(FnPointer { sig: FnSig { variadic }, substs, .. }) => { TyKind::Function(FnPointer { sig: FnSig { variadic }, 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 {
num_binders: 0, num_binders: 0,
@ -38,57 +38,57 @@ impl ToChalk for Ty {
}) })
.intern(&Interner) .intern(&Interner)
} }
Ty::AssociatedType(type_alias, substs) => { TyKind::AssociatedType(type_alias, substs) => {
let assoc_type = TypeAliasAsAssocType(type_alias); let assoc_type = TypeAliasAsAssocType(type_alias);
let assoc_type_id = assoc_type.to_chalk(db); let assoc_type_id = assoc_type.to_chalk(db);
let substitution = substs.to_chalk(db); let substitution = substs.to_chalk(db);
chalk_ir::TyKind::AssociatedType(assoc_type_id, substitution).intern(&Interner) chalk_ir::TyKind::AssociatedType(assoc_type_id, substitution).intern(&Interner)
} }
Ty::OpaqueType(impl_trait_id, substs) => { TyKind::OpaqueType(impl_trait_id, substs) => {
let id = impl_trait_id.to_chalk(db); let id = impl_trait_id.to_chalk(db);
let substitution = substs.to_chalk(db); let substitution = substs.to_chalk(db);
chalk_ir::TyKind::OpaqueType(id, substitution).intern(&Interner) chalk_ir::TyKind::OpaqueType(id, substitution).intern(&Interner)
} }
Ty::ForeignType(type_alias) => { TyKind::ForeignType(type_alias) => {
let foreign_type = TypeAliasAsForeignType(type_alias); let foreign_type = TypeAliasAsForeignType(type_alias);
let foreign_type_id = foreign_type.to_chalk(db); let foreign_type_id = foreign_type.to_chalk(db);
chalk_ir::TyKind::Foreign(foreign_type_id).intern(&Interner) chalk_ir::TyKind::Foreign(foreign_type_id).intern(&Interner)
} }
Ty::Scalar(scalar) => chalk_ir::TyKind::Scalar(scalar).intern(&Interner), TyKind::Scalar(scalar) => chalk_ir::TyKind::Scalar(scalar).intern(&Interner),
Ty::Tuple(cardinality, substs) => { TyKind::Tuple(cardinality, substs) => {
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)
} }
Ty::Raw(mutability, substs) => { TyKind::Raw(mutability, substs) => {
let ty = substs[0].clone().to_chalk(db); let ty = substs[0].clone().to_chalk(db);
chalk_ir::TyKind::Raw(mutability, ty).intern(&Interner) chalk_ir::TyKind::Raw(mutability, ty).intern(&Interner)
} }
Ty::Slice(substs) => { TyKind::Slice(substs) => {
chalk_ir::TyKind::Slice(substs[0].clone().to_chalk(db)).intern(&Interner) chalk_ir::TyKind::Slice(substs[0].clone().to_chalk(db)).intern(&Interner)
} }
Ty::Str => chalk_ir::TyKind::Str.intern(&Interner), TyKind::Str => chalk_ir::TyKind::Str.intern(&Interner),
Ty::FnDef(callable_def, substs) => { TyKind::FnDef(callable_def, substs) => {
let id = callable_def.to_chalk(db); let id = callable_def.to_chalk(db);
let substitution = substs.to_chalk(db); let substitution = substs.to_chalk(db);
chalk_ir::TyKind::FnDef(id, substitution).intern(&Interner) chalk_ir::TyKind::FnDef(id, substitution).intern(&Interner)
} }
Ty::Never => chalk_ir::TyKind::Never.intern(&Interner), TyKind::Never => chalk_ir::TyKind::Never.intern(&Interner),
Ty::Closure(def, expr, substs) => { TyKind::Closure(def, expr, substs) => {
let closure_id = db.intern_closure((def, expr)); let closure_id = db.intern_closure((def, expr));
let substitution = substs.to_chalk(db); let substitution = substs.to_chalk(db);
chalk_ir::TyKind::Closure(closure_id.into(), substitution).intern(&Interner) chalk_ir::TyKind::Closure(closure_id.into(), substitution).intern(&Interner)
} }
Ty::Adt(adt_id, substs) => { TyKind::Adt(adt_id, substs) => {
let substitution = substs.to_chalk(db); let substitution = substs.to_chalk(db);
chalk_ir::TyKind::Adt(adt_id, substitution).intern(&Interner) chalk_ir::TyKind::Adt(adt_id, substitution).intern(&Interner)
} }
Ty::Alias(AliasTy::Projection(proj_ty)) => { TyKind::Alias(AliasTy::Projection(proj_ty)) => {
let associated_ty_id = TypeAliasAsAssocType(proj_ty.associated_ty).to_chalk(db); let associated_ty_id = TypeAliasAsAssocType(proj_ty.associated_ty).to_chalk(db);
let substitution = proj_ty.parameters.to_chalk(db); let substitution = proj_ty.parameters.to_chalk(db);
chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy { chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy {
@ -98,7 +98,7 @@ impl ToChalk for Ty {
.cast(&Interner) .cast(&Interner)
.intern(&Interner) .intern(&Interner)
} }
Ty::Placeholder(id) => { TyKind::Placeholder(id) => {
let interned_id = db.intern_type_param_id(id); let interned_id = db.intern_type_param_id(id);
PlaceholderIndex { PlaceholderIndex {
ui: UniverseIndex::ROOT, ui: UniverseIndex::ROOT,
@ -106,9 +106,9 @@ impl ToChalk for Ty {
} }
.to_ty::<Interner>(&Interner) .to_ty::<Interner>(&Interner)
} }
Ty::BoundVar(idx) => chalk_ir::TyKind::BoundVar(idx).intern(&Interner), TyKind::BoundVar(idx) => chalk_ir::TyKind::BoundVar(idx).intern(&Interner),
Ty::InferenceVar(..) => panic!("uncanonicalized infer ty"), TyKind::InferenceVar(..) => panic!("uncanonicalized infer ty"),
Ty::Dyn(predicates) => { TyKind::Dyn(predicates) => {
let where_clauses = chalk_ir::QuantifiedWhereClauses::from_iter( let where_clauses = chalk_ir::QuantifiedWhereClauses::from_iter(
&Interner, &Interner,
predicates.iter().filter(|p| !p.is_error()).cloned().map(|p| p.to_chalk(db)), predicates.iter().filter(|p| !p.is_error()).cloned().map(|p| p.to_chalk(db)),
@ -119,7 +119,7 @@ impl ToChalk for Ty {
}; };
chalk_ir::TyKind::Dyn(bounded_ty).intern(&Interner) chalk_ir::TyKind::Dyn(bounded_ty).intern(&Interner)
} }
Ty::Alias(AliasTy::Opaque(opaque_ty)) => { TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
let opaque_ty_id = opaque_ty.opaque_ty_id.to_chalk(db); let opaque_ty_id = opaque_ty.opaque_ty_id.to_chalk(db);
let substitution = opaque_ty.parameters.to_chalk(db); let substitution = opaque_ty.parameters.to_chalk(db);
chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy { chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy {
@ -128,30 +128,30 @@ impl ToChalk for Ty {
})) }))
.intern(&Interner) .intern(&Interner)
} }
Ty::Unknown => chalk_ir::TyKind::Error.intern(&Interner), TyKind::Unknown => chalk_ir::TyKind::Error.intern(&Interner),
} }
} }
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 => Ty::Unknown, chalk_ir::TyKind::Error => TyKind::Unknown,
chalk_ir::TyKind::Array(ty, _size) => Ty::Array(Substs::single(from_chalk(db, ty))), chalk_ir::TyKind::Array(ty, _size) => TyKind::Array(Substs::single(from_chalk(db, ty))),
chalk_ir::TyKind::Placeholder(idx) => { chalk_ir::TyKind::Placeholder(idx) => {
assert_eq!(idx.ui, UniverseIndex::ROOT); assert_eq!(idx.ui, UniverseIndex::ROOT);
let interned_id = crate::db::GlobalTypeParamId::from_intern_id( let interned_id = crate::db::GlobalTypeParamId::from_intern_id(
crate::salsa::InternId::from(idx.idx), crate::salsa::InternId::from(idx.idx),
); );
Ty::Placeholder(db.lookup_intern_type_param_id(interned_id)) TyKind::Placeholder(db.lookup_intern_type_param_id(interned_id))
} }
chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Projection(proj)) => { chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Projection(proj)) => {
let associated_ty = let associated_ty =
from_chalk::<TypeAliasAsAssocType, _>(db, proj.associated_ty_id).0; from_chalk::<TypeAliasAsAssocType, _>(db, proj.associated_ty_id).0;
let parameters = from_chalk(db, proj.substitution); let parameters = from_chalk(db, proj.substitution);
Ty::Alias(AliasTy::Projection(ProjectionTy { associated_ty, parameters })) TyKind::Alias(AliasTy::Projection(ProjectionTy { associated_ty, parameters }))
} }
chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Opaque(opaque_ty)) => { chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Opaque(opaque_ty)) => {
let impl_trait_id = from_chalk(db, opaque_ty.opaque_ty_id); let impl_trait_id = from_chalk(db, opaque_ty.opaque_ty_id);
let parameters = from_chalk(db, opaque_ty.substitution); let parameters = from_chalk(db, opaque_ty.substitution);
Ty::Alias(AliasTy::Opaque(OpaqueTy { opaque_ty_id: impl_trait_id, parameters })) TyKind::Alias(AliasTy::Opaque(OpaqueTy { opaque_ty_id: impl_trait_id, parameters }))
} }
chalk_ir::TyKind::Function(chalk_ir::FnPointer { chalk_ir::TyKind::Function(chalk_ir::FnPointer {
num_binders, num_binders,
@ -164,14 +164,14 @@ impl ToChalk for Ty {
db, db,
substitution.0.shifted_out(&Interner).expect("fn ptr should have no binders"), substitution.0.shifted_out(&Interner).expect("fn ptr should have no binders"),
); );
Ty::Function(FnPointer { TyKind::Function(FnPointer {
num_args: (substs.len() - 1), num_args: (substs.len() - 1),
sig: FnSig { variadic }, sig: FnSig { variadic },
substs, substs,
}) })
} }
chalk_ir::TyKind::BoundVar(idx) => Ty::BoundVar(idx), chalk_ir::TyKind::BoundVar(idx) => TyKind::BoundVar(idx),
chalk_ir::TyKind::InferenceVar(_iv, _kind) => Ty::Unknown, chalk_ir::TyKind::InferenceVar(_iv, _kind) => TyKind::Unknown,
chalk_ir::TyKind::Dyn(where_clauses) => { chalk_ir::TyKind::Dyn(where_clauses) => {
assert_eq!(where_clauses.bounds.binders.len(&Interner), 1); assert_eq!(where_clauses.bounds.binders.len(&Interner), 1);
let predicates = where_clauses let predicates = where_clauses
@ -180,49 +180,50 @@ impl ToChalk for Ty {
.iter(&Interner) .iter(&Interner)
.map(|c| from_chalk(db, c.clone())) .map(|c| from_chalk(db, c.clone()))
.collect(); .collect();
Ty::Dyn(predicates) TyKind::Dyn(predicates)
} }
chalk_ir::TyKind::Adt(adt_id, subst) => Ty::Adt(adt_id, from_chalk(db, subst)), chalk_ir::TyKind::Adt(adt_id, subst) => TyKind::Adt(adt_id, from_chalk(db, subst)),
chalk_ir::TyKind::AssociatedType(type_id, subst) => Ty::AssociatedType( chalk_ir::TyKind::AssociatedType(type_id, subst) => TyKind::AssociatedType(
from_chalk::<TypeAliasAsAssocType, _>(db, type_id).0, from_chalk::<TypeAliasAsAssocType, _>(db, type_id).0,
from_chalk(db, subst), from_chalk(db, subst),
), ),
chalk_ir::TyKind::OpaqueType(opaque_type_id, subst) => { chalk_ir::TyKind::OpaqueType(opaque_type_id, subst) => {
Ty::OpaqueType(from_chalk(db, opaque_type_id), from_chalk(db, subst)) TyKind::OpaqueType(from_chalk(db, opaque_type_id), from_chalk(db, subst))
} }
chalk_ir::TyKind::Scalar(scalar) => Ty::Scalar(scalar), chalk_ir::TyKind::Scalar(scalar) => TyKind::Scalar(scalar),
chalk_ir::TyKind::Tuple(cardinality, subst) => { chalk_ir::TyKind::Tuple(cardinality, subst) => {
Ty::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) => {
Ty::Raw(mutability, Substs::single(from_chalk(db, ty))) TyKind::Raw(mutability, Substs::single(from_chalk(db, ty)))
} }
chalk_ir::TyKind::Slice(ty) => Ty::Slice(Substs::single(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) => {
Ty::Ref(mutability, Substs::single(from_chalk(db, ty))) TyKind::Ref(mutability, Substs::single(from_chalk(db, ty)))
} }
chalk_ir::TyKind::Str => Ty::Str, chalk_ir::TyKind::Str => TyKind::Str,
chalk_ir::TyKind::Never => Ty::Never, chalk_ir::TyKind::Never => TyKind::Never,
chalk_ir::TyKind::FnDef(fn_def_id, subst) => { chalk_ir::TyKind::FnDef(fn_def_id, subst) => {
Ty::FnDef(from_chalk(db, fn_def_id), from_chalk(db, subst)) TyKind::FnDef(from_chalk(db, fn_def_id), from_chalk(db, subst))
} }
chalk_ir::TyKind::Closure(id, subst) => { chalk_ir::TyKind::Closure(id, subst) => {
let id: crate::db::ClosureId = id.into(); let id: crate::db::ClosureId = id.into();
let (def, expr) = db.lookup_intern_closure(id); let (def, expr) = db.lookup_intern_closure(id);
Ty::Closure(def, expr, from_chalk(db, subst)) TyKind::Closure(def, expr, from_chalk(db, subst))
} }
chalk_ir::TyKind::Foreign(foreign_def_id) => { chalk_ir::TyKind::Foreign(foreign_def_id) => {
Ty::ForeignType(from_chalk::<TypeAliasAsForeignType, _>(db, foreign_def_id).0) TyKind::ForeignType(from_chalk::<TypeAliasAsForeignType, _>(db, foreign_def_id).0)
} }
chalk_ir::TyKind::Generator(_, _) => unimplemented!(), // FIXME chalk_ir::TyKind::Generator(_, _) => unimplemented!(), // FIXME
chalk_ir::TyKind::GeneratorWitness(_, _) => unimplemented!(), // FIXME chalk_ir::TyKind::GeneratorWitness(_, _) => unimplemented!(), // FIXME
} }
.intern(&Interner)
} }
} }

View file

@ -12,7 +12,7 @@ use hir::{
AssocItem, Crate, HasSource, HirDisplay, ModuleDef, AssocItem, Crate, HasSource, HirDisplay, ModuleDef,
}; };
use hir_def::FunctionId; use hir_def::FunctionId;
use hir_ty::{Ty, TypeWalk}; use hir_ty::TypeWalk;
use ide_db::base_db::{ use ide_db::base_db::{
salsa::{self, ParallelDatabase}, salsa::{self, ParallelDatabase},
SourceDatabaseExt, SourceDatabaseExt,
@ -187,12 +187,12 @@ impl AnalysisStatsCmd {
for (expr_id, _) in body.exprs.iter() { for (expr_id, _) in body.exprs.iter() {
let ty = &inference_result[expr_id]; let ty = &inference_result[expr_id];
num_exprs += 1; num_exprs += 1;
if let Ty::Unknown = ty { if ty.is_unknown() {
num_exprs_unknown += 1; num_exprs_unknown += 1;
} else { } else {
let mut is_partially_unknown = false; let mut is_partially_unknown = false;
ty.walk(&mut |ty| { ty.walk(&mut |ty| {
if let Ty::Unknown = ty { if ty.is_unknown() {
is_partially_unknown = true; is_partially_unknown = true;
} }
}); });