Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions crates/mun_codegen/src/ir/body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1326,9 +1326,7 @@ impl<'db, 'ink, 't> BodyIrGenerator<'db, 'ink, 't> {
let field_idx = hir_struct
.field(self.db, name)
.expect("expected a struct field")
.id()
.into_raw()
.into();
.index(self.db);

let field_ir_name = &format!("{}.{}", hir_struct_name, name);
if self.is_place_expr(receiver_expr) {
Expand Down Expand Up @@ -1383,9 +1381,7 @@ impl<'db, 'ink, 't> BodyIrGenerator<'db, 'ink, 't> {
let field_idx = hir_struct
.field(self.db, name)
.expect("expected a struct field")
.id()
.into_raw()
.into();
.index(self.db);

let receiver_ptr = self.gen_place_expr(receiver_expr);
let receiver_ptr = self
Expand Down
3 changes: 2 additions & 1 deletion crates/mun_hir/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ ena = "0.14"
drop_bomb = "0.1.4"
either = "1.5.3"
itertools = "0.10.0"
smallvec = "1.4.2"
smallvec = "1.6.1"
arrayvec = "0.5.2"

[dev-dependencies]
insta = "0.16"
Expand Down
9 changes: 5 additions & 4 deletions crates/mun_hir/src/code_model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@ pub use self::{
function::Function,
module::{Module, ModuleDef},
package::Package,
r#struct::{LocalStructFieldId, Struct, StructField, StructKind, StructMemoryKind},
r#struct::{Field, LocalFieldId, Struct, StructKind, StructMemoryKind},
src::HasSource,
type_alias::TypeAlias,
};

pub use self::{
function::FunctionData,
r#struct::{StructData, StructFieldData},
r#struct::{FieldData, StructData},
type_alias::TypeAliasData,
};

Expand Down Expand Up @@ -57,13 +58,13 @@ impl DefWithStruct {
}
}

pub fn fields(self, db: &dyn HirDatabase) -> Vec<StructField> {
pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
match self {
DefWithStruct::Struct(s) => s.fields(db),
}
}

pub fn field(self, db: &dyn HirDatabase, name: &Name) -> Option<StructField> {
pub fn field(self, db: &dyn HirDatabase, name: &Name) -> Option<Field> {
match self {
DefWithStruct::Struct(s) => s.field(db, name),
}
Expand Down
6 changes: 6 additions & 0 deletions crates/mun_hir/src/code_model/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,12 @@ impl Function {
db.type_for_def(self.into(), Namespace::Values).0
}

pub fn ret_type(self, db: &dyn HirDatabase) -> Ty {
let resolver = self.id.resolver(db.upcast());
let data = self.data(db.upcast());
Ty::from_hir(db, &resolver, &data.type_ref_map, data.ret_type).ty
}

pub fn infer(self, db: &dyn HirDatabase) -> Arc<InferenceResult> {
db.infer(self.id.into())
}
Expand Down
8 changes: 6 additions & 2 deletions crates/mun_hir/src/code_model/src.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
use crate::code_model::{Function, Struct, StructField, TypeAlias};
use crate::code_model::{Field, Function, Struct, TypeAlias};
use crate::ids::{AssocItemLoc, Lookup};
use crate::in_file::InFile;
use crate::item_tree::{ItemTreeId, ItemTreeNode};
use crate::{DefDatabase, ItemLoc};
use mun_syntax::ast;

/// A trait implemented for items that can be related back to their source. The
/// [`HasSource::source`] method returns the source location of its instance.
pub trait HasSource {
type Ast;

/// Returns the source location of this instance.
fn source(&self, db: &dyn DefDatabase) -> InFile<Self::Ast>;
}

Expand Down Expand Up @@ -56,7 +60,7 @@ impl HasSource for Struct {
}
}

impl HasSource for StructField {
impl HasSource for Field {
type Ast = ast::RecordFieldDef;

fn source(&self, db: &dyn DefDatabase) -> InFile<Self::Ast> {
Expand Down
35 changes: 22 additions & 13 deletions crates/mun_hir/src/code_model/struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,25 +31,34 @@ impl From<StructId> for Struct {
}
}

/// A field of a [`Struct`].
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct StructField {
pub struct Field {
pub(crate) parent: Struct,
pub(crate) id: LocalStructFieldId,
pub(crate) id: LocalFieldId,
}

impl StructField {
impl Field {
/// Returns the type of the field
pub fn ty(self, db: &dyn HirDatabase) -> Ty {
let data = self.parent.data(db.upcast());
let type_ref_id = data.fields[self.id].type_ref;
let lower = self.parent.lower(db);
lower[type_ref_id].clone()
}

/// Returns the name of the field
pub fn name(self, db: &dyn HirDatabase) -> Name {
self.parent.data(db.upcast()).fields[self.id].name.clone()
}

pub fn id(self) -> LocalStructFieldId {
/// Returns the index of this field in the parent
pub fn index(self, _db: &dyn HirDatabase) -> u32 {
self.id.into_raw().into()
}

/// Returns the ID of the field with relation to the parent struct
pub(crate) fn id(self) -> LocalFieldId {
self.id
}
}
Expand Down Expand Up @@ -86,20 +95,20 @@ impl Struct {
.collect()
}

pub fn fields(self, db: &dyn HirDatabase) -> Vec<StructField> {
pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
self.data(db.upcast())
.fields
.iter()
.map(|(id, _)| StructField { parent: self, id })
.map(|(id, _)| Field { parent: self, id })
.collect()
}

pub fn field(self, db: &dyn HirDatabase, name: &Name) -> Option<StructField> {
pub fn field(self, db: &dyn HirDatabase, name: &Name) -> Option<Field> {
self.data(db.upcast())
.fields
.iter()
.find(|(_, data)| data.name == *name)
.map(|(id, _)| StructField { parent: self, id })
.map(|(id, _)| Field { parent: self, id })
}

pub fn ty(self, db: &dyn HirDatabase) -> Ty {
Expand Down Expand Up @@ -131,7 +140,7 @@ impl Struct {
/// )
/// ```
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct StructFieldData {
pub struct FieldData {
pub name: Name,
pub type_ref: LocalTypeRefId,
}
Expand All @@ -155,13 +164,13 @@ impl fmt::Display for StructKind {
}

/// An identifier for a struct's or tuple's field
pub type LocalStructFieldId = Idx<StructFieldData>;
pub type LocalFieldId = Idx<FieldData>;

#[derive(Debug, PartialEq, Eq)]
pub struct StructData {
pub name: Name,
pub visibility: RawVisibility,
pub fields: Arena<StructFieldData>,
pub fields: Arena<FieldData>,
pub kind: StructKind,
pub memory_kind: StructMemoryKind,
type_ref_map: TypeRefMap,
Expand All @@ -185,7 +194,7 @@ impl StructData {
ast::StructKind::Record(r) => {
let fields = r
.fields()
.map(|fd| StructFieldData {
.map(|fd| FieldData {
name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing),
type_ref: type_ref_builder.alloc_from_node_opt(fd.ascribed_type().as_ref()),
})
Expand All @@ -196,7 +205,7 @@ impl StructData {
let fields = t
.fields()
.enumerate()
.map(|(index, fd)| StructFieldData {
.map(|(index, fd)| FieldData {
name: Name::new_tuple_field(index),
type_ref: type_ref_builder.alloc_from_node_opt(fd.type_ref().as_ref()),
})
Expand Down
7 changes: 4 additions & 3 deletions crates/mun_hir/src/item_scope.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::module_tree::LocalModuleId;
use crate::primitive_type::PrimitiveType;
use crate::{ids::ItemDefinitionId, visibility::Visibility, Name, PerNs};
use crate::{
ids::ItemDefinitionId, module_tree::LocalModuleId, primitive_type::PrimitiveType,
visibility::Visibility, Name, PerNs,
};
use once_cell::sync::Lazy;
use rustc_hash::{FxHashMap, FxHashSet};
use std::collections::hash_map::Entry;
Expand Down
5 changes: 1 addition & 4 deletions crates/mun_hir/src/item_tree/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,7 @@ impl Context {
ast::ModuleItemKind::StructDef(ast) => self.lower_struct(&ast).map(Into::into),
ast::ModuleItemKind::TypeAliasDef(ast) => self.lower_type_alias(&ast).map(Into::into),
ast::ModuleItemKind::Use(ast) => Some(ModItems(
self.lower_use(&ast)
.into_iter()
.map(Into::into)
.collect::<SmallVec<_>>(),
self.lower_use(&ast).into_iter().map(Into::into).collect(),
)),
}
}
Expand Down
5 changes: 4 additions & 1 deletion crates/mun_hir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ pub use crate::{
use crate::{name::AsName, source_id::AstIdMap};

pub use self::code_model::{
Function, FunctionData, Module, ModuleDef, Package, Struct, StructMemoryKind, TypeAlias,
Field, Function, FunctionData, HasSource, Module, ModuleDef, Package, Struct, StructMemoryKind,
TypeAlias,
};

#[macro_use]
Expand Down Expand Up @@ -71,6 +72,8 @@ mod item_scope;
mod mock;
mod package_defs;
mod package_set;
pub mod semantics;
mod source_analyzer;
#[cfg(test)]
mod tests;
mod visibility;
Expand Down
45 changes: 44 additions & 1 deletion crates/mun_hir/src/resolve.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use crate::ids::{
DefWithBodyId, FunctionId, ItemDefinitionId, Lookup, ModuleId, StructId, TypeAliasId,
};
use crate::item_scope::BUILTIN_SCOPE;
use crate::module_tree::LocalModuleId;
use crate::package_defs::PackageDefs;
use crate::primitive_type::PrimitiveType;
use crate::visibility::RawVisibility;
use crate::{
expr::scope::LocalScopeId, expr::PatId, DefDatabase, ExprId, ExprScopes, Path, PerNs,
expr::scope::LocalScopeId, expr::PatId, DefDatabase, ExprId, ExprScopes, Name, Path, PerNs,
Visibility,
};
use std::sync::Arc;
Expand Down Expand Up @@ -58,6 +59,12 @@ pub enum TypeNs {
PrimitiveType(PrimitiveType),
}

/// An item definition visible from a certain scope.
pub enum ScopeDef {
PerNs(PerNs<(ItemDefinitionId, Visibility)>),
Local(PatId),
}

impl Resolver {
/// Adds another scope to the resolver from which it can resolve names
pub(crate) fn push_scope(mut self, scope: Scope) -> Resolver {
Expand Down Expand Up @@ -273,6 +280,42 @@ impl Resolver {
local_id,
})
}

/// If the resolver holds a scope from a body, returns that body.
pub fn body_owner(&self) -> Option<DefWithBodyId> {
self.scopes.iter().rev().find_map(|scope| match scope {
Scope::ExprScope(it) => Some(it.owner),
_ => None,
})
}

/// Calls the `visitor` for each entry in scope.
pub fn visit_all_names(&self, db: &dyn DefDatabase, visitor: &mut dyn FnMut(Name, ScopeDef)) {
for scope in self.scopes.iter().rev() {
scope.visit_names(db, visitor)
}
}
}

impl Scope {
/// Calls the `visitor` for each entry in scope.
fn visit_names(&self, _db: &dyn DefDatabase, visitor: &mut dyn FnMut(Name, ScopeDef)) {
match self {
Scope::ModuleScope(m) => {
m.package_defs[m.module_id]
.entries()
.for_each(|(name, def)| visitor(name.clone(), ScopeDef::PerNs(def)));
BUILTIN_SCOPE.iter().for_each(|(name, &def)| {
visitor(name.clone(), ScopeDef::PerNs(def));
})
}
Scope::ExprScope(scope) => scope
.expr_scopes
.entries(scope.scope_id)
.iter()
.for_each(|entry| visitor(entry.name().clone(), ScopeDef::Local(entry.pat()))),
}
}
}

/// Returns a resolver applicable to the specified expression
Expand Down
Loading