Skip to content

Commit

Permalink
SuperABIs
Browse files Browse the repository at this point in the history
close #4049
  • Loading branch information
anton-trunov committed Mar 27, 2023
1 parent adc5c1a commit 77b6d25
Show file tree
Hide file tree
Showing 39 changed files with 502 additions and 19 deletions.
12 changes: 10 additions & 2 deletions sway-core/src/semantic_analysis/ast_node/declaration/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ use crate::{
parsed::*,
ty::{self, TyTraitItem},
},
semantic_analysis::{declaration::insert_supertraits_into_namespace, Mode, TypeCheckContext},
semantic_analysis::{
declaration::{insert_supertraits_into_namespace, SupertraitOf},
Mode, TypeCheckContext,
},
CompileResult,
};

Expand Down Expand Up @@ -44,7 +47,12 @@ impl ty::TyAbiDecl {
// Recursively make the interface surfaces and methods of the
// supertraits available to this abi.
check!(
insert_supertraits_into_namespace(ctx.by_ref(), contract_type, &supertraits),
insert_supertraits_into_namespace(
ctx.by_ref(),
contract_type,
&supertraits,
SupertraitOf::Abi
),
return err(warnings, errors),
warnings,
errors
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,12 +181,28 @@ impl ty::TyDecl {
warnings,
errors
);
// if this ImplTrait implements a trait and not an ABI,
// we insert its methods into the context
// otherwise, if it implements an ABI, we do not
// insert those since we do not allow calling contract methods
// from contract methods
let emp_vec = vec![];
let impl_trait_items = if let Some(ty::TyDecl::TraitDecl { .. }) = ctx
.namespace
.resolve_call_path(&impl_trait.trait_name)
.ok(&mut warnings, &mut errors)
.cloned()
{
&impl_trait.items
} else {
&emp_vec
};
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_items,
&impl_trait.span,
false,
engines,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -649,7 +649,6 @@ fn type_check_trait_implementation(
warnings,
errors
);

ctx.namespace.insert_trait_implementation(
trait_name.clone(),
trait_type_arguments.to_vec(),
Expand Down Expand Up @@ -1303,9 +1302,9 @@ fn handle_supertraits(
interface_surface_item_ids.extend(next_interface_supertrait_decl_refs);
impld_item_refs.extend(next_these_supertrait_decl_refs);
}
Some(ty::TyDecl::AbiDecl { .. }) => errors.push(CompileError::AbiAsSupertrait {
span: supertrait.name.span().clone(),
}),
Some(ty::TyDecl::AbiDecl { .. }) => {
// we allow ABIs as superABIs now
}
_ => errors.push(CompileError::TraitNotFound {
name: supertrait.name.to_string(),
span: supertrait.name.span(),
Expand Down
31 changes: 23 additions & 8 deletions sway-core/src/semantic_analysis/ast_node/declaration/supertrait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,19 @@ use crate::{
EnforceTypeArguments, TypeId,
};

#[derive(Clone, Copy, PartialEq, Eq)]
pub enum SupertraitOf {
Abi,
Trait,
}

/// Recursively insert the interface surfaces and methods from supertraits to
/// the given namespace.
pub(crate) fn insert_supertraits_into_namespace(
mut ctx: TypeCheckContext,
type_id: TypeId,
supertraits: &[parsed::Supertrait],
supertraits_of: SupertraitOf,
) -> CompileResult<()> {
let mut warnings = vec![];
let mut errors = vec![];
Expand All @@ -33,13 +40,15 @@ pub(crate) fn insert_supertraits_into_namespace(
continue;
}

match ctx
let decl = ctx
.namespace
.resolve_call_path(&supertrait.name)
.ok(&mut warnings, &mut errors)
.cloned()
{
Some(ty::TyDecl::TraitDecl { decl_id, .. }) => {
.cloned();

match (decl.clone(), supertraits_of) {
// a trait can be a supertrait of either a trait or a an ABI
(Some(ty::TyDecl::TraitDecl { decl_id, .. }), _) => {
let mut trait_decl = decl_engine.get_trait(&decl_id);

// Right now we don't parse type arguments for supertraits, so
Expand Down Expand Up @@ -83,16 +92,22 @@ pub(crate) fn insert_supertraits_into_namespace(
insert_supertraits_into_namespace(
ctx.by_ref(),
type_id,
&trait_decl.supertraits
&trait_decl.supertraits,
SupertraitOf::Trait
),
continue,
warnings,
errors
);
}
Some(ty::TyDecl::AbiDecl { .. }) => errors.push(CompileError::AbiAsSupertrait {
span: supertrait.name.span().clone(),
}),
// an ABI can only be a superABI of an ABI
(Some(ty::TyDecl::AbiDecl { decl_id: _, .. }), SupertraitOf::Abi) => {}
// an ABI cannot be a supertrait of a trait
(Some(ty::TyDecl::AbiDecl { .. }), SupertraitOf::Trait) => {
errors.push(CompileError::AbiAsSupertrait {
span: supertrait.name.span().clone(),
})
}
_ => errors.push(CompileError::TraitNotFound {
name: supertrait.name.to_string(),
span: supertrait.name.span(),
Expand Down
12 changes: 10 additions & 2 deletions sway-core/src/semantic_analysis/ast_node/declaration/trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ use crate::{
ty::{self, TyImplItem, TyTraitItem},
CallPath,
},
semantic_analysis::{declaration::insert_supertraits_into_namespace, Mode, TypeCheckContext},
semantic_analysis::{
declaration::{insert_supertraits_into_namespace, SupertraitOf},
Mode, TypeCheckContext,
},
type_system::*,
};

Expand Down Expand Up @@ -65,7 +68,12 @@ impl ty::TyTraitDecl {
// Recursively make the interface surfaces and methods of the
// supertraits available to this trait.
check!(
insert_supertraits_into_namespace(ctx.by_ref(), self_type, &supertraits),
insert_supertraits_into_namespace(
ctx.by_ref(),
self_type,
&supertraits,
SupertraitOf::Trait
),
return err(warnings, errors),
warnings,
errors
Expand Down
8 changes: 6 additions & 2 deletions sway-core/src/type_system/ast_elements/trait_constraint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ use crate::{
engine_threading::*,
error::*,
language::{parsed::Supertrait, ty, CallPath},
semantic_analysis::{declaration::insert_supertraits_into_namespace, TypeCheckContext},
semantic_analysis::{
declaration::{insert_supertraits_into_namespace, SupertraitOf},
TypeCheckContext,
},
type_system::priv_prelude::*,
types::*,
CompileResult,
Expand Down Expand Up @@ -220,7 +223,8 @@ impl TraitConstraint {
insert_supertraits_into_namespace(
ctx.by_ref(),
type_id,
&trait_decl.supertraits
&trait_decl.supertraits,
SupertraitOf::Trait
),
return err(warnings, errors),
warnings,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[[package]]
name = 'superabi_contract_call1'
source = 'member'
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[project]
name = "superabi_contract_call1"
authors = ["Fuel Labs <[email protected]>"]
entry = "main.sw"
license = "Apache-2.0"
implicit-std = false
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
contract;

abi MySuperAbi {
fn super_abi_method();
}

abi MyAbi : MySuperAbi {
fn abi_method();
} {
// this must fail, because contract methods cannot call each other
fn foo() { Self::super_abi_method() }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
category = "fail"

# check: $()No method named "super_abi_method" found for type "contract".
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[[package]]
name = 'superabi_contract_call2'
source = 'member'
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[project]
name = "superabi_contract_call2"
authors = ["Fuel Labs <[email protected]>"]
entry = "main.sw"
license = "Apache-2.0"
implicit-std = false
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
contract;

abi MySuperAbi {
fn super_abi_method();
}

abi MyAbi : MySuperAbi {
fn abi_method();
}

impl MySuperAbi for Contract {
fn super_abi_method() { }
}

impl MyAbi for Contract {
// this must fail, because contract methods cannot call each other
fn abi_method() { Self::super_abi_method() }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
category = "fail"

# check: $()No method named "super_abi_method" found for type "contract".
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[[package]]
name = 'superabi_trait'
source = 'member'
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[project]
name = "superabi_trait"
authors = ["Fuel Labs <[email protected]>"]
entry = "main.sw"
license = "Apache-2.0"
implicit-std = false
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"configurables": [],
"functions": [
{
"attributes": null,
"inputs": [],
"name": "bar",
"output": {
"name": "",
"type": 0,
"typeArguments": null
}
},
{
"attributes": null,
"inputs": [],
"name": "baz",
"output": {
"name": "",
"type": 0,
"typeArguments": null
}
}
],
"loggedTypes": [],
"messagesTypes": [],
"types": [
{
"components": [],
"type": "()",
"typeId": 0,
"typeParameters": null
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
contract;

abi MySuperAbi {
fn super_abi_method();
}

// error: traits cannot have superABIs
trait MyAbi : MySuperAbi {
fn abi_method();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
category = "fail"

# check: $()A trait cannot be a subtrait of an ABI.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[[package]]
name = 'superabi_unimplemented'
source = 'member'
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[project]
name = "superabi_unimplemented"
authors = ["Fuel Labs <[email protected]>"]
entry = "main.sw"
license = "Apache-2.0"
implicit-std = false
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"configurables": [],
"functions": [
{
"attributes": null,
"inputs": [],
"name": "bar",
"output": {
"name": "",
"type": 0,
"typeArguments": null
}
},
{
"attributes": null,
"inputs": [],
"name": "baz",
"output": {
"name": "",
"type": 0,
"typeArguments": null
}
}
],
"loggedTypes": [],
"messagesTypes": [],
"types": [
{
"components": [],
"type": "()",
"typeId": 0,
"typeParameters": null
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
contract;

abi MySuperAbi {
fn super_abi_method();
}

abi MyAbi : MySuperAbi {
fn abi_method();
}

// The implementation of MyAbi for Contract must also implement MySuperAbi
// impl MySuperAbi for Contract {
// ...
// }

impl MyAbi for Contract {
fn abi_method() { }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
category = "fail"

# check: $()Trait "MySuperAbi" is not implemented for type "contract".
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[[package]]
name = 'superabi'
source = 'member'
Loading

0 comments on commit 77b6d25

Please sign in to comment.