aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty/lower.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/ty/lower.rs')
-rw-r--r--crates/ra_hir/src/ty/lower.rs204
1 files changed, 96 insertions, 108 deletions
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index 805a73ff5..709492d21 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -14,8 +14,8 @@ use hir_def::{
14 path::{GenericArg, PathSegment}, 14 path::{GenericArg, PathSegment},
15 resolver::{HasResolver, Resolver, TypeNs}, 15 resolver::{HasResolver, Resolver, TypeNs},
16 type_ref::{TypeBound, TypeRef}, 16 type_ref::{TypeBound, TypeRef},
17 AdtId, AstItemDef, EnumVariantId, FunctionId, GenericDefId, HasModule, LocalStructFieldId, 17 AdtId, AstItemDef, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule,
18 Lookup, StructId, VariantId, 18 LocalStructFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, UnionId, VariantId,
19}; 19};
20use ra_arena::map::ArenaMap; 20use ra_arena::map::ArenaMap;
21use ra_db::CrateId; 21use ra_db::CrateId;
@@ -29,24 +29,12 @@ use crate::{
29 ty::{ 29 ty::{
30 primitive::{FloatTy, IntTy}, 30 primitive::{FloatTy, IntTy},
31 utils::{all_super_traits, associated_type_by_name_including_super_traits}, 31 utils::{all_super_traits, associated_type_by_name_including_super_traits},
32 Adt,
33 }, 32 },
34 util::make_mut_slice, 33 util::make_mut_slice,
35 Const, Enum, EnumVariant, Function, ImplBlock, ModuleDef, Path, Static, Struct, Trait, 34 Adt, Const, Enum, EnumVariant, Function, ImplBlock, ModuleDef, Path, Static, Struct, Trait,
36 TypeAlias, Union, 35 TypeAlias, Union,
37}; 36};
38 37
39// FIXME: this is only really used in `type_for_def`, which contains a bunch of
40// impossible cases. Perhaps we should recombine `TypeableDef` and `Namespace`
41// into a `AsTypeDef`, `AsValueDef` enums?
42#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
43pub enum Namespace {
44 Types,
45 Values,
46 // Note that only type inference uses this enum, and it doesn't care about macros.
47 // Macro,
48}
49
50impl Ty { 38impl Ty {
51 pub(crate) fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &TypeRef) -> Self { 39 pub(crate) fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &TypeRef) -> Self {
52 match type_ref { 40 match type_ref {
@@ -172,7 +160,7 @@ impl Ty {
172 let segment = &remaining_segments[0]; 160 let segment = &remaining_segments[0];
173 let associated_ty = associated_type_by_name_including_super_traits( 161 let associated_ty = associated_type_by_name_including_super_traits(
174 db, 162 db,
175 trait_ref.trait_.id, 163 trait_ref.trait_,
176 &segment.name, 164 &segment.name,
177 ); 165 );
178 match associated_ty { 166 match associated_ty {
@@ -263,7 +251,7 @@ impl Ty {
263 GenericPredicate::Implemented(tr) if tr.self_ty() == &self_ty => Some(tr.trait_), 251 GenericPredicate::Implemented(tr) if tr.self_ty() == &self_ty => Some(tr.trait_),
264 _ => None, 252 _ => None,
265 }); 253 });
266 let traits = traits_from_env.flat_map(|t| all_super_traits(db, t.id)).map(Trait::from); 254 let traits = traits_from_env.flat_map(|t| all_super_traits(db, t)).map(Trait::from);
267 for t in traits { 255 for t in traits {
268 if let Some(associated_ty) = db.trait_data(t.id).associated_type_by_name(&segment.name) 256 if let Some(associated_ty) = db.trait_data(t.id).associated_type_by_name(&segment.name)
269 { 257 {
@@ -282,27 +270,15 @@ impl Ty {
282 db: &impl HirDatabase, 270 db: &impl HirDatabase,
283 resolver: &Resolver, 271 resolver: &Resolver,
284 segment: &PathSegment, 272 segment: &PathSegment,
285 typable: TypableDef, 273 typable: TyDefId,
286 ) -> Ty { 274 ) -> Ty {
287 let ty = db.type_for_def(typable, Namespace::Types); 275 let generic_def = match typable {
288 let substs = Ty::substs_from_path_segment(db, resolver, segment, typable); 276 TyDefId::BuiltinType(_) => None,
289 ty.subst(&substs) 277 TyDefId::AdtId(it) => Some(it.into()),
290 } 278 TyDefId::TypeAliasId(it) => Some(it.into()),
291
292 pub(super) fn substs_from_path_segment(
293 db: &impl HirDatabase,
294 resolver: &Resolver,
295 segment: &PathSegment,
296 resolved: TypableDef,
297 ) -> Substs {
298 let def_generic: Option<GenericDefId> = match resolved {
299 TypableDef::Function(func) => Some(func.id.into()),
300 TypableDef::Adt(adt) => Some(adt.into()),
301 TypableDef::EnumVariant(var) => Some(var.parent_enum(db).id.into()),
302 TypableDef::TypeAlias(t) => Some(t.id.into()),
303 TypableDef::Const(_) | TypableDef::Static(_) | TypableDef::BuiltinType(_) => None,
304 }; 279 };
305 substs_from_path_segment(db, resolver, segment, def_generic, false) 280 let substs = substs_from_path_segment(db, resolver, segment, generic_def, false);
281 db.ty(typable).subst(&substs)
306 } 282 }
307 283
308 /// Collect generic arguments from a path into a `Substs`. See also 284 /// Collect generic arguments from a path into a `Substs`. See also
@@ -311,17 +287,18 @@ impl Ty {
311 db: &impl HirDatabase, 287 db: &impl HirDatabase,
312 resolver: &Resolver, 288 resolver: &Resolver,
313 path: &Path, 289 path: &Path,
314 resolved: TypableDef, 290 // Note that we don't call `db.value_type(resolved)` here,
291 // `ValueTyDefId` is just a convenient way to pass generics and
292 // special-case enum variants
293 resolved: ValueTyDefId,
315 ) -> Substs { 294 ) -> Substs {
316 let last = path.segments.last().expect("path should have at least one segment"); 295 let last = path.segments.last().expect("path should have at least one segment");
317 let segment = match resolved { 296 let (segment, generic_def) = match resolved {
318 TypableDef::Function(_) 297 ValueTyDefId::FunctionId(it) => (last, Some(it.into())),
319 | TypableDef::Adt(_) 298 ValueTyDefId::StructId(it) => (last, Some(it.into())),
320 | TypableDef::Const(_) 299 ValueTyDefId::ConstId(it) => (last, Some(it.into())),
321 | TypableDef::Static(_) 300 ValueTyDefId::StaticId(_) => (last, None),
322 | TypableDef::TypeAlias(_) 301 ValueTyDefId::EnumVariantId(var) => {
323 | TypableDef::BuiltinType(_) => last,
324 TypableDef::EnumVariant(_) => {
325 // the generic args for an enum variant may be either specified 302 // the generic args for an enum variant may be either specified
326 // on the segment referring to the enum, or on the segment 303 // on the segment referring to the enum, or on the segment
327 // referring to the variant. So `Option::<T>::None` and 304 // referring to the variant. So `Option::<T>::None` and
@@ -335,10 +312,10 @@ impl Ty {
335 // Option::None::<T> 312 // Option::None::<T>
336 last 313 last
337 }; 314 };
338 segment 315 (segment, Some(var.parent.into()))
339 } 316 }
340 }; 317 };
341 Ty::substs_from_path_segment(db, resolver, segment, resolved) 318 substs_from_path_segment(db, resolver, segment, generic_def, false)
342 } 319 }
343} 320}
344 321
@@ -423,7 +400,7 @@ impl TraitRef {
423 if let Some(self_ty) = explicit_self_ty { 400 if let Some(self_ty) = explicit_self_ty {
424 make_mut_slice(&mut substs.0)[0] = self_ty; 401 make_mut_slice(&mut substs.0)[0] = self_ty;
425 } 402 }
426 TraitRef { trait_: resolved, substs } 403 TraitRef { trait_: resolved.id, substs }
427 } 404 }
428 405
429 pub(crate) fn from_hir( 406 pub(crate) fn from_hir(
@@ -450,8 +427,8 @@ impl TraitRef {
450 substs_from_path_segment(db, resolver, segment, Some(resolved.id.into()), !has_self_param) 427 substs_from_path_segment(db, resolver, segment, Some(resolved.id.into()), !has_self_param)
451 } 428 }
452 429
453 pub(crate) fn for_trait(db: &impl HirDatabase, trait_: Trait) -> TraitRef { 430 pub(crate) fn for_trait(db: &impl HirDatabase, trait_: TraitId) -> TraitRef {
454 let substs = Substs::identity(&db.generic_params(trait_.id.into())); 431 let substs = Substs::identity(&db.generic_params(trait_.into()));
455 TraitRef { trait_, substs } 432 TraitRef { trait_, substs }
456 } 433 }
457 434
@@ -510,7 +487,7 @@ fn assoc_type_bindings_from_type_bound<'a>(
510 .flat_map(|args_and_bindings| args_and_bindings.bindings.iter()) 487 .flat_map(|args_and_bindings| args_and_bindings.bindings.iter())
511 .map(move |(name, type_ref)| { 488 .map(move |(name, type_ref)| {
512 let associated_ty = 489 let associated_ty =
513 associated_type_by_name_including_super_traits(db, trait_ref.trait_.id, &name); 490 associated_type_by_name_including_super_traits(db, trait_ref.trait_, &name);
514 let associated_ty = match associated_ty { 491 let associated_ty = match associated_ty {
515 None => return GenericPredicate::Error, 492 None => return GenericPredicate::Error,
516 Some(t) => t, 493 Some(t) => t,
@@ -523,33 +500,6 @@ fn assoc_type_bindings_from_type_bound<'a>(
523 }) 500 })
524} 501}
525 502
526/// Build the declared type of an item. This depends on the namespace; e.g. for
527/// `struct Foo(usize)`, we have two types: The type of the struct itself, and
528/// the constructor function `(usize) -> Foo` which lives in the values
529/// namespace.
530pub(crate) fn type_for_def(db: &impl HirDatabase, def: TypableDef, ns: Namespace) -> Ty {
531 match (def, ns) {
532 (TypableDef::Function(f), Namespace::Values) => type_for_fn(db, f),
533 (TypableDef::Adt(Adt::Struct(s)), Namespace::Values) => type_for_struct_constructor(db, s),
534 (TypableDef::Adt(adt), Namespace::Types) => type_for_adt(db, adt),
535 (TypableDef::EnumVariant(v), Namespace::Values) => type_for_enum_variant_constructor(db, v),
536 (TypableDef::TypeAlias(t), Namespace::Types) => type_for_type_alias(db, t),
537 (TypableDef::Const(c), Namespace::Values) => type_for_const(db, c),
538 (TypableDef::Static(c), Namespace::Values) => type_for_static(db, c),
539 (TypableDef::BuiltinType(t), Namespace::Types) => type_for_builtin(t),
540
541 // 'error' cases:
542 (TypableDef::Function(_), Namespace::Types) => Ty::Unknown,
543 (TypableDef::Adt(Adt::Union(_)), Namespace::Values) => Ty::Unknown,
544 (TypableDef::Adt(Adt::Enum(_)), Namespace::Values) => Ty::Unknown,
545 (TypableDef::EnumVariant(_), Namespace::Types) => Ty::Unknown,
546 (TypableDef::TypeAlias(_), Namespace::Values) => Ty::Unknown,
547 (TypableDef::Const(_), Namespace::Types) => Ty::Unknown,
548 (TypableDef::Static(_), Namespace::Types) => Ty::Unknown,
549 (TypableDef::BuiltinType(_), Namespace::Values) => Ty::Unknown,
550 }
551}
552
553/// Build the signature of a callable item (function, struct or enum variant). 503/// Build the signature of a callable item (function, struct or enum variant).
554pub(crate) fn callable_item_sig(db: &impl HirDatabase, def: CallableDef) -> FnSig { 504pub(crate) fn callable_item_sig(db: &impl HirDatabase, def: CallableDef) -> FnSig {
555 match def { 505 match def {
@@ -648,24 +598,24 @@ fn fn_sig_for_fn(db: &impl HirDatabase, def: FunctionId) -> FnSig {
648 598
649/// Build the declared type of a function. This should not need to look at the 599/// Build the declared type of a function. This should not need to look at the
650/// function body. 600/// function body.
651fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty { 601fn type_for_fn(db: &impl HirDatabase, def: FunctionId) -> Ty {
652 let generics = db.generic_params(def.id.into()); 602 let generics = db.generic_params(def.into());
653 let substs = Substs::identity(&generics); 603 let substs = Substs::identity(&generics);
654 Ty::apply(TypeCtor::FnDef(def.id.into()), substs) 604 Ty::apply(TypeCtor::FnDef(def.into()), substs)
655} 605}
656 606
657/// Build the declared type of a const. 607/// Build the declared type of a const.
658fn type_for_const(db: &impl HirDatabase, def: Const) -> Ty { 608fn type_for_const(db: &impl HirDatabase, def: ConstId) -> Ty {
659 let data = db.const_data(def.id); 609 let data = db.const_data(def);
660 let resolver = def.id.resolver(db); 610 let resolver = def.resolver(db);
661 611
662 Ty::from_hir(db, &resolver, &data.type_ref) 612 Ty::from_hir(db, &resolver, &data.type_ref)
663} 613}
664 614
665/// Build the declared type of a static. 615/// Build the declared type of a static.
666fn type_for_static(db: &impl HirDatabase, def: Static) -> Ty { 616fn type_for_static(db: &impl HirDatabase, def: StaticId) -> Ty {
667 let data = db.static_data(def.id); 617 let data = db.static_data(def);
668 let resolver = def.id.resolver(db); 618 let resolver = def.resolver(db);
669 619
670 Ty::from_hir(db, &resolver, &data.type_ref) 620 Ty::from_hir(db, &resolver, &data.type_ref)
671} 621}
@@ -689,19 +639,19 @@ fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> FnSig
689 .iter() 639 .iter()
690 .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) 640 .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref))
691 .collect::<Vec<_>>(); 641 .collect::<Vec<_>>();
692 let ret = type_for_adt(db, Struct::from(def)); 642 let ret = type_for_adt(db, def.into());
693 FnSig::from_params_and_return(params, ret) 643 FnSig::from_params_and_return(params, ret)
694} 644}
695 645
696/// Build the type of a tuple struct constructor. 646/// Build the type of a tuple struct constructor.
697fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty { 647fn type_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> Ty {
698 let struct_data = db.struct_data(def.id.into()); 648 let struct_data = db.struct_data(def.into());
699 if struct_data.variant_data.is_unit() { 649 if struct_data.variant_data.is_unit() {
700 return type_for_adt(db, def); // Unit struct 650 return type_for_adt(db, def.into()); // Unit struct
701 } 651 }
702 let generics = db.generic_params(def.id.into()); 652 let generics = db.generic_params(def.into());
703 let substs = Substs::identity(&generics); 653 let substs = Substs::identity(&generics);
704 Ty::apply(TypeCtor::FnDef(def.id.into()), substs) 654 Ty::apply(TypeCtor::FnDef(def.into()), substs)
705} 655}
706 656
707fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) -> FnSig { 657fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) -> FnSig {
@@ -715,34 +665,33 @@ fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId
715 .collect::<Vec<_>>(); 665 .collect::<Vec<_>>();
716 let generics = db.generic_params(def.parent.into()); 666 let generics = db.generic_params(def.parent.into());
717 let substs = Substs::identity(&generics); 667 let substs = Substs::identity(&generics);
718 let ret = type_for_adt(db, Enum::from(def.parent)).subst(&substs); 668 let ret = type_for_adt(db, def.parent.into()).subst(&substs);
719 FnSig::from_params_and_return(params, ret) 669 FnSig::from_params_and_return(params, ret)
720} 670}
721 671
722/// Build the type of a tuple enum variant constructor. 672/// Build the type of a tuple enum variant constructor.
723fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> Ty { 673fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) -> Ty {
724 let var_data = def.variant_data(db); 674 let enum_data = db.enum_data(def.parent);
675 let var_data = &enum_data.variants[def.local_id].variant_data;
725 if var_data.is_unit() { 676 if var_data.is_unit() {
726 return type_for_adt(db, def.parent_enum(db)); // Unit variant 677 return type_for_adt(db, def.parent.into()); // Unit variant
727 } 678 }
728 let generics = db.generic_params(def.parent_enum(db).id.into()); 679 let generics = db.generic_params(def.parent.into());
729 let substs = Substs::identity(&generics); 680 let substs = Substs::identity(&generics);
730 Ty::apply(TypeCtor::FnDef(EnumVariantId::from(def).into()), substs) 681 Ty::apply(TypeCtor::FnDef(EnumVariantId::from(def).into()), substs)
731} 682}
732 683
733fn type_for_adt(db: &impl HirDatabase, adt: impl Into<Adt>) -> Ty { 684fn type_for_adt(db: &impl HirDatabase, adt: AdtId) -> Ty {
734 let adt = adt.into(); 685 let generics = db.generic_params(adt.into());
735 let adt_id: AdtId = adt.into(); 686 Ty::apply(TypeCtor::Adt(adt), Substs::identity(&generics))
736 let generics = db.generic_params(adt_id.into());
737 Ty::apply(TypeCtor::Adt(adt_id), Substs::identity(&generics))
738} 687}
739 688
740fn type_for_type_alias(db: &impl HirDatabase, t: TypeAlias) -> Ty { 689fn type_for_type_alias(db: &impl HirDatabase, t: TypeAliasId) -> Ty {
741 let generics = db.generic_params(t.id.into()); 690 let generics = db.generic_params(t.into());
742 let resolver = t.id.resolver(db); 691 let resolver = t.resolver(db);
743 let type_ref = t.type_ref(db); 692 let type_ref = &db.type_alias_data(t).type_ref;
744 let substs = Substs::identity(&generics); 693 let substs = Substs::identity(&generics);
745 let inner = Ty::from_hir(db, &resolver, &type_ref.unwrap_or(TypeRef::Error)); 694 let inner = Ty::from_hir(db, &resolver, type_ref.as_ref().unwrap_or(&TypeRef::Error));
746 inner.subst(&substs) 695 inner.subst(&substs)
747} 696}
748 697
@@ -809,3 +758,42 @@ impl From<CallableDef> for GenericDefId {
809 } 758 }
810 } 759 }
811} 760}
761
762#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
763pub enum TyDefId {
764 BuiltinType(BuiltinType),
765 AdtId(AdtId),
766 TypeAliasId(TypeAliasId),
767}
768impl_froms!(TyDefId: BuiltinType, AdtId(StructId, EnumId, UnionId), TypeAliasId);
769
770#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
771pub enum ValueTyDefId {
772 FunctionId(FunctionId),
773 StructId(StructId),
774 EnumVariantId(EnumVariantId),
775 ConstId(ConstId),
776 StaticId(StaticId),
777}
778impl_froms!(ValueTyDefId: FunctionId, StructId, EnumVariantId, ConstId, StaticId);
779
780/// Build the declared type of an item. This depends on the namespace; e.g. for
781/// `struct Foo(usize)`, we have two types: The type of the struct itself, and
782/// the constructor function `(usize) -> Foo` which lives in the values
783/// namespace.
784pub(crate) fn ty_query(db: &impl HirDatabase, def: TyDefId) -> Ty {
785 match def {
786 TyDefId::BuiltinType(it) => type_for_builtin(it),
787 TyDefId::AdtId(it) => type_for_adt(db, it),
788 TyDefId::TypeAliasId(it) => type_for_type_alias(db, it),
789 }
790}
791pub(crate) fn value_ty_query(db: &impl HirDatabase, def: ValueTyDefId) -> Ty {
792 match def {
793 ValueTyDefId::FunctionId(it) => type_for_fn(db, it),
794 ValueTyDefId::StructId(it) => type_for_struct_constructor(db, it),
795 ValueTyDefId::EnumVariantId(it) => type_for_enum_variant_constructor(db, it),
796 ValueTyDefId::ConstId(it) => type_for_const(db, it),
797 ValueTyDefId::StaticId(it) => type_for_static(db, it),
798 }
799}