Skip to content

Commit

Permalink
Add structs to the declaration engine (FuelLabs#2688)
Browse files Browse the repository at this point in the history
Add structs declarations to the declaration engine.
  • Loading branch information
tritao authored Sep 9, 2022
1 parent 057e83a commit 719dca1
Show file tree
Hide file tree
Showing 12 changed files with 123 additions and 39 deletions.
15 changes: 8 additions & 7 deletions sway-core/src/control_flow_analysis/dead_code_analysis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,13 +170,13 @@ impl ControlFlowGraph {
ControlFlowGraphNode::ProgramNode(TypedAstNode {
content:
TypedAstNodeContent::Declaration(TypedDeclaration::StructDeclaration(
TypedStructDeclaration {
visibility: Visibility::Public,
..
},
decl_id,
)),
..
}) => true,
}) => {
let struct_decl = de_get_struct(decl_id.clone(), &decl_id.span())?;
struct_decl.visibility == Visibility::Public
}
ControlFlowGraphNode::ProgramNode(TypedAstNode {
content:
TypedAstNodeContent::Declaration(TypedDeclaration::ImplTrait { .. }),
Expand Down Expand Up @@ -368,8 +368,9 @@ fn connect_declaration(
connect_abi_declaration(&abi_decl, graph, entry_node);
Ok(leaves.to_vec())
}
StructDeclaration(struct_decl) => {
connect_struct_declaration(struct_decl, graph, entry_node, tree_type);
StructDeclaration(decl_id) => {
let struct_decl = de_get_struct(decl_id.clone(), &span)?;
connect_struct_declaration(&struct_decl, graph, entry_node, tree_type);
Ok(leaves.to_vec())
}
EnumDeclaration(decl_id) => {
Expand Down
2 changes: 1 addition & 1 deletion sway-core/src/declaration_engine/declaration_engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ pub(crate) fn de_insert_struct(r#struct: TypedStructDeclaration) -> DeclarationI
DECLARATION_ENGINE.insert_struct(r#struct)
}

pub(crate) fn de_get_struct(
pub fn de_get_struct(
index: DeclarationId,
span: &Span,
) -> Result<TypedStructDeclaration, CompileError> {
Expand Down
53 changes: 42 additions & 11 deletions sway-core/src/semantic_analysis/ast_node/declaration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ pub enum TypedDeclaration {
ConstantDeclaration(DeclarationId),
FunctionDeclaration(TypedFunctionDeclaration),
TraitDeclaration(DeclarationId),
StructDeclaration(TypedStructDeclaration),
StructDeclaration(DeclarationId),
EnumDeclaration(DeclarationId),
ImplTrait(DeclarationId),
AbiDeclaration(DeclarationId),
Expand All @@ -53,7 +53,7 @@ impl CopyTypes for TypedDeclaration {
VariableDeclaration(ref mut var_decl) => var_decl.copy_types(type_mapping),
FunctionDeclaration(ref mut fn_decl) => fn_decl.copy_types(type_mapping),
TraitDeclaration(ref mut trait_decl) => trait_decl.copy_types(type_mapping),
StructDeclaration(ref mut struct_decl) => struct_decl.copy_types(type_mapping),
StructDeclaration(ref mut decl_id) => decl_id.copy_types(type_mapping),
EnumDeclaration(ref mut enum_decl) => enum_decl.copy_types(type_mapping),
ImplTrait(impl_trait) => impl_trait.copy_types(type_mapping),
// generics in an ABI is unsupported by design
Expand All @@ -74,7 +74,7 @@ impl Spanned for TypedDeclaration {
ConstantDeclaration(decl_id) => decl_id.span(),
FunctionDeclaration(TypedFunctionDeclaration { span, .. }) => span.clone(),
TraitDeclaration(decl_id) => decl_id.span(),
StructDeclaration(TypedStructDeclaration { name, .. }) => name.span(),
StructDeclaration(decl_id) => decl_id.span(),
EnumDeclaration(decl_id) => decl_id.span(),
AbiDeclaration(decl_id) => decl_id.span(),
ImplTrait(decl_id) => decl_id.span(),
Expand Down Expand Up @@ -128,8 +128,12 @@ impl fmt::Display for TypedDeclaration {
Err(_) => "unknown trait".into(),
}
}
TypedDeclaration::StructDeclaration(TypedStructDeclaration { name, .. }) =>
name.as_str().into(),
TypedDeclaration::StructDeclaration(decl_id) => {
match de_get_struct(decl_id.clone(), &decl_id.span()) {
Ok(TypedStructDeclaration { name, .. }) => name.as_str().into(),
Err(_) => "unknown struct".into(),
}
}
TypedDeclaration::EnumDeclaration(decl_id) => {
match de_get_enum(decl_id.clone(), &decl_id.span()) {
Ok(TypedEnumDeclaration { name, .. }) => name.as_str().into(),
Expand Down Expand Up @@ -253,11 +257,22 @@ impl TypedDeclaration {
/// Retrieves the declaration as a struct declaration.
///
/// Returns an error if `self` is not a `TypedStructDeclaration`.
pub(crate) fn expect_struct(&self) -> CompileResult<&TypedStructDeclaration> {
let warnings = vec![];
pub(crate) fn expect_struct(
&self,
access_span: &Span,
) -> CompileResult<TypedStructDeclaration> {
let mut warnings = vec![];
let mut errors = vec![];
match self {
TypedDeclaration::StructDeclaration(decl) => ok(decl, warnings, errors),
TypedDeclaration::StructDeclaration(decl_id) => {
let decl = check!(
CompileResult::from(de_get_struct(decl_id.clone(), access_span)),
return err(warnings, errors),
warnings,
errors
);
ok(decl, warnings, errors)
}
decl => {
errors.push(CompileError::DeclIsNotAStruct {
actually: decl.friendly_name().to_string(),
Expand Down Expand Up @@ -352,7 +367,15 @@ impl TypedDeclaration {
));
return err(warnings, errors);
}
TypedDeclaration::StructDeclaration(decl) => decl.create_type_id(),
TypedDeclaration::StructDeclaration(decl_id) => {
let decl = check!(
CompileResult::from(de_get_struct(decl_id.clone(), &self.span())),
return err(warnings, errors),
warnings,
errors
);
decl.create_type_id()
}
TypedDeclaration::EnumDeclaration(decl_id) => {
let decl = check!(
CompileResult::from(de_get_enum(decl_id.clone(), access_span)),
Expand Down Expand Up @@ -411,6 +434,15 @@ impl TypedDeclaration {
);
visibility
}
StructDeclaration(decl_id) => {
let TypedStructDeclaration { visibility, .. } = check!(
CompileResult::from(de_get_struct(decl_id.clone(), &decl_id.span())),
return err(warnings, errors),
warnings,
errors
);
visibility
}
EnumDeclaration(decl_id) => {
let TypedEnumDeclaration { visibility, .. } = check!(
CompileResult::from(de_get_enum(decl_id.clone(), &decl_id.span())),
Expand All @@ -426,8 +458,7 @@ impl TypedDeclaration {
| AbiDeclaration(..)
| ErrorRecovery => Visibility::Public,
VariableDeclaration(decl) => decl.mutability.visibility(),
FunctionDeclaration(TypedFunctionDeclaration { visibility, .. })
| StructDeclaration(TypedStructDeclaration { visibility, .. }) => *visibility,
FunctionDeclaration(TypedFunctionDeclaration { visibility, .. }) => *visibility,
};
ok(visibility, warnings, errors)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ impl TypedScrutinee {
errors
);
let mut struct_decl = check!(
unknown_decl.expect_struct().cloned(),
unknown_decl.expect_struct(&span),
return err(warnings, errors),
warnings,
errors
Expand Down
4 changes: 3 additions & 1 deletion sway-core/src/semantic_analysis/ast_node/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ impl TypedAstNode {
warnings,
errors
);

let name = fn_decl.name.clone();
let decl = TypedDeclaration::FunctionDeclaration(fn_decl);
ctx.namespace.insert_symbol(name, decl.clone());
Expand Down Expand Up @@ -366,7 +367,8 @@ impl TypedAstNode {
errors
);
let name = decl.name.clone();
let decl = TypedDeclaration::StructDeclaration(decl);
let decl_id = de_insert_struct(decl);
let decl = TypedDeclaration::StructDeclaration(decl_id);
// insert the struct decl into namespace
check!(
ctx.namespace.insert_symbol(name, decl.clone()),
Expand Down
2 changes: 1 addition & 1 deletion sway-core/src/semantic_analysis/namespace/items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ impl Items {
let mut warnings = vec![];
let mut errors = vec![];
// purposefully do not preemptively return errors so that the
// new definiton allows later usages to compile
// new definition allows later usages to compile
if self.symbols.get(&name).is_some() {
match item {
TypedDeclaration::EnumDeclaration { .. }
Expand Down
30 changes: 25 additions & 5 deletions sway-core/src/semantic_analysis/namespace/root.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use crate::{
declaration_engine::declaration_engine::{de_add_monomorphized_enum_copy, de_get_enum},
declaration_engine::{
de_add_monomorphized_struct_copy,
declaration_engine::{de_add_monomorphized_enum_copy, de_get_enum, de_get_struct},
},
error::*,
semantic_analysis::*,
type_system::*,
Expand Down Expand Up @@ -110,10 +113,19 @@ impl Root {
.ok(&mut warnings, &mut errors)
.cloned()
{
Some(TypedDeclaration::StructDeclaration(mut decl)) => {
Some(TypedDeclaration::StructDeclaration(original_id)) => {
// get the copy from the declaration engine
let mut new_copy = check!(
CompileResult::from(de_get_struct(original_id.clone(), &name.span())),
return err(warnings, errors),
warnings,
errors
);

// monomorphize the copy, in place
check!(
monomorphize(
&mut decl,
&mut new_copy,
&mut type_arguments.unwrap_or_default(),
enforce_type_arguments,
span,
Expand All @@ -122,9 +134,17 @@ impl Root {
),
return err(warnings, errors),
warnings,
errors
errors,
);
decl.create_type_id()

// create the type id from the copy
let type_id = new_copy.create_type_id();

// add the new copy as a monomorphized copy of the original id
de_add_monomorphized_struct_copy(original_id, new_copy);

// return the id
type_id
}
Some(TypedDeclaration::EnumDeclaration(original_id)) => {
// get the copy from the declaration engine
Expand Down
8 changes: 7 additions & 1 deletion sway-core/src/semantic_analysis/storage_only_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,13 @@ fn decl_validate(decl: &TypedDeclaration) -> CompileResult<()> {
)
}
}
TypedDeclaration::StructDeclaration(TypedStructDeclaration { fields, .. }) => {
TypedDeclaration::StructDeclaration(decl_id) => {
let TypedStructDeclaration { fields, .. } = check!(
CompileResult::from(de_get_struct(decl_id.clone(), &decl_id.span())),
return err(warnings, errors),
warnings,
errors,
);
for field in fields {
check!(
check_type(field.type_id, field.span.clone(), false),
Expand Down
22 changes: 19 additions & 3 deletions sway-core/src/type_system/type_binding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,10 +193,19 @@ impl TypeBinding<CallPath> {

TypedDeclaration::EnumDeclaration(new_id)
}
TypedDeclaration::StructDeclaration(ref mut decl) => {
TypedDeclaration::StructDeclaration(original_id) => {
// get the copy from the declaration engine
let mut new_copy = check!(
CompileResult::from(de_get_struct(original_id.clone(), &self.span())),
return err(warnings, errors),
warnings,
errors
);

// monomorphize the copy, in place
check!(
ctx.monomorphize(
decl,
&mut new_copy,
&mut self.type_arguments,
EnforceTypeArguments::No,
&self.span
Expand All @@ -205,7 +214,14 @@ impl TypeBinding<CallPath> {
warnings,
errors
);
unknown_decl

// insert the new copy into the declaration engine
let new_id = de_insert_struct(new_copy);

// add the new copy as a monomorphized copy of the original id
de_add_monomorphized_copy(original_id, new_id.clone());

TypedDeclaration::StructDeclaration(new_id)
}
_ => unknown_decl,
};
Expand Down
5 changes: 4 additions & 1 deletion sway-lsp/src/capabilities/hover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,10 @@ fn hover_format(token: &Token, ident: &Ident) -> Hover {
format_variable_hover(var_decl.mutability.is_mutable(), type_name)
}
TypedDeclaration::FunctionDeclaration(func) => extract_fn_signature(&func.span()),
TypedDeclaration::StructDeclaration(ref struct_decl) => {
TypedDeclaration::StructDeclaration(decl_id) => {
// TODO: do not use unwrap
let struct_decl =
declaration_engine::de_get_struct(decl_id.clone(), &decl.span()).unwrap();
format_visibility_hover(struct_decl.visibility, decl.friendly_name())
}
TypedDeclaration::TraitDeclaration(ref decl_id) => {
Expand Down
15 changes: 9 additions & 6 deletions sway-lsp/src/core/traverse_typed_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{
utils::token::{struct_declaration_of_type_id, to_ident_key},
};
use sway_core::{
declaration_engine::{self, de_get_impl_trait},
declaration_engine,
semantic_analysis::ast_node::{
code_block::TypedCodeBlock,
expression::{
Expand Down Expand Up @@ -72,12 +72,15 @@ fn handle_declaration(declaration: &TypedDeclaration, tokens: &TokenMap) {
collect_typed_trait_fn_token(trait_fn, tokens);
}
}
TypedDeclaration::StructDeclaration(struct_dec) => {
if let Some(mut token) = tokens.get_mut(&to_ident_key(&struct_dec.name)) {
TypedDeclaration::StructDeclaration(decl_id) => {
// TODO: do not use unwrap
let struct_decl =
declaration_engine::de_get_struct(decl_id.clone(), &declaration.span()).unwrap();
if let Some(mut token) = tokens.get_mut(&to_ident_key(&struct_decl.name)) {
token.typed = Some(TypedAstToken::TypedDeclaration(declaration.clone()));
}

for field in &struct_dec.fields {
for field in &struct_decl.fields {
if let Some(mut token) = tokens.get_mut(&to_ident_key(&field.name)) {
token.typed = Some(TypedAstToken::TypedStructField(field.clone()));
token.type_def = Some(TypeDefinition::TypeId(field.type_id));
Expand All @@ -91,7 +94,7 @@ fn handle_declaration(declaration: &TypedDeclaration, tokens: &TokenMap) {
}
}

for type_param in &struct_dec.type_parameters {
for type_param in &struct_decl.type_parameters {
if let Some(mut token) = tokens.get_mut(&to_ident_key(&type_param.name_ident)) {
token.typed = Some(TypedAstToken::TypedDeclaration(declaration.clone()));
token.type_def = Some(TypeDefinition::TypeId(type_param.type_id));
Expand Down Expand Up @@ -134,7 +137,7 @@ fn handle_declaration(declaration: &TypedDeclaration, tokens: &TokenMap) {
implementing_for_type_id,
type_implementing_for_span,
..
} = de_get_impl_trait(decl_id.clone(), &decl_id.span()).unwrap();
} = declaration_engine::de_get_impl_trait(decl_id.clone(), &decl_id.span()).unwrap();
for ident in &trait_name.prefixes {
if let Some(mut token) = tokens.get_mut(&to_ident_key(ident)) {
token.typed = Some(TypedAstToken::TypedDeclaration(declaration.clone()));
Expand Down
4 changes: 3 additions & 1 deletion sway-lsp/src/utils/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@ pub(crate) fn struct_declaration_of_type_id(
tokens: &TokenMap,
) -> Option<TypedStructDeclaration> {
declaration_of_type_id(type_id, tokens).and_then(|decl| match decl {
TypedDeclaration::StructDeclaration(struct_decl) => Some(struct_decl),
TypedDeclaration::StructDeclaration(ref decl_id) => {
Some(declaration_engine::de_get_struct(decl_id.clone(), &decl.span()).unwrap())
}
_ => None,
})
}
Expand Down

0 comments on commit 719dca1

Please sign in to comment.