Use Chalk's built-in representation of function item types

This commit is contained in:
Florian Diebold 2020-05-22 18:15:53 +02:00 committed by Florian Diebold
parent d4daca9f02
commit bfbc210bc1
7 changed files with 128 additions and 10 deletions

View file

@ -76,6 +76,8 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
#[salsa::interned]
fn intern_type_ctor(&self, type_ctor: TypeCtor) -> crate::TypeCtorId;
#[salsa::interned]
fn intern_callable_def(&self, callable_def: CallableDef) -> crate::CallableDefId;
#[salsa::interned]
fn intern_type_param_id(&self, param_id: TypeParamId) -> GlobalTypeParamId;
#[salsa::interned]
fn intern_chalk_impl(&self, impl_: Impl) -> crate::traits::GlobalImplId;
@ -94,6 +96,9 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
#[salsa::invoke(crate::traits::chalk::impl_datum_query)]
fn impl_datum(&self, krate: CrateId, impl_id: chalk::ImplId) -> Arc<chalk::ImplDatum>;
#[salsa::invoke(crate::traits::chalk::fn_def_datum_query)]
fn fn_def_datum(&self, krate: CrateId, fn_def_id: chalk::FnDefId) -> Arc<chalk::FnDefDatum>;
#[salsa::invoke(crate::traits::chalk::associated_ty_value_query)]
fn associated_ty_value(
&self,

View file

@ -159,6 +159,12 @@ pub enum TypeCtor {
pub struct TypeCtorId(salsa::InternId);
impl_intern_key!(TypeCtorId);
/// This exists just for Chalk, because Chalk just has a single `FnDefId` where
/// we have different IDs for struct and enum variant constructors.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub struct CallableDefId(salsa::InternId);
impl_intern_key!(CallableDefId);
impl TypeCtor {
pub fn num_ty_params(self, db: &dyn HirDatabase) -> usize {
match self {

View file

@ -2643,6 +2643,48 @@ fn test() {
);
}
#[test]
fn builtin_fn_def_copy() {
assert_snapshot!(
infer_with_mismatches(r#"
#[lang = "copy"]
trait Copy {}
fn foo() {}
fn bar<T: Copy>(T) -> T {}
struct Struct(usize);
enum Enum { Variant(usize) }
trait Test { fn test(&self) -> bool; }
impl<T: Copy> Test for T {}
fn test() {
foo.test();
bar.test();
Struct.test();
Enum::Variant.test();
}
"#, true),
// wrong result, because the built-in Copy impl for fn defs doesn't exist in Chalk yet
@r###"
42..44 '{}': ()
61..62 'T': {unknown}
69..71 '{}': ()
69..71: expected T, got ()
146..150 'self': &Self
202..282 '{ ...t(); }': ()
208..211 'foo': fn foo()
208..218 'foo.test()': {unknown}
224..227 'bar': fn bar<{unknown}>({unknown}) -> {unknown}
224..234 'bar.test()': {unknown}
240..246 'Struct': Struct(usize) -> Struct
240..253 'Struct.test()': {unknown}
259..272 'Enum::Variant': Variant(usize) -> Enum
259..279 'Enum::...test()': {unknown}
"###
);
}
#[test]
fn builtin_sized() {
assert_snapshot!(

View file

@ -14,7 +14,7 @@ use ra_db::{salsa::InternKey, CrateId};
use super::{builtin, AssocTyValue, ChalkContext, Impl};
use crate::{
db::HirDatabase, display::HirDisplay, method_resolution::TyFingerprint, utils::generics,
DebruijnIndex, GenericPredicate, Substs, Ty, TypeCtor,
CallableDef, DebruijnIndex, GenericPredicate, Substs, Ty, TypeCtor,
};
use chalk_rust_ir::WellKnownTrait;
use mapping::{convert_where_clauses, generic_predicate_to_inline_bound, make_binders};
@ -54,10 +54,9 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
fn fn_def_datum(
&self,
_fn_def_id: chalk_ir::FnDefId<Interner>,
fn_def_id: chalk_ir::FnDefId<Interner>,
) -> Arc<chalk_rust_ir::FnDefDatum<Interner>> {
// We don't yet provide any FnDefs to Chalk
unimplemented!()
self.db.fn_def_datum(self.krate, fn_def_id)
}
fn impls_for_trait(
@ -405,6 +404,26 @@ fn type_alias_associated_ty_value(
Arc::new(value)
}
pub(crate) fn fn_def_datum_query(
db: &dyn HirDatabase,
_krate: CrateId,
fn_def_id: FnDefId,
) -> Arc<FnDefDatum> {
let callable_def: CallableDef = from_chalk(db, fn_def_id);
let generic_params = generics(db.upcast(), callable_def.into());
let sig = db.callable_item_signature(callable_def);
let bound_vars = Substs::bound_vars(&generic_params, DebruijnIndex::INNERMOST);
let where_clauses = convert_where_clauses(db, callable_def.into(), &bound_vars);
let bound = chalk_rust_ir::FnDefDatumBound {
// Note: Chalk doesn't actually use this information yet as far as I am aware, but we provide it anyway
argument_types: sig.value.params().iter().map(|ty| ty.clone().to_chalk(db)).collect(),
return_type: sig.value.ret().clone().to_chalk(db),
where_clauses,
};
let datum = FnDefDatum { id: fn_def_id, binders: make_binders(bound, sig.num_binders) };
Arc::new(datum)
}
impl From<AdtId> for crate::TypeCtorId {
fn from(struct_id: AdtId) -> Self {
struct_id.0
@ -417,6 +436,18 @@ impl From<crate::TypeCtorId> for AdtId {
}
}
impl From<FnDefId> for crate::CallableDefId {
fn from(fn_def_id: FnDefId) -> Self {
InternKey::from_intern_id(fn_def_id.0)
}
}
impl From<crate::CallableDefId> for FnDefId {
fn from(callable_def_id: crate::CallableDefId) -> Self {
chalk_ir::FnDefId(callable_def_id.as_intern_id())
}
}
impl From<ImplId> for crate::traits::GlobalImplId {
fn from(impl_id: ImplId) -> Self {
InternKey::from_intern_id(impl_id.0)

View file

@ -20,6 +20,8 @@ pub type ImplId = chalk_ir::ImplId<Interner>;
pub type ImplDatum = chalk_rust_ir::ImplDatum<Interner>;
pub type AssociatedTyValueId = chalk_rust_ir::AssociatedTyValueId<Interner>;
pub type AssociatedTyValue = chalk_rust_ir::AssociatedTyValue<Interner>;
pub type FnDefId = chalk_ir::FnDefId<Interner>;
pub type FnDefDatum = chalk_rust_ir::FnDefDatum<Interner>;
impl chalk_ir::interner::Interner for Interner {
type InternedType = Box<chalk_ir::TyData<Self>>; // FIXME use Arc?

View file

@ -15,8 +15,8 @@ use crate::{
db::HirDatabase,
primitive::{FloatBitness, FloatTy, IntBitness, IntTy, Signedness, Uncertain},
traits::{builtin, AssocTyValue, Canonical, Impl, Obligation},
ApplicationTy, GenericPredicate, InEnvironment, ProjectionPredicate, ProjectionTy, Substs,
TraitEnvironment, TraitRef, Ty, TypeCtor,
ApplicationTy, CallableDef, GenericPredicate, InEnvironment, ProjectionPredicate, ProjectionTy,
Substs, TraitEnvironment, TraitRef, Ty, TypeCtor,
};
use super::interner::*;
@ -217,11 +217,14 @@ impl ToChalk for TypeCtor {
TypeCtor::Slice => TypeName::Slice,
TypeCtor::Ref(mutability) => TypeName::Ref(mutability.to_chalk(db)),
TypeCtor::Str => TypeName::Str,
TypeCtor::FnDef(callable_def) => {
let id = callable_def.to_chalk(db);
TypeName::FnDef(id)
}
TypeCtor::Int(Uncertain::Unknown)
| TypeCtor::Float(Uncertain::Unknown)
| TypeCtor::Adt(_)
| TypeCtor::Array
| TypeCtor::FnDef(_)
| TypeCtor::FnPtr { .. }
| TypeCtor::Never
| TypeCtor::Closure { .. } => {
@ -260,7 +263,10 @@ impl ToChalk for TypeCtor {
TypeName::Ref(mutability) => TypeCtor::Ref(from_chalk(db, mutability)),
TypeName::Str => TypeCtor::Str,
TypeName::FnDef(_) => unreachable!(),
TypeName::FnDef(fn_def_id) => {
let callable_def = from_chalk(db, fn_def_id);
TypeCtor::FnDef(callable_def)
}
TypeName::Error => {
// this should not be reached, since we don't represent TypeName::Error with TypeCtor
@ -347,6 +353,18 @@ impl ToChalk for Impl {
}
}
impl ToChalk for CallableDef {
type Chalk = FnDefId;
fn to_chalk(self, db: &dyn HirDatabase) -> FnDefId {
db.intern_callable_def(self).into()
}
fn from_chalk(db: &dyn HirDatabase, fn_def_id: FnDefId) -> CallableDef {
db.lookup_intern_callable_def(fn_def_id.into())
}
}
impl ToChalk for TypeAliasId {
type Chalk = AssocTypeId;

View file

@ -247,10 +247,24 @@ impl DebugContext<'_> {
pub fn debug_fn_def_id(
&self,
_fn_def_id: chalk_ir::FnDefId<Interner>,
fn_def_id: chalk_ir::FnDefId<Interner>,
fmt: &mut fmt::Formatter<'_>,
) -> Result<(), fmt::Error> {
write!(fmt, "fn")
let def: CallableDef = from_chalk(self.0, fn_def_id);
let name = match def {
CallableDef::FunctionId(ff) => self.0.function_data(ff).name.clone(),
CallableDef::StructId(s) => self.0.struct_data(s).name.clone(),
CallableDef::EnumVariantId(e) => {
let enum_data = self.0.enum_data(e.parent);
enum_data.variants[e.local_id].name.clone()
}
};
match def {
CallableDef::FunctionId(_) => write!(fmt, "{{fn {}}}", name),
CallableDef::StructId(_) | CallableDef::EnumVariantId(_) => {
write!(fmt, "{{ctor {}}}", name)
}
}
}
pub fn debug_const(