Skip to content

Commit

Permalink
Forward attributes from ParseProgram to TyProgram (FuelLabs#2979)
Browse files Browse the repository at this point in the history
This is useful for both upcoming `forc doc` (`#[doc]`) and `forc test`
(`#[test]`) behaviour.

`forc test` requires this for in-language unit tests as it needs access
to the attributes of the function declaration during dead code analysis.
This is so that we can add the test functions as entry points and avoid
producing dead function warnings for all `#[test]` functions.

@eureka-cpu also mentioned that this would be useful for `#[doc]`
support, though I don't quite remember the details.

Following parsing, each item's set of `Attribute`s remains unmodified
and used in a read-only manner throughout the rest of compilation. This
PR also moves the `HashMap` used to store the attributes behind an `Arc`
to cut down on memory usage slightly.
  • Loading branch information
mitchmindtree authored Oct 10, 2022
1 parent 2c448d9 commit cf39056
Show file tree
Hide file tree
Showing 10 changed files with 69 additions and 45 deletions.
13 changes: 8 additions & 5 deletions sway-core/src/convert_parse_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ use std::{
iter,
mem::MaybeUninit,
ops::ControlFlow,
sync::atomic::{AtomicUsize, Ordering},
sync::{
atomic::{AtomicUsize, Ordering},
Arc,
},
};

#[derive(Debug, Default)]
Expand Down Expand Up @@ -236,7 +239,7 @@ fn item_to_ast_nodes(ec: &mut ErrorContext, item: Item) -> Result<Vec<AstNode>,

/// An attribute has a name (i.e "doc", "storage") and
/// a vector of possible arguments.
#[derive(Clone, Debug)]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Attribute {
pub name: Ident,
pub args: Vec<Ident>,
Expand All @@ -250,13 +253,13 @@ pub enum AttributeKind {
}

/// Stores the attributes associated with the type.
pub type AttributesMap = HashMap<AttributeKind, Vec<Attribute>>;
pub type AttributesMap = Arc<HashMap<AttributeKind, Vec<Attribute>>>;

fn item_attrs_to_map(
ec: &mut ErrorContext,
attribute_list: &[AttributeDecl],
) -> Result<AttributesMap, ErrorEmitted> {
let mut attrs_map = AttributesMap::new();
let mut attrs_map: HashMap<_, Vec<Attribute>> = HashMap::new();
for attr_decl in attribute_list {
let attr = attr_decl.attribute.get();
let name = attr.name.as_str();
Expand Down Expand Up @@ -295,7 +298,7 @@ fn item_attrs_to_map(
}
}
}
Ok(attrs_map)
Ok(Arc::new(attrs_map))
}

fn item_use_to_use_statements(
Expand Down
3 changes: 3 additions & 0 deletions sway-core/src/semantic_analysis/ast_node/declaration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use crate::{
language::*,
semantic_analysis::*,
type_system::*,
AttributesMap,
};
use derivative::Derivative;
use std::{borrow::Cow, fmt};
Expand Down Expand Up @@ -504,6 +505,7 @@ pub struct TyTraitFn {
#[derivative(PartialEq = "ignore")]
#[derivative(Eq(bound = ""))]
pub return_type_span: Span,
pub attributes: AttributesMap,
}

impl CopyTypes for TyTraitFn {
Expand All @@ -523,6 +525,7 @@ impl TyTraitFn {
body: TyCodeBlock { contents: vec![] },
parameters: self.parameters.clone(),
span: self.name.span(),
attributes: self.attributes.clone(),
return_type: self.return_type,
initial_return_type: self.return_type,
return_type_span: self.return_type_span.clone(),
Expand Down
5 changes: 4 additions & 1 deletion sway-core/src/semantic_analysis/ast_node/declaration/enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
insert_type, look_up_type_id, CopyTypes, CreateTypeId, EnforceTypeArguments,
MonomorphizeHelper, ReplaceSelfType, TypeId, TypeMapping, TypeParameter,
},
TypeInfo,
AttributesMap, TypeInfo,
};
use std::hash::{Hash, Hasher};
use sway_error::error::CompileError;
Expand All @@ -16,6 +16,7 @@ use sway_types::{Ident, Span, Spanned};
pub struct TyEnumDeclaration {
pub name: Ident,
pub type_parameters: Vec<TypeParameter>,
pub attributes: AttributesMap,
pub variants: Vec<TyEnumVariant>,
pub(crate) span: Span,
pub visibility: Visibility,
Expand Down Expand Up @@ -80,6 +81,7 @@ impl TyEnumDeclaration {
type_parameters,
variants,
span,
attributes,
visibility,
..
} = decl;
Expand Down Expand Up @@ -117,6 +119,7 @@ impl TyEnumDeclaration {
type_parameters: new_type_parameters,
variants: variants_buf,
span,
attributes,
visibility,
};
ok(decl, warnings, errors)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::{
semantic_analysis::*,
style::*,
type_system::*,
AttributesMap,
};
use sha2::{Digest, Sha256};
use sway_types::{Ident, JsonABIFunction, JsonTypeApplication, JsonTypeDeclaration, Span, Spanned};
Expand All @@ -18,6 +19,7 @@ pub struct TyFunctionDeclaration {
pub body: TyCodeBlock,
pub parameters: Vec<TyFunctionParameter>,
pub span: Span,
pub attributes: AttributesMap,
pub return_type: TypeId,
pub initial_return_type: TypeId,
pub type_parameters: Vec<TypeParameter>,
Expand Down Expand Up @@ -97,6 +99,7 @@ impl TyFunctionDeclaration {
body,
parameters,
span,
attributes,
return_type,
type_parameters,
return_type_span,
Expand Down Expand Up @@ -196,6 +199,7 @@ impl TyFunctionDeclaration {
body,
parameters: new_parameters,
span,
attributes,
return_type,
initial_return_type,
type_parameters: new_type_parameters,
Expand Down Expand Up @@ -343,6 +347,7 @@ fn test_function_selector_behavior() {
body: TyCodeBlock { contents: vec![] },
parameters: vec![],
span: Span::dummy(),
attributes: Default::default(),
return_type: 0.into(),
initial_return_type: 0.into(),
type_parameters: vec![],
Expand Down Expand Up @@ -383,6 +388,7 @@ fn test_function_selector_behavior() {
},
],
span: Span::dummy(),
attributes: Default::default(),
return_type: 0.into(),
initial_return_type: 0.into(),
type_parameters: vec![],
Expand Down
30 changes: 11 additions & 19 deletions sway-core/src/semantic_analysis/ast_node/declaration/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::{
TyExpression, TyStructField, TypeCheckedStorageAccess, TypeCheckedStorageAccessDescriptor,
},
type_system::{look_up_type_id, TypeId, TypeInfo},
Ident,
AttributesMap, Ident,
};
use derivative::Derivative;
use fuel_tx::StorageSlot;
Expand All @@ -23,6 +23,7 @@ pub struct TyStorageDeclaration {
#[derivative(PartialEq = "ignore")]
#[derivative(Eq(bound = ""))]
pub span: Span,
pub attributes: AttributesMap,
}

impl Spanned for TyStorageDeclaration {
Expand All @@ -32,8 +33,12 @@ impl Spanned for TyStorageDeclaration {
}

impl TyStorageDeclaration {
pub fn new(fields: Vec<TyStorageField>, span: Span) -> Self {
TyStorageDeclaration { fields, span }
pub fn new(fields: Vec<TyStorageField>, span: Span, attributes: AttributesMap) -> Self {
TyStorageDeclaration {
fields,
span,
attributes,
}
}
/// Given a field, find its type information in the declaration and return it. If the field has not
/// been declared as a part of storage, return an error.
Expand Down Expand Up @@ -139,13 +144,15 @@ impl TyStorageDeclaration {
type_id: ref r#type,
ref span,
ref initializer,
ref attributes,
..
}| TyStructField {
name: name.clone(),
type_id: *r#type,
initial_type_id: *r#type,
span: span.clone(),
type_span: initializer.span.clone(),
attributes: attributes.clone(),
},
)
.collect()
Expand Down Expand Up @@ -183,6 +190,7 @@ pub struct TyStorageField {
pub type_span: Span,
pub initializer: TyExpression,
pub(crate) span: Span,
pub attributes: AttributesMap,
}

// NOTE: Hash and PartialEq must uphold the invariant:
Expand All @@ -197,22 +205,6 @@ impl PartialEq for TyStorageField {
}

impl TyStorageField {
pub fn new(
name: Ident,
r#type: TypeId,
type_span: Span,
initializer: TyExpression,
span: Span,
) -> Self {
TyStorageField {
name,
type_id: r#type,
type_span,
initializer,
span,
}
}

pub(crate) fn get_initialized_storage_slots(
&self,
context: &mut Context,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use crate::{
language::{parsed::*, Visibility},
semantic_analysis::*,
type_system::*,
AttributesMap,
};
use std::hash::{Hash, Hasher};
use sway_error::error::CompileError;
Expand All @@ -15,6 +16,7 @@ pub struct TyStructDeclaration {
pub type_parameters: Vec<TypeParameter>,
pub visibility: Visibility,
pub(crate) span: Span,
pub attributes: AttributesMap,
}

// NOTE: Hash and PartialEq must uphold the invariant:
Expand Down Expand Up @@ -80,6 +82,7 @@ impl TyStructDeclaration {
type_parameters,
visibility,
span,
attributes,
..
} = decl;

Expand Down Expand Up @@ -117,6 +120,7 @@ impl TyStructDeclaration {
fields: new_fields,
visibility,
span,
attributes,
};

ok(decl, warnings, errors)
Expand Down Expand Up @@ -155,6 +159,7 @@ pub struct TyStructField {
pub initial_type_id: TypeId,
pub(crate) span: Span,
pub type_span: Span,
pub attributes: AttributesMap,
}

// NOTE: Hash and PartialEq must uphold the invariant:
Expand Down Expand Up @@ -210,6 +215,7 @@ impl TyStructField {
initial_type_id,
span: field.span,
type_span: field.type_span,
attributes: field.attributes,
};
ok(field, warnings, errors)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ fn convert_trait_methods_to_dummy_funcs(
name: name.clone(),
body: TyCodeBlock { contents: vec![] },
parameters: typed_parameters,
attributes: method.attributes.clone(),
span: name.span(),
return_type,
initial_return_type,
Expand Down
16 changes: 11 additions & 5 deletions sway-core/src/semantic_analysis/ast_node/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,7 @@ impl TyAstNode {
Declaration::StorageDeclaration(StorageDeclaration {
span,
fields,
attributes,
..
}) => {
let mut fields_buf = Vec::with_capacity(fields.len());
Expand All @@ -402,6 +403,7 @@ impl TyAstNode {
type_info,
initializer,
type_info_span,
attributes,
..
} in fields
{
Expand All @@ -424,15 +426,16 @@ impl TyAstNode {
errors,
);

fields_buf.push(TyStorageField::new(
fields_buf.push(TyStorageField {
name,
type_id,
type_info_span,
type_span: type_info_span,
initializer,
span.clone(),
));
span: span.clone(),
attributes,
});
}
let decl = TyStorageDeclaration::new(fields_buf, span);
let decl = TyStorageDeclaration::new(fields_buf, span, attributes);
let decl_id = de_insert_storage(decl);
// insert the storage declaration into the symbols
// if there already was one, return an error that duplicate storage
Expand Down Expand Up @@ -543,6 +546,7 @@ fn type_check_interface_surface(
return_type_span,
parameters: typed_parameters,
return_type,
attributes: trait_fn.attributes,
});
}
ok(typed_surface, warnings, errors)
Expand Down Expand Up @@ -656,6 +660,7 @@ fn type_check_trait_methods(
body,
parameters: typed_parameters,
span,
attributes: method.attributes,
return_type,
initial_return_type,
type_parameters,
Expand Down Expand Up @@ -689,6 +694,7 @@ fn error_recovery_function_declaration(decl: FunctionDeclaration) -> TyFunctionD
contents: Default::default(),
},
span,
attributes: Default::default(),
is_contract_call: false,
return_type_span,
parameters: Default::default(),
Expand Down
2 changes: 1 addition & 1 deletion sway-core/src/semantic_analysis/namespace/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ impl Module {

// perform the conversions from parser code to parse tree types
let name = const_item.name.clone();
let attributes = std::collections::HashMap::new();
let attributes = Default::default();
// convert to const decl
let const_decl = match crate::convert_parse_tree::item_const_to_constant_declaration(
ec, const_item, attributes,
Expand Down
Loading

0 comments on commit cf39056

Please sign in to comment.