Skip to content

Commit

Permalink
- Renamed StorageHandle to StorageKey as per the RFC
Browse files Browse the repository at this point in the history
- Remove support for type ascription on `self` for now
- Instead, we now do `impl StorageKey<StorageMap<K, V>>` which seems to
  work just as well
  • Loading branch information
mohammadfawaz committed Apr 5, 2023
1 parent 284c7f6 commit 985cde0
Show file tree
Hide file tree
Showing 13 changed files with 65 additions and 260 deletions.
1 change: 0 additions & 1 deletion sway-ast/src/item/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ pub enum FnArgs {
self_token: SelfToken,
ref_self: Option<RefToken>,
mutable_self: Option<MutToken>,
ty: Option<(ColonToken, Ty)>,
args_opt: Option<(CommaToken, Punctuated<FnArg, CommaToken>)>,
},
}
Expand Down
6 changes: 0 additions & 6 deletions sway-core/src/language/parsed/declaration/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,6 @@ impl PartialEqWithEngines for FunctionParameter {
}
}

impl FunctionParameter {
pub fn is_self(&self) -> bool {
self.name.as_str() == "self"
}
}

impl FunctionDeclaration {
/// Checks if this `FunctionDeclaration` is a test.
pub(crate) fn is_test(&self) -> bool {
Expand Down
97 changes: 15 additions & 82 deletions sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,12 @@ use sway_types::{Named, Spanned};
use crate::{
decl_engine::{DeclEngineInsert, DeclRef, ReplaceFunctionImplementingType},
error::*,
language::{parsed, ty, ty::TyImplItem},
language::{parsed, ty},
semantic_analysis::TypeCheckContext,
type_system::*,
CompileResult,
};

use std::collections::{BTreeMap, HashSet};

impl ty::TyDecl {
pub(crate) fn type_check(
mut ctx: TypeCheckContext,
Expand Down Expand Up @@ -197,7 +195,6 @@ impl ty::TyDecl {
warnings,
errors
);

let impl_trait_decl: ty::TyDecl = decl_engine.insert(impl_trait.clone()).into();
impl_trait.items.iter_mut().for_each(|item| {
item.replace_implementing_type(engines, impl_trait_decl.clone());
Expand All @@ -212,84 +209,20 @@ impl ty::TyDecl {
warnings,
errors
);

// Set of all type IDs that have corresponding items implemented for them in this
// `impl` block. In most cases, this is a single type ID that is equal to
// `impl_trait.implementing_for.type_id`.
let mut processed_ids = HashSet::new();

// This is a map from type IDs to a vector of impl items. In most cases, all the
// items are available to `impl_trait.implementing_for.type_id` (i.e. `Self`).
// However, there are situations where `self`, in some of the impl methods, has a
// type ascription that is different from `Self`. In that case, we have to keep
// track of which impl items are available to which type ID.
//
// For now, only `std::core::experimental::StorageHandle` is allowed as a type
// ascription for `self`, so check that here as well
let type_id_to_impl_items: BTreeMap<TypeId, Vec<TyImplItem>> = impl_trait
.items
.iter()
.map(|item| match item {
TyImplItem::Fn(func) => {
// For function items, check if the first argument is `self`. If so,
// map the corresponding type ID to this item. Make sure that type IDs
// that are subset of each other are uniqued using `processed_ids`.
let func = decl_engine.get_function(func);
(
match func.parameters.first() {
Some(first_arg) if first_arg.is_self() => {
let self_type_id = first_arg.type_argument.type_id;
match processed_ids.iter().find(|p| {
type_engine
.get(self_type_id)
.is_subset_of(&type_engine.get(**p), engines)
}) {
Some(id) => *id,
_ => {
processed_ids.insert(self_type_id);
self_type_id
}
}
}
_ => impl_trait.implementing_for.type_id,
},
item,
)
}
_ => {
// Other items are only available for `Self`
(impl_trait.implementing_for.type_id, item)
}
})
.fold(
BTreeMap::new(),
|mut acc: BTreeMap<TypeId, Vec<_>>, (type_id, item)| {
acc.entry(type_id)
.and_modify(|v| v.push(item.clone()))
.or_insert(vec![item.clone()]);
acc
},
);

// For each type ID discovered in type_id_to_impl_items, insert the collected items
// into the trait map
for type_id in type_id_to_impl_items.keys() {
check!(
ctx.namespace.insert_trait_implementation(
impl_trait.trait_name.clone(),
impl_trait.trait_type_arguments.clone(),
*type_id,
&type_id_to_impl_items[type_id],
&impl_trait.span,
true,
engines,
),
return err(warnings, errors),
warnings,
errors
);
}

check!(
ctx.namespace.insert_trait_implementation(
impl_trait.trait_name.clone(),
impl_trait.trait_type_arguments.clone(),
impl_trait.implementing_for.type_id,
&impl_trait.items,
&impl_trait.span,
true,
engines,
),
return err(warnings, errors),
warnings,
errors
);
let impl_trait_decl: ty::TyDecl = decl_engine.insert(impl_trait.clone()).into();
impl_trait.items.iter_mut().for_each(|item| {
item.replace_implementing_type(engines, impl_trait_decl.clone())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::{
};

use sway_error::error::CompileError;
use sway_types::{Ident, Spanned};
use sway_types::Spanned;

impl ty::TyFunctionParameter {
pub(crate) fn type_check(
Expand All @@ -21,8 +21,6 @@ impl ty::TyFunctionParameter {
let type_engine = ctx.type_engine;
let decl_engine = ctx.decl_engine;

let is_self = parameter.is_self();

let FunctionParameter {
name,
is_reference,
Expand All @@ -31,9 +29,6 @@ impl ty::TyFunctionParameter {
mut type_argument,
} = parameter;

let is_self_and_is_ascribed =
is_self && !matches!(type_engine.get(type_argument.type_id), TypeInfo::SelfType);

type_argument.type_id = check!(
ctx.resolve_type_with_self(
type_argument.type_id,
Expand All @@ -46,37 +41,6 @@ impl ty::TyFunctionParameter {
errors,
);

// If this parameter is `self` and if it is type ascribed, then check that the type
// ascribed is `core::experimental::storage::StorageHandle`. Otherwise, emit an error. In
// the future, we may want to allow more types such as `Self`.
if is_self_and_is_ascribed {
match type_engine.get(type_argument.type_id) {
TypeInfo::Struct(decl_ref) => {
let struct_decl = decl_engine.get_struct(&decl_ref);
if !(struct_decl.call_path.prefixes
== vec![
Ident::new_no_span("core".into()),
Ident::new_no_span("experimental".into()),
Ident::new_no_span("storage".into()),
]
&& struct_decl.call_path.suffix
== Ident::new_no_span("StorageHandle".into()))
{
errors.push(CompileError::InvalidSelfParamterType {
r#type: ctx.engines().help_out(type_argument.type_id).to_string(),
span: name.span(),
});
}
}
_ => {
errors.push(CompileError::InvalidSelfParamterType {
r#type: ctx.engines().help_out(type_argument.type_id).to_string(),
span: name.span(),
});
}
}
}

if !is_from_method {
let mutability = ty::VariableMutability::new_from_ref_mut(is_reference, is_mutable);
if mutability == ty::VariableMutability::Mutable {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -911,48 +911,46 @@ impl ty::TyExpression {
);

if ctx.experimental_storage_enabled() {
// The type of a storage access is `core::experimental::StorageHandle`. This is the
// path to it.
let storage_handle_mod_path = vec![
// The type of a storage access is `core::experimental::storage::StorageKey`. This is
// the path to it.
let storage_key_mod_path = vec![
Ident::new_with_override("core".into(), span.clone()),
Ident::new_with_override("experimental".into(), span.clone()),
Ident::new_with_override("storage".into(), span.clone()),
];
let storage_handle_ident =
Ident::new_with_override("StorageHandle".into(), span.clone());
let storage_key_ident = Ident::new_with_override("StorageKey".into(), span.clone());

// Search for the struct declaration with the call path above.
let storage_handle_decl_opt = check!(
let storage_key_decl_opt = check!(
ctx.namespace
.root()
.resolve_symbol(&storage_handle_mod_path, &storage_handle_ident),
.resolve_symbol(&storage_key_mod_path, &storage_key_ident),
return err(warnings, errors),
warnings,
errors
);
let storage_handle_struct_decl_ref = check!(
storage_handle_decl_opt.to_struct_ref(engines),
let storage_key_struct_decl_ref = check!(
storage_key_decl_opt.to_struct_ref(engines),
return err(warnings, errors),
warnings,
errors
);
let mut storage_handle_struct_decl =
decl_engine.get_struct(&storage_handle_struct_decl_ref);
let mut storage_key_struct_decl = decl_engine.get_struct(&storage_key_struct_decl_ref);

// Set the type arguments to `StorageHandle` to the `access_type`, which is represents
// the type of the data that the `StorageHandle` "points" to.
// Set the type arguments to `StorageKey` to the `access_type`, which is represents the
// type of the data that the `StorageKey` "points" to.
let mut type_arguments = vec![TypeArgument {
initial_type_id: access_type,
type_id: access_type,
span: span.clone(),
call_path_tree: None,
}];

// Monomorphize the generic `StorageHandle` type given the type argument specified above
// Monomorphize the generic `StorageKey` type given the type argument specified above
let mut ctx = ctx;
check!(
ctx.monomorphize(
&mut storage_handle_struct_decl,
&mut storage_key_struct_decl,
&mut type_arguments,
EnforceTypeArguments::Yes,
span
Expand All @@ -964,14 +962,11 @@ impl ty::TyExpression {

// Update `access_type` to be the type of the monomorphized struct after inserting it
// into the type engine
let storage_handle_struct_decl_ref =
ctx.engines().de().insert(storage_handle_struct_decl);
access_type = type_engine.insert(
decl_engine,
TypeInfo::Struct(storage_handle_struct_decl_ref),
);
let storage_key_struct_decl_ref = ctx.engines().de().insert(storage_key_struct_decl);
access_type =
type_engine.insert(decl_engine, TypeInfo::Struct(storage_key_struct_decl_ref));

// take any trait items that apply to `StorageHandle<T>` and copy them to the
// take any trait items that apply to `StorageKey<T>` and copy them to the
// monomorphized type
ctx.namespace
.insert_trait_implementation_for_type(engines, access_type);
Expand Down
9 changes: 1 addition & 8 deletions sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1139,7 +1139,6 @@ fn fn_args_to_function_parameters(
self_token,
ref_self,
mutable_self,
ty,
args_opt,
} => {
let mutability_span = match (&ref_self, &mutable_self) {
Expand All @@ -1148,13 +1147,7 @@ fn fn_args_to_function_parameters(
(Some(reference), None) => reference.span(),
(Some(reference), Some(mutable)) => Span::join(reference.span(), mutable.span()),
};
let type_id = match ty {
None => engines.te().insert(engines.de(), TypeInfo::SelfType),
Some(ty) => engines.te().insert(
engines.de(),
ty_to_type_info(context, handler, engines, ty.1)?,
),
};
let type_id = engines.te().insert(engines.de(), TypeInfo::SelfType);
let mut function_parameters = vec![FunctionParameter {
name: Ident::new(self_token.span()),
is_reference: ref_self.is_some(),
Expand Down
3 changes: 0 additions & 3 deletions sway-error/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -633,8 +633,6 @@ pub enum CompileError {
ConfigurableInLibrary { span: Span },
#[error("The name `{name}` is defined multiple times")]
NameDefinedMultipleTimes { name: String, span: Span },
#[error("invalid `self` parameter type: {r#type}")]
InvalidSelfParamterType { r#type: String, span: Span },
}

impl std::convert::From<TypeError> for CompileError {
Expand Down Expand Up @@ -805,7 +803,6 @@ impl Spanned for CompileError {
TraitImplPayabilityMismatch { span, .. } => span.clone(),
ConfigurableInLibrary { span } => span.clone(),
NameDefinedMultipleTimes { span, .. } => span.clone(),
InvalidSelfParamterType { span, .. } => span.clone(),
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion sway-lib-core/src/experimental/storage.sw
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ library;
/// Describes a location in storage specified by the `b256` key of a particular storage slot and an
/// offset, in words, from the start of the storage slot at `key`. The parameter `T` is the type of
/// the data to be read from or written to at `offset`.
pub struct StorageHandle<T> {
pub struct StorageKey<T> {
key: b256,
offset: u64,
}
Loading

0 comments on commit 985cde0

Please sign in to comment.