Remove ns-polymorphic type_for_def

This commit is contained in:
Aleksey Kladov 2019-11-26 21:04:24 +03:00
parent 475367d08a
commit 4e415a269e
9 changed files with 129 additions and 165 deletions

View file

@ -28,8 +28,7 @@ use crate::{
expr::{BindingAnnotation, Body, BodySourceMap, ExprValidator, Pat, PatId}, expr::{BindingAnnotation, Body, BodySourceMap, ExprValidator, Pat, PatId},
ty::display::HirFormatter, ty::display::HirFormatter,
ty::{ ty::{
self, InEnvironment, InferenceResult, Namespace, TraitEnvironment, TraitRef, Ty, TypeCtor, self, InEnvironment, InferenceResult, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk,
TypeWalk,
}, },
CallableDef, Either, HirDisplay, Name, Source, CallableDef, Either, HirDisplay, Name, Source,
}; };
@ -354,11 +353,11 @@ impl Struct {
} }
pub fn ty(self, db: &impl HirDatabase) -> Ty { pub fn ty(self, db: &impl HirDatabase) -> Ty {
db.type_for_def(self.into(), Namespace::Types) db.ty(self.id.into())
} }
pub fn constructor_ty(self, db: &impl HirDatabase) -> Ty { pub fn constructor_ty(self, db: &impl HirDatabase) -> Ty {
db.type_for_def(self.into(), Namespace::Values) db.value_ty(self.id.into())
} }
fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> { fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> {
@ -381,7 +380,7 @@ impl Union {
} }
pub fn ty(self, db: &impl HirDatabase) -> Ty { pub fn ty(self, db: &impl HirDatabase) -> Ty {
db.type_for_def(self.into(), Namespace::Types) db.ty(self.id.into())
} }
pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> { pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> {
@ -442,7 +441,7 @@ impl Enum {
} }
pub fn ty(self, db: &impl HirDatabase) -> Ty { pub fn ty(self, db: &impl HirDatabase) -> Ty {
db.type_for_def(self.into(), Namespace::Types) db.ty(self.id.into())
} }
} }
@ -617,7 +616,7 @@ impl Function {
} }
pub fn ty(self, db: &impl HirDatabase) -> Ty { pub fn ty(self, db: &impl HirDatabase) -> Ty {
db.type_for_def(self.into(), Namespace::Values) db.value_ty(self.id.into())
} }
pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> { pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> {
@ -797,7 +796,7 @@ impl TypeAlias {
} }
pub fn ty(self, db: &impl HirDatabase) -> Ty { pub fn ty(self, db: &impl HirDatabase) -> Ty {
db.type_for_def(self.into(), Namespace::Types) db.ty(self.id.into())
} }
pub fn name(self, db: &impl DefDatabase) -> Name { pub fn name(self, db: &impl DefDatabase) -> Name {

View file

@ -9,8 +9,8 @@ use crate::{
ty::{ ty::{
method_resolution::CrateImplBlocks, method_resolution::CrateImplBlocks,
traits::{AssocTyValue, Impl}, traits::{AssocTyValue, Impl},
CallableDef, FnSig, GenericPredicate, InferenceResult, Namespace, Substs, Ty, TypableDef, CallableDef, FnSig, GenericPredicate, InferenceResult, Substs, Ty, TyDefId, TypeCtor,
TypeCtor, ValueTyDefId,
}, },
Crate, DefWithBody, ImplBlock, Trait, Crate, DefWithBody, ImplBlock, Trait,
}; };
@ -37,8 +37,11 @@ pub trait HirDatabase: DefDatabase {
#[salsa::invoke(crate::ty::infer_query)] #[salsa::invoke(crate::ty::infer_query)]
fn infer(&self, def: DefWithBody) -> Arc<InferenceResult>; fn infer(&self, def: DefWithBody) -> Arc<InferenceResult>;
#[salsa::invoke(crate::ty::type_for_def)] #[salsa::invoke(crate::ty::ty_query)]
fn type_for_def(&self, def: TypableDef, ns: Namespace) -> Ty; fn ty(&self, def: TyDefId) -> Ty;
#[salsa::invoke(crate::ty::value_ty_query)]
fn value_ty(&self, def: ValueTyDefId) -> Ty;
#[salsa::invoke(crate::ty::field_types_query)] #[salsa::invoke(crate::ty::field_types_query)]
fn field_types(&self, var: VariantId) -> Arc<ArenaMap<LocalStructFieldId, Ty>>; fn field_types(&self, var: VariantId) -> Arc<ArenaMap<LocalStructFieldId, Ty>>;

View file

@ -37,8 +37,8 @@ pub(crate) use infer::{infer_query, InferTy, InferenceResult};
pub use lower::CallableDef; pub use lower::CallableDef;
pub(crate) use lower::{ pub(crate) use lower::{
callable_item_sig, field_types_query, generic_defaults_query, callable_item_sig, field_types_query, generic_defaults_query,
generic_predicates_for_param_query, generic_predicates_query, type_for_def, Namespace, generic_predicates_for_param_query, generic_predicates_query, ty_query, value_ty_query,
TypableDef, TyDefId, TypableDef, ValueTyDefId,
}; };
pub(crate) use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment}; pub(crate) use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment};

View file

@ -35,15 +35,15 @@ use test_utils::tested_by;
use super::{ use super::{
traits::{Guidance, Obligation, ProjectionPredicate, Solution}, traits::{Guidance, Obligation, ProjectionPredicate, Solution},
ApplicationTy, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypableDef, ApplicationTy, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor,
TypeCtor, TypeWalk, Uncertain, TypeWalk, Uncertain,
}; };
use crate::{ use crate::{
code_model::TypeAlias, code_model::TypeAlias,
db::HirDatabase, db::HirDatabase,
expr::{BindingAnnotation, Body, ExprId, PatId}, expr::{BindingAnnotation, Body, ExprId, PatId},
ty::infer::diagnostics::InferenceDiagnostic, ty::infer::diagnostics::InferenceDiagnostic,
Adt, AssocItem, DefWithBody, FloatTy, Function, IntTy, Path, StructField, VariantDef, AssocItem, DefWithBody, FloatTy, Function, IntTy, Path, StructField, VariantDef,
}; };
macro_rules! ty_app { macro_rules! ty_app {
@ -520,45 +520,22 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
None => return (Ty::Unknown, None), None => return (Ty::Unknown, None),
}; };
let resolver = &self.resolver; let resolver = &self.resolver;
let def: TypableDef = // FIXME: this should resolve assoc items as well, see this example:
// FIXME: this should resolve assoc items as well, see this example: // https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521
// https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521 match resolver.resolve_path_in_type_ns_fully(self.db, &path) {
match resolver.resolve_path_in_type_ns_fully(self.db, &path) { Some(TypeNs::AdtId(AdtId::StructId(strukt))) => {
Some(TypeNs::AdtId(AdtId::StructId(it))) => it.into(), let substs = Ty::substs_from_path(self.db, resolver, path, strukt.into());
Some(TypeNs::AdtId(AdtId::UnionId(it))) => it.into(), let ty = self.db.ty(strukt.into());
Some(TypeNs::AdtSelfType(adt)) => adt.into(),
Some(TypeNs::EnumVariantId(it)) => it.into(),
Some(TypeNs::TypeAliasId(it)) => it.into(),
Some(TypeNs::SelfType(_)) |
Some(TypeNs::GenericParam(_)) |
Some(TypeNs::BuiltinType(_)) |
Some(TypeNs::TraitId(_)) |
Some(TypeNs::AdtId(AdtId::EnumId(_))) |
None => {
return (Ty::Unknown, None)
}
};
// FIXME remove the duplication between here and `Ty::from_path`?
let substs = Ty::substs_from_path(self.db, resolver, path, def);
match def {
TypableDef::Adt(Adt::Struct(s)) => {
let ty = s.ty(self.db);
let ty = self.insert_type_vars(ty.apply_substs(substs)); let ty = self.insert_type_vars(ty.apply_substs(substs));
(ty, Some(s.into())) (ty, Some(VariantDef::Struct(strukt.into())))
} }
TypableDef::EnumVariant(var) => { Some(TypeNs::EnumVariantId(var)) => {
let ty = var.parent_enum(self.db).ty(self.db); let substs = Ty::substs_from_path(self.db, resolver, path, var.into());
let ty = self.db.ty(var.parent.into());
let ty = self.insert_type_vars(ty.apply_substs(substs)); let ty = self.insert_type_vars(ty.apply_substs(substs));
(ty, Some(var.into())) (ty, Some(VariantDef::EnumVariant(var.into())))
} }
TypableDef::Adt(Adt::Enum(_)) Some(_) | None => (Ty::Unknown, None),
| TypableDef::Adt(Adt::Union(_))
| TypableDef::TypeAlias(_)
| TypableDef::Function(_)
| TypableDef::Const(_)
| TypableDef::Static(_)
| TypableDef::BuiltinType(_) => (Ty::Unknown, None),
} }
} }

View file

@ -17,8 +17,8 @@ use crate::{
expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp},
ty::{ ty::{
autoderef, method_resolution, op, traits::InEnvironment, CallableDef, InferTy, IntTy, autoderef, method_resolution, op, traits::InEnvironment, CallableDef, InferTy, IntTy,
Mutability, Namespace, Obligation, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, Mutability, Obligation, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor,
TypeCtor, TypeWalk, Uncertain, TypeWalk, Uncertain,
}, },
Name, Name,
}; };
@ -558,11 +558,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
Some((ty, func)) => { Some((ty, func)) => {
let ty = canonicalized_receiver.decanonicalize_ty(ty); let ty = canonicalized_receiver.decanonicalize_ty(ty);
self.write_method_resolution(tgt_expr, func); self.write_method_resolution(tgt_expr, func);
( (ty, self.db.value_ty(func.id.into()), Some(self.db.generic_params(func.id.into())))
ty,
self.db.type_for_def(func.into(), Namespace::Values),
Some(self.db.generic_params(func.id.into())),
)
} }
None => (receiver_ty, Ty::Unknown, None), None => (receiver_ty, Ty::Unknown, None),
}; };

View file

@ -7,7 +7,7 @@ use hir_def::{
use crate::{ use crate::{
db::HirDatabase, db::HirDatabase,
ty::{method_resolution, Namespace, Substs, Ty, TypableDef, TypeWalk}, ty::{method_resolution, Substs, Ty, TypeWalk, ValueTyDefId},
AssocItem, Container, Function, Name, Path, AssocItem, Container, Function, Name, Path,
}; };
@ -56,7 +56,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
} }
}; };
let typable: TypableDef = match value { let typable: ValueTyDefId = match value {
ValueNs::LocalBinding(pat) => { ValueNs::LocalBinding(pat) => {
let ty = self.result.type_of_pat.get(pat)?.clone(); let ty = self.result.type_of_pat.get(pat)?.clone();
let ty = self.resolve_ty_as_possible(&mut vec![], ty); let ty = self.resolve_ty_as_possible(&mut vec![], ty);
@ -69,11 +69,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
ValueNs::EnumVariantId(it) => it.into(), ValueNs::EnumVariantId(it) => it.into(),
}; };
let mut ty = self.db.type_for_def(typable, Namespace::Values); let mut ty = self.db.value_ty(typable);
if let Some(self_subst) = self_subst { if let Some(self_subst) = self_subst {
ty = ty.subst(&self_subst); ty = ty.subst(&self_subst);
} }
let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable); let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable);
let ty = ty.subst(&substs); let ty = ty.subst(&substs);
Some(ty) Some(ty)

View file

@ -14,8 +14,8 @@ use hir_def::{
path::{GenericArg, PathSegment}, path::{GenericArg, PathSegment},
resolver::{HasResolver, Resolver, TypeNs}, resolver::{HasResolver, Resolver, TypeNs},
type_ref::{TypeBound, TypeRef}, type_ref::{TypeBound, TypeRef},
AdtId, AstItemDef, EnumVariantId, FunctionId, GenericDefId, HasModule, LocalStructFieldId, AdtId, AstItemDef, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule,
Lookup, StructId, TraitId, VariantId, LocalStructFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, UnionId, VariantId,
}; };
use ra_arena::map::ArenaMap; use ra_arena::map::ArenaMap;
use ra_db::CrateId; use ra_db::CrateId;
@ -35,17 +35,6 @@ use crate::{
TypeAlias, Union, TypeAlias, Union,
}; };
// FIXME: this is only really used in `type_for_def`, which contains a bunch of
// impossible cases. Perhaps we should recombine `TypeableDef` and `Namespace`
// into a `AsTypeDef`, `AsValueDef` enums?
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Namespace {
Types,
Values,
// Note that only type inference uses this enum, and it doesn't care about macros.
// Macro,
}
impl Ty { impl Ty {
pub(crate) fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &TypeRef) -> Self { pub(crate) fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &TypeRef) -> Self {
match type_ref { match type_ref {
@ -281,27 +270,15 @@ impl Ty {
db: &impl HirDatabase, db: &impl HirDatabase,
resolver: &Resolver, resolver: &Resolver,
segment: &PathSegment, segment: &PathSegment,
typable: TypableDef, typable: TyDefId,
) -> Ty { ) -> Ty {
let ty = db.type_for_def(typable, Namespace::Types); let generic_def = match typable {
let substs = Ty::substs_from_path_segment(db, resolver, segment, typable); TyDefId::BuiltinType(_) => None,
ty.subst(&substs) TyDefId::AdtId(it) => Some(it.into()),
} TyDefId::TypeAliasId(it) => Some(it.into()),
pub(super) fn substs_from_path_segment(
db: &impl HirDatabase,
resolver: &Resolver,
segment: &PathSegment,
resolved: TypableDef,
) -> Substs {
let def_generic: Option<GenericDefId> = match resolved {
TypableDef::Function(func) => Some(func.id.into()),
TypableDef::Adt(adt) => Some(adt.into()),
TypableDef::EnumVariant(var) => Some(var.parent_enum(db).id.into()),
TypableDef::TypeAlias(t) => Some(t.id.into()),
TypableDef::Const(_) | TypableDef::Static(_) | TypableDef::BuiltinType(_) => None,
}; };
substs_from_path_segment(db, resolver, segment, def_generic, false) let substs = substs_from_path_segment(db, resolver, segment, generic_def, false);
db.ty(typable).subst(&substs)
} }
/// Collect generic arguments from a path into a `Substs`. See also /// Collect generic arguments from a path into a `Substs`. See also
@ -310,17 +287,18 @@ impl Ty {
db: &impl HirDatabase, db: &impl HirDatabase,
resolver: &Resolver, resolver: &Resolver,
path: &Path, path: &Path,
resolved: TypableDef, // Note that we don't call `db.value_type(resolved)` here,
// `ValueTyDefId` is just a convenient way to pass generics and
// special-case enum variants
resolved: ValueTyDefId,
) -> Substs { ) -> Substs {
let last = path.segments.last().expect("path should have at least one segment"); let last = path.segments.last().expect("path should have at least one segment");
let segment = match resolved { let (segment, generic_def) = match resolved {
TypableDef::Function(_) ValueTyDefId::FunctionId(it) => (last, Some(it.into())),
| TypableDef::Adt(_) ValueTyDefId::StructId(it) => (last, Some(it.into())),
| TypableDef::Const(_) ValueTyDefId::ConstId(it) => (last, Some(it.into())),
| TypableDef::Static(_) ValueTyDefId::StaticId(_) => (last, None),
| TypableDef::TypeAlias(_) ValueTyDefId::EnumVariantId(var) => {
| TypableDef::BuiltinType(_) => last,
TypableDef::EnumVariant(_) => {
// the generic args for an enum variant may be either specified // the generic args for an enum variant may be either specified
// on the segment referring to the enum, or on the segment // on the segment referring to the enum, or on the segment
// referring to the variant. So `Option::<T>::None` and // referring to the variant. So `Option::<T>::None` and
@ -334,10 +312,10 @@ impl Ty {
// Option::None::<T> // Option::None::<T>
last last
}; };
segment (segment, Some(var.parent.into()))
} }
}; };
Ty::substs_from_path_segment(db, resolver, segment, resolved) substs_from_path_segment(db, resolver, segment, generic_def, false)
} }
} }
@ -522,33 +500,6 @@ fn assoc_type_bindings_from_type_bound<'a>(
}) })
} }
/// Build the declared type of an item. This depends on the namespace; e.g. for
/// `struct Foo(usize)`, we have two types: The type of the struct itself, and
/// the constructor function `(usize) -> Foo` which lives in the values
/// namespace.
pub(crate) fn type_for_def(db: &impl HirDatabase, def: TypableDef, ns: Namespace) -> Ty {
match (def, ns) {
(TypableDef::Function(f), Namespace::Values) => type_for_fn(db, f),
(TypableDef::Adt(Adt::Struct(s)), Namespace::Values) => type_for_struct_constructor(db, s),
(TypableDef::Adt(adt), Namespace::Types) => type_for_adt(db, adt),
(TypableDef::EnumVariant(v), Namespace::Values) => type_for_enum_variant_constructor(db, v),
(TypableDef::TypeAlias(t), Namespace::Types) => type_for_type_alias(db, t),
(TypableDef::Const(c), Namespace::Values) => type_for_const(db, c),
(TypableDef::Static(c), Namespace::Values) => type_for_static(db, c),
(TypableDef::BuiltinType(t), Namespace::Types) => type_for_builtin(t),
// 'error' cases:
(TypableDef::Function(_), Namespace::Types) => Ty::Unknown,
(TypableDef::Adt(Adt::Union(_)), Namespace::Values) => Ty::Unknown,
(TypableDef::Adt(Adt::Enum(_)), Namespace::Values) => Ty::Unknown,
(TypableDef::EnumVariant(_), Namespace::Types) => Ty::Unknown,
(TypableDef::TypeAlias(_), Namespace::Values) => Ty::Unknown,
(TypableDef::Const(_), Namespace::Types) => Ty::Unknown,
(TypableDef::Static(_), Namespace::Types) => Ty::Unknown,
(TypableDef::BuiltinType(_), Namespace::Values) => Ty::Unknown,
}
}
/// Build the signature of a callable item (function, struct or enum variant). /// Build the signature of a callable item (function, struct or enum variant).
pub(crate) fn callable_item_sig(db: &impl HirDatabase, def: CallableDef) -> FnSig { pub(crate) fn callable_item_sig(db: &impl HirDatabase, def: CallableDef) -> FnSig {
match def { match def {
@ -647,24 +598,24 @@ fn fn_sig_for_fn(db: &impl HirDatabase, def: FunctionId) -> FnSig {
/// Build the declared type of a function. This should not need to look at the /// Build the declared type of a function. This should not need to look at the
/// function body. /// function body.
fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty { fn type_for_fn(db: &impl HirDatabase, def: FunctionId) -> Ty {
let generics = db.generic_params(def.id.into()); let generics = db.generic_params(def.into());
let substs = Substs::identity(&generics); let substs = Substs::identity(&generics);
Ty::apply(TypeCtor::FnDef(def.id.into()), substs) Ty::apply(TypeCtor::FnDef(def.into()), substs)
} }
/// Build the declared type of a const. /// Build the declared type of a const.
fn type_for_const(db: &impl HirDatabase, def: Const) -> Ty { fn type_for_const(db: &impl HirDatabase, def: ConstId) -> Ty {
let data = db.const_data(def.id); let data = db.const_data(def);
let resolver = def.id.resolver(db); let resolver = def.resolver(db);
Ty::from_hir(db, &resolver, &data.type_ref) Ty::from_hir(db, &resolver, &data.type_ref)
} }
/// Build the declared type of a static. /// Build the declared type of a static.
fn type_for_static(db: &impl HirDatabase, def: Static) -> Ty { fn type_for_static(db: &impl HirDatabase, def: StaticId) -> Ty {
let data = db.static_data(def.id); let data = db.static_data(def);
let resolver = def.id.resolver(db); let resolver = def.resolver(db);
Ty::from_hir(db, &resolver, &data.type_ref) Ty::from_hir(db, &resolver, &data.type_ref)
} }
@ -688,19 +639,19 @@ fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> FnSig
.iter() .iter()
.map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let ret = type_for_adt(db, Struct::from(def)); let ret = type_for_adt(db, def.into());
FnSig::from_params_and_return(params, ret) FnSig::from_params_and_return(params, ret)
} }
/// Build the type of a tuple struct constructor. /// Build the type of a tuple struct constructor.
fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty { fn type_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> Ty {
let struct_data = db.struct_data(def.id.into()); let struct_data = db.struct_data(def.into());
if struct_data.variant_data.is_unit() { if struct_data.variant_data.is_unit() {
return type_for_adt(db, def); // Unit struct return type_for_adt(db, def.into()); // Unit struct
} }
let generics = db.generic_params(def.id.into()); let generics = db.generic_params(def.into());
let substs = Substs::identity(&generics); let substs = Substs::identity(&generics);
Ty::apply(TypeCtor::FnDef(def.id.into()), substs) Ty::apply(TypeCtor::FnDef(def.into()), substs)
} }
fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) -> FnSig { fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) -> FnSig {
@ -714,34 +665,33 @@ fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let generics = db.generic_params(def.parent.into()); let generics = db.generic_params(def.parent.into());
let substs = Substs::identity(&generics); let substs = Substs::identity(&generics);
let ret = type_for_adt(db, Enum::from(def.parent)).subst(&substs); let ret = type_for_adt(db, def.parent.into()).subst(&substs);
FnSig::from_params_and_return(params, ret) FnSig::from_params_and_return(params, ret)
} }
/// Build the type of a tuple enum variant constructor. /// Build the type of a tuple enum variant constructor.
fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> Ty { fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) -> Ty {
let var_data = def.variant_data(db); let enum_data = db.enum_data(def.parent);
let var_data = &enum_data.variants[def.local_id].variant_data;
if var_data.is_unit() { if var_data.is_unit() {
return type_for_adt(db, def.parent_enum(db)); // Unit variant return type_for_adt(db, def.parent.into()); // Unit variant
} }
let generics = db.generic_params(def.parent_enum(db).id.into()); let generics = db.generic_params(def.parent.into());
let substs = Substs::identity(&generics); let substs = Substs::identity(&generics);
Ty::apply(TypeCtor::FnDef(EnumVariantId::from(def).into()), substs) Ty::apply(TypeCtor::FnDef(EnumVariantId::from(def).into()), substs)
} }
fn type_for_adt(db: &impl HirDatabase, adt: impl Into<Adt>) -> Ty { fn type_for_adt(db: &impl HirDatabase, adt: AdtId) -> Ty {
let adt = adt.into(); let generics = db.generic_params(adt.into());
let adt_id: AdtId = adt.into(); Ty::apply(TypeCtor::Adt(adt), Substs::identity(&generics))
let generics = db.generic_params(adt_id.into());
Ty::apply(TypeCtor::Adt(adt_id), Substs::identity(&generics))
} }
fn type_for_type_alias(db: &impl HirDatabase, t: TypeAlias) -> Ty { fn type_for_type_alias(db: &impl HirDatabase, t: TypeAliasId) -> Ty {
let generics = db.generic_params(t.id.into()); let generics = db.generic_params(t.into());
let resolver = t.id.resolver(db); let resolver = t.resolver(db);
let type_ref = t.type_ref(db); let type_ref = &db.type_alias_data(t).type_ref;
let substs = Substs::identity(&generics); let substs = Substs::identity(&generics);
let inner = Ty::from_hir(db, &resolver, &type_ref.unwrap_or(TypeRef::Error)); let inner = Ty::from_hir(db, &resolver, type_ref.as_ref().unwrap_or(&TypeRef::Error));
inner.subst(&substs) inner.subst(&substs)
} }
@ -808,3 +758,42 @@ impl From<CallableDef> for GenericDefId {
} }
} }
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum TyDefId {
BuiltinType(BuiltinType),
AdtId(AdtId),
TypeAliasId(TypeAliasId),
}
impl_froms!(TyDefId: BuiltinType, AdtId(StructId, EnumId, UnionId), TypeAliasId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ValueTyDefId {
FunctionId(FunctionId),
StructId(StructId),
EnumVariantId(EnumVariantId),
ConstId(ConstId),
StaticId(StaticId),
}
impl_froms!(ValueTyDefId: FunctionId, StructId, EnumVariantId, ConstId, StaticId);
/// Build the declared type of an item. This depends on the namespace; e.g. for
/// `struct Foo(usize)`, we have two types: The type of the struct itself, and
/// the constructor function `(usize) -> Foo` which lives in the values
/// namespace.
pub(crate) fn ty_query(db: &impl HirDatabase, def: TyDefId) -> Ty {
match def {
TyDefId::BuiltinType(it) => type_for_builtin(it),
TyDefId::AdtId(it) => type_for_adt(db, it),
TyDefId::TypeAliasId(it) => type_for_type_alias(db, it),
}
}
pub(crate) fn value_ty_query(db: &impl HirDatabase, def: ValueTyDefId) -> Ty {
match def {
ValueTyDefId::FunctionId(it) => type_for_fn(db, it),
ValueTyDefId::StructId(it) => type_for_struct_constructor(db, it),
ValueTyDefId::EnumVariantId(it) => type_for_enum_variant_constructor(db, it),
ValueTyDefId::ConstId(it) => type_for_const(db, it),
ValueTyDefId::StaticId(it) => type_for_static(db, it),
}
}

View file

@ -786,7 +786,7 @@ fn type_alias_associated_ty_value(
.expect("assoc ty value should not exist"); // validated when building the impl data as well .expect("assoc ty value should not exist"); // validated when building the impl data as well
let generic_params = db.generic_params(impl_block.id.into()); let generic_params = db.generic_params(impl_block.id.into());
let bound_vars = Substs::bound_vars(&generic_params); let bound_vars = Substs::bound_vars(&generic_params);
let ty = db.type_for_def(type_alias.into(), crate::ty::Namespace::Types).subst(&bound_vars); let ty = db.ty(type_alias.id.into()).subst(&bound_vars);
let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) }; let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) };
let value = chalk_rust_ir::AssociatedTyValue { let value = chalk_rust_ir::AssociatedTyValue {
impl_id, impl_id,

View file

@ -323,7 +323,8 @@ impl RootDatabase {
hir::db::DocumentationQuery hir::db::DocumentationQuery
hir::db::ExprScopesQuery hir::db::ExprScopesQuery
hir::db::InferQuery hir::db::InferQuery
hir::db::TypeForDefQuery hir::db::TyQuery
hir::db::ValueTyQuery
hir::db::FieldTypesQuery hir::db::FieldTypesQuery
hir::db::CallableItemSignatureQuery hir::db::CallableItemSignatureQuery
hir::db::GenericPredicatesQuery hir::db::GenericPredicatesQuery