From 5d54aa678153d0af0edc8b4dd2d74709d10ca66c Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 23 May 2019 20:18:47 +0300 Subject: add union to code_model --- crates/ra_hir/src/adt.rs | 7 +++++-- crates/ra_hir/src/code_model_api.rs | 38 ++++++++++++++++++++++++++++++++++ crates/ra_hir/src/generics.rs | 13 +++++++++--- crates/ra_hir/src/lib.rs | 2 +- crates/ra_hir/src/nameres/collector.rs | 6 +++++- crates/ra_hir/src/nameres/raw.rs | 19 +++++++++-------- crates/ra_hir/src/ty.rs | 1 + crates/ra_hir/src/ty/infer.rs | 21 ++++++++++++------- crates/ra_hir/src/ty/lower.rs | 10 +++++++-- 9 files changed, 91 insertions(+), 26 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs index e027eedd9..5e5905f15 100644 --- a/crates/ra_hir/src/adt.rs +++ b/crates/ra_hir/src/adt.rs @@ -10,7 +10,7 @@ use ra_syntax::{ }; use crate::{ - Name, AsName, Struct, Enum, EnumVariant, Crate, + Name, AsName, Struct, Union, Enum, EnumVariant, Crate, HirDatabase, HirFileId, StructField, FieldSource, type_ref::TypeRef, DefDatabase, }; @@ -18,14 +18,16 @@ use crate::{ #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum AdtDef { Struct(Struct), + Union(Union), Enum(Enum), } -impl_froms!(AdtDef: Struct, Enum); +impl_froms!(AdtDef: Struct, Union, Enum); impl AdtDef { pub(crate) fn krate(self, db: &impl HirDatabase) -> Option { match self { AdtDef::Struct(s) => s.module(db), + AdtDef::Union(s) => s.module(db), AdtDef::Enum(e) => e.module(db), } .krate(db) @@ -38,6 +40,7 @@ impl Struct { } } +/// Note that we use `StructData` for unions as well! #[derive(Debug, Clone, PartialEq, Eq)] pub struct StructData { pub(crate) name: Option, diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 0c4a80bfa..970b78412 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs @@ -71,6 +71,7 @@ pub enum ModuleDef { Module(Module), Function(Function), Struct(Struct), + Union(Union), Enum(Enum), // Can't be directly declared, but can be imported. EnumVariant(EnumVariant), @@ -83,6 +84,7 @@ impl_froms!( ModuleDef: Module, Function, Struct, + Union, Enum, EnumVariant, Const, @@ -325,6 +327,42 @@ impl Docs for Struct { } } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct Union { + pub(crate) id: StructId, +} + +impl Union { + pub fn source(&self, db: &impl DefDatabase) -> (HirFileId, TreeArc) { + self.id.source(db) + } + + pub fn name(&self, db: &impl HirDatabase) -> Option { + db.struct_data(Struct { id: self.id }).name.clone() + } + + pub fn module(&self, db: &impl HirDatabase) -> Module { + self.id.module(db) + } + + // FIXME move to a more general type + /// Builds a resolver for type references inside this union. + pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver { + // take the outer scope... + let r = self.module(db).resolver(db); + // ...and add generic params, if present + let p = self.generic_params(db); + let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r }; + r + } +} + +impl Docs for Union { + fn docs(&self, db: &impl HirDatabase) -> Option { + docs_from_ast(&*self.source(db).1) + } +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Enum { pub(crate) id: EnumId, diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs index 79a7fa23a..8effbbe35 100644 --- a/crates/ra_hir/src/generics.rs +++ b/crates/ra_hir/src/generics.rs @@ -9,7 +9,7 @@ use ra_syntax::ast::{self, NameOwner, TypeParamsOwner, TypeBoundsOwner, DefaultT use crate::{ db::{ HirDatabase, DefDatabase}, - Name, AsName, Function, Struct, Enum, Trait, TypeAlias, ImplBlock, Container, path::Path, type_ref::TypeRef, AdtDef + Name, AsName, Function, Struct, Union, Enum, Trait, TypeAlias, ImplBlock, Container, path::Path, type_ref::TypeRef, AdtDef }; /// Data about a generic parameter (to a function, struct, impl, ...). @@ -42,12 +42,13 @@ pub struct WherePredicate { pub enum GenericDef { Function(Function), Struct(Struct), + Union(Union), Enum(Enum), Trait(Trait), TypeAlias(TypeAlias), ImplBlock(ImplBlock), } -impl_froms!(GenericDef: Function, Struct, Enum, Trait, TypeAlias, ImplBlock); +impl_froms!(GenericDef: Function, Struct, Union, Enum, Trait, TypeAlias, ImplBlock); impl GenericParams { pub(crate) fn generic_params_query( @@ -58,7 +59,10 @@ impl GenericParams { let parent = match def { GenericDef::Function(it) => it.container(db).map(GenericDef::from), GenericDef::TypeAlias(it) => it.container(db).map(GenericDef::from), - GenericDef::Struct(_) | GenericDef::Enum(_) | GenericDef::Trait(_) => None, + GenericDef::Struct(_) + | GenericDef::Union(_) + | GenericDef::Enum(_) + | GenericDef::Trait(_) => None, GenericDef::ImplBlock(_) => None, }; generics.parent_params = parent.map(|p| db.generic_params(p)); @@ -66,6 +70,7 @@ impl GenericParams { match def { GenericDef::Function(it) => generics.fill(&*it.source(db).1, start), GenericDef::Struct(it) => generics.fill(&*it.source(db).1, start), + GenericDef::Union(it) => generics.fill(&*it.source(db).1, start), GenericDef::Enum(it) => generics.fill(&*it.source(db).1, start), GenericDef::Trait(it) => { // traits get the Self type as an implicit first type parameter @@ -171,6 +176,7 @@ impl GenericDef { match self { GenericDef::Function(inner) => inner.resolver(db), GenericDef::Struct(inner) => inner.resolver(db), + GenericDef::Union(inner) => inner.resolver(db), GenericDef::Enum(inner) => inner.resolver(db), GenericDef::Trait(inner) => inner.resolver(db), GenericDef::TypeAlias(inner) => inner.resolver(db), @@ -192,6 +198,7 @@ impl From for GenericDef { fn from(adt: crate::adt::AdtDef) -> Self { match adt { AdtDef::Struct(s) => s.into(), + AdtDef::Union(u) => u.into(), AdtDef::Enum(e) => e.into(), } } diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 0c6d7c2b7..0135644db 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -77,7 +77,7 @@ pub use self::code_model_api::{ Crate, CrateDependency, DefWithBody, Module, ModuleDef, ModuleSource, - Struct, Enum, EnumVariant, + Struct, Union, Enum, EnumVariant, Function, FnSignature, StructField, FieldSource, Static, Const, ConstSignature, diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs index c615d80c3..621236551 100644 --- a/crates/ra_hir/src/nameres/collector.rs +++ b/crates/ra_hir/src/nameres/collector.rs @@ -6,7 +6,7 @@ use ra_db::FileId; use ra_syntax::ast; use crate::{ - Function, Module, Struct, Enum, Const, Static, Trait, TypeAlias, + Function, Module, Struct, Union, Enum, Const, Static, Trait, TypeAlias, DefDatabase, HirFileId, Name, Path, KnownName, nameres::{ @@ -495,6 +495,10 @@ where let s = def!(Struct, ast_id); PerNs::both(s, s) } + raw::DefKind::Union(ast_id) => { + let s = def!(Union, ast_id); + PerNs::both(s, s) + } raw::DefKind::Enum(ast_id) => PerNs::types(def!(Enum, ast_id)), raw::DefKind::Const(ast_id) => PerNs::values(def!(Const, ast_id)), raw::DefKind::Static(ast_id) => PerNs::values(def!(Static, ast_id)), diff --git a/crates/ra_hir/src/nameres/raw.rs b/crates/ra_hir/src/nameres/raw.rs index bd32b264b..1b4dcbb7a 100644 --- a/crates/ra_hir/src/nameres/raw.rs +++ b/crates/ra_hir/src/nameres/raw.rs @@ -1,7 +1,4 @@ -use std::{ - sync::Arc, - ops::Index, -}; +use std::{sync::Arc, ops::Index}; use test_utils::tested_by; use ra_arena::{Arena, impl_arena_id, RawId, map::ArenaMap}; @@ -10,10 +7,7 @@ use ra_syntax::{ ast::{self, NameOwner, AttrsOwner}, }; -use crate::{ - DefDatabase, Name, AsName, Path, HirFileId, ModuleSource, - AstIdMap, FileAstId, Either, -}; +use crate::{DefDatabase, Name, AsName, Path, HirFileId, ModuleSource, AstIdMap, FileAstId, Either}; /// `RawItems` is a set of top-level items in a file (except for impls). /// @@ -161,6 +155,7 @@ pub(super) struct DefData { pub(super) enum DefKind { Function(FileAstId), Struct(FileAstId), + Union(FileAstId), Enum(FileAstId), Const(FileAstId), Static(FileAstId), @@ -215,7 +210,13 @@ impl RawItemsCollector { return; } ast::ModuleItemKind::StructDef(it) => { - (DefKind::Struct(self.source_ast_id_map.ast_id(it)), it.name()) + let id = self.source_ast_id_map.ast_id(it); + let name = it.name(); + if it.is_union() { + (DefKind::Union(id), name) + } else { + (DefKind::Struct(id), name) + } } ast::ModuleItemKind::EnumDef(it) => { (DefKind::Enum(self.source_ast_id_map.ast_id(it)), it.name()) diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 3679a2242..76d34c12b 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -536,6 +536,7 @@ impl HirDisplay for ApplicationTy { TypeCtor::Adt(def_id) => { let name = match def_id { AdtDef::Struct(s) => s.name(f.db), + AdtDef::Union(u) => u.name(f.db), AdtDef::Enum(e) => e.name(f.db), } .unwrap_or_else(Name::missing); diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index a48272981..7d8250292 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs @@ -27,13 +27,13 @@ use ra_prof::profile; use test_utils::tested_by; use crate::{ - Function, StructField, Path, Name, - FnSignature, AdtDef,ConstSignature, - HirDatabase, - DefWithBody, - ImplItem, + Function, StructField, Path, Name, FnSignature, AdtDef, ConstSignature, HirDatabase, + DefWithBody, ImplItem, type_ref::{TypeRef, Mutability}, - expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat,Array, self}, + expr::{ + Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, + FieldPat, Array, self, + }, generics::{GenericParams, HasGenericParams}, path::{GenericArgs, GenericArg}, ModuleDef, @@ -644,7 +644,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let ty = self.insert_type_vars(ty.apply_substs(substs)); (ty, Some(var.into())) } - TypableDef::TypeAlias(_) + TypableDef::Union(_) + | TypableDef::TypeAlias(_) | TypableDef::Function(_) | TypableDef::Enum(_) | TypableDef::Const(_) @@ -1407,7 +1408,11 @@ impl Expectation { } mod diagnostics { - use crate::{expr::ExprId, diagnostics::{DiagnosticSink, NoSuchField}, HirDatabase, Function}; + use crate::{ + expr::ExprId, + diagnostics::{DiagnosticSink, NoSuchField}, + HirDatabase, Function, +}; #[derive(Debug, PartialEq, Eq, Clone)] pub(super) enum InferenceDiagnostic { diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index a1a2d0f6b..7defa7a9b 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs @@ -9,7 +9,7 @@ use std::sync::Arc; use std::iter; use crate::{ - Function, Struct, StructField, Enum, EnumVariant, Path, ModuleDef, TypeAlias, Const, Static, + Function, Struct, Union, StructField, Enum, EnumVariant, Path, ModuleDef, TypeAlias, Const, Static, HirDatabase, type_ref::TypeRef, name::KnownName, @@ -124,6 +124,7 @@ impl Ty { let def_generic: Option = match resolved { TypableDef::Function(func) => Some(func.into()), TypableDef::Struct(s) => Some(s.into()), + TypableDef::Union(u) => Some(u.into()), TypableDef::Enum(e) => Some(e.into()), TypableDef::EnumVariant(var) => Some(var.parent_enum(db).into()), TypableDef::TypeAlias(t) => Some(t.into()), @@ -144,6 +145,7 @@ impl Ty { let segment = match resolved { TypableDef::Function(_) | TypableDef::Struct(_) + | TypableDef::Union(_) | TypableDef::Enum(_) | TypableDef::Const(_) | TypableDef::Static(_) @@ -293,12 +295,14 @@ pub(crate) fn type_for_def(db: &impl HirDatabase, def: TypableDef, ns: Namespace (TypableDef::Struct(s), Namespace::Values) => type_for_struct_constructor(db, s), (TypableDef::Enum(e), Namespace::Types) => type_for_adt(db, e), (TypableDef::EnumVariant(v), Namespace::Values) => type_for_enum_variant_constructor(db, v), + (TypableDef::Union(u), Namespace::Types) => type_for_adt(db, u), (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), // 'error' cases: (TypableDef::Function(_), Namespace::Types) => Ty::Unknown, + (TypableDef::Union(_), Namespace::Values) => Ty::Unknown, (TypableDef::Enum(_), Namespace::Values) => Ty::Unknown, (TypableDef::EnumVariant(_), Namespace::Types) => Ty::Unknown, (TypableDef::TypeAlias(_), Namespace::Values) => Ty::Unknown, @@ -467,19 +471,21 @@ fn type_for_type_alias(db: &impl HirDatabase, t: TypeAlias) -> Ty { pub enum TypableDef { Function(Function), Struct(Struct), + Union(Union), Enum(Enum), EnumVariant(EnumVariant), TypeAlias(TypeAlias), Const(Const), Static(Static), } -impl_froms!(TypableDef: Function, Struct, Enum, EnumVariant, TypeAlias, Const, Static); +impl_froms!(TypableDef: Function, Struct, Union, Enum, EnumVariant, TypeAlias, Const, Static); impl From for Option { fn from(def: ModuleDef) -> Option { let res = match def { ModuleDef::Function(f) => f.into(), ModuleDef::Struct(s) => s.into(), + ModuleDef::Union(u) => u.into(), ModuleDef::Enum(e) => e.into(), ModuleDef::EnumVariant(v) => v.into(), ModuleDef::TypeAlias(t) => t.into(), -- cgit v1.2.3