Skip to content

Commit

Permalink
Merge branch 'master' into laishaw/sway-reference
Browse files Browse the repository at this point in the history
  • Loading branch information
K1-R1 authored Sep 5, 2024
2 parents 3f70909 + 8959f11 commit 3e0009c
Show file tree
Hide file tree
Showing 54 changed files with 655 additions and 64 deletions.
13 changes: 13 additions & 0 deletions forc-plugins/forc-client/test/data/standalone_contract/Forc.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[[package]]
name = "core"
source = "path+from-root-79BB3EA8498403DE"

[[package]]
name = "standalone_contract"
source = "member"
dependencies = ["std"]

[[package]]
name = "std"
source = "path+from-root-79BB3EA8498403DE"
dependencies = ["core"]
8 changes: 4 additions & 4 deletions forc-plugins/forc-client/tests/deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ async fn test_simple_deploy() {
node.kill().unwrap();
let expected = vec![DeployedContract {
id: ContractId::from_str(
"ad0bba17e0838ef859abe2693d8a5e3bc4e7cfb901601e30f4dc34999fda6335",
"50fe882cbef5f3da6da82509a66b7e5e0a64a40d70164861c01c908a332198ae",
)
.unwrap(),
proxy: None,
Expand Down Expand Up @@ -383,7 +383,7 @@ async fn test_deploy_submit_only() {
node.kill().unwrap();
let expected = vec![DeployedContract {
id: ContractId::from_str(
"ad0bba17e0838ef859abe2693d8a5e3bc4e7cfb901601e30f4dc34999fda6335",
"50fe882cbef5f3da6da82509a66b7e5e0a64a40d70164861c01c908a332198ae",
)
.unwrap(),
proxy: None,
Expand Down Expand Up @@ -428,12 +428,12 @@ async fn test_deploy_fresh_proxy() {
node.kill().unwrap();
let impl_contract = DeployedContract {
id: ContractId::from_str(
"ad0bba17e0838ef859abe2693d8a5e3bc4e7cfb901601e30f4dc34999fda6335",
"50fe882cbef5f3da6da82509a66b7e5e0a64a40d70164861c01c908a332198ae",
)
.unwrap(),
proxy: Some(
ContractId::from_str(
"f2d67efbd6038c85ddaffdcdc859770d8bd20eeec8e3909911f1446b2ec9f764",
"9c50c6837ba29508ad1b0fb01953892031218b5a08be73925ca5c0148e00a186",
)
.unwrap(),
),
Expand Down
6 changes: 4 additions & 2 deletions sway-core/src/abi_generation/abi_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@ impl TypeId {
&*type_engine.get(resolved_type_id),
) {
(TypeInfo::Custom { .. }, TypeInfo::Struct { .. })
| (TypeInfo::Custom { .. }, TypeInfo::Enum { .. })
| (TypeInfo::Custom { .. }, TypeInfo::Alias { .. }) => type_engine
| (TypeInfo::Custom { .. }, TypeInfo::Enum { .. }) => type_engine
.get(resolved_type_id)
.abi_str(ctx, engines, true),
(_, TypeInfo::Alias { ty, .. }) => {
ty.type_id.get_abi_type_str(ctx, engines, ty.type_id)
}
(TypeInfo::Tuple(fields), TypeInfo::Tuple(resolved_fields)) => {
assert_eq!(fields.len(), resolved_fields.len());
let field_strs = resolved_fields
Expand Down
2 changes: 1 addition & 1 deletion sway-core/src/ir_generation/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 +635,7 @@ fn compile_fn(
// recent instruction was a RET.
let already_returns = compiler
.current_block
.is_terminated_by_ret_or_revert(context);
.is_terminated_by_return_or_revert(context);
if !already_returns
&& (compiler.current_block.num_instructions(context) > 0
|| compiler.current_block == compiler.function.get_entry_block(context)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1855,14 +1855,7 @@ fn type_check_smo(
);
let data = ty::TyExpression::type_check(handler, ctx.by_ref(), &arguments[1])?;

// Type check the third argument which is the output index, so it has to be a `u64`.
let mut ctx = ctx.by_ref().with_type_annotation(type_engine.insert(
engines,
TypeInfo::UnsignedInteger(IntegerBits::SixtyFour),
None,
));

// Type check the fourth argument which is the amount of coins to send, so it has to be a `u64`.
// Type check the third argument which is the amount of coins to send, so it has to be a `u64`.
let mut ctx = ctx.by_ref().with_type_annotation(type_engine.insert(
engines,
TypeInfo::UnsignedInteger(IntegerBits::SixtyFour),
Expand All @@ -1881,20 +1874,37 @@ fn type_check_smo(
))
}

/// Signature: `__contract_call<T>()`
/// Description: Calls another contract
/// Signature: `__contract_ret(ptr: raw_ptr, len: u64) -> !`
/// Description: Returns from contract. The returned data is located at the memory location `ptr` and has
/// the length of `len` bytes.
/// Constraints: None.
fn type_check_contract_ret(
handler: &Handler,
mut ctx: TypeCheckContext,
_kind: sway_ast::Intrinsic,
kind: sway_ast::Intrinsic,
arguments: &[Expression],
_type_arguments: &[TypeArgument],
_span: Span,
type_arguments: &[TypeArgument],
span: Span,
) -> Result<(ty::TyIntrinsicFunctionKind, TypeId), ErrorEmitted> {
let type_engine = ctx.engines.te();
let engines = ctx.engines();

if arguments.len() != 2 {
return Err(handler.emit_err(CompileError::IntrinsicIncorrectNumArgs {
name: kind.to_string(),
expected: 2,
span,
}));
}

if !type_arguments.is_empty() {
return Err(handler.emit_err(CompileError::IntrinsicIncorrectNumTArgs {
name: kind.to_string(),
expected: 0,
span,
}));
}

let arguments: Vec<ty::TyExpression> = arguments
.iter()
.map(|x| {
Expand All @@ -1906,17 +1916,14 @@ fn type_check_contract_ret(
})
.collect::<Result<Vec<_>, _>>()?;

let t = ctx
.engines
.te()
.insert(ctx.engines, TypeInfo::Tuple(vec![]), None);
let t = ctx.engines.te().insert(ctx.engines, TypeInfo::Never, None);

Ok((
ty::TyIntrinsicFunctionKind {
kind: Intrinsic::ContractRet,
arguments,
type_arguments: vec![],
span: Span::dummy(),
span,
},
t,
))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,17 @@ pub(crate) fn instantiate_function_application(
&function_decl.parameters,
)?;

// unify function return type with current ctx.type_annotation().
engines.te().unify_with_generic(
handler,
engines,
function_decl.return_type.type_id,
ctx.type_annotation(),
&call_path_binding.span(),
"Function return type does not match up with local type annotation.",
None,
);

let mut function_return_type_id = function_decl.return_type.type_id;

let function_ident: IdentUnique = function_decl.name.clone().into();
Expand Down
5 changes: 4 additions & 1 deletion sway-core/src/type_system/unify/unify_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,10 @@ impl<'a> UnifyCheck<'a> {
parent: _,
is_from_type_parameter: _,
},
) => rtc.eq(ltc, &PartialEqWithEnginesContext::new(self.engines)),
) => {
matches!(self.mode, NonGenericConstraintSubset)
|| rtc.eq(ltc, &PartialEqWithEnginesContext::new(self.engines))
}

// any type can be coerced into a generic,
// except if the type already contains the generic
Expand Down
13 changes: 10 additions & 3 deletions sway-ir/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -369,14 +369,21 @@ impl Block {
}
}

/// Return whether this block is already terminated specifically by a Ret instruction.
pub fn is_terminated_by_ret_or_revert(&self, context: &Context) -> bool {
/// Return whether this block is already terminated by non-branching instructions,
/// means with instructions that cause either revert, or local or context returns.
/// Those instructions are: [InstOp::Ret], [FuelVmInstruction::Retd],
/// [FuelVmInstruction::JmpMem], and [FuelVmInstruction::Revert]).
pub fn is_terminated_by_return_or_revert(&self, context: &Context) -> bool {
self.get_terminator(context).map_or(false, |i| {
matches!(
i,
Instruction {
op: InstOp::Ret(..)
| InstOp::FuelVm(FuelVmInstruction::Revert(..) | FuelVmInstruction::JmpMem),
| InstOp::FuelVm(
FuelVmInstruction::Revert(..)
| FuelVmInstruction::JmpMem
| FuelVmInstruction::Retd { .. }
),
..
}
)
Expand Down
13 changes: 10 additions & 3 deletions sway-ir/src/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,6 @@ impl InstOp {
InstOp::FuelVm(FuelVmInstruction::Log { .. }) => Some(Type::get_unit(context)),
InstOp::FuelVm(FuelVmInstruction::ReadRegister(_)) => Some(Type::get_uint64(context)),
InstOp::FuelVm(FuelVmInstruction::Smo { .. }) => Some(Type::get_unit(context)),
InstOp::FuelVm(FuelVmInstruction::Retd { .. }) => None,

// Load needs to strip the pointer from the source type.
InstOp::Load(ptr_val) => match &context.values[ptr_val.0].value {
Expand All @@ -310,7 +309,11 @@ impl InstOp {
// These are all terminators which don't return, essentially. No type.
InstOp::Branch(_)
| InstOp::ConditionalBranch { .. }
| InstOp::FuelVm(FuelVmInstruction::Revert(..) | FuelVmInstruction::JmpMem)
| InstOp::FuelVm(
FuelVmInstruction::Revert(..)
| FuelVmInstruction::JmpMem
| FuelVmInstruction::Retd { .. },
)
| InstOp::Ret(..) => None,

// No-op is also no-type.
Expand Down Expand Up @@ -692,7 +695,11 @@ impl InstOp {
InstOp::Branch(_)
| InstOp::ConditionalBranch { .. }
| InstOp::Ret(..)
| InstOp::FuelVm(FuelVmInstruction::Revert(..) | FuelVmInstruction::JmpMem)
| InstOp::FuelVm(
FuelVmInstruction::Revert(..)
| FuelVmInstruction::JmpMem
| FuelVmInstruction::Retd { .. }
)
)
}
}
Expand Down
10 changes: 2 additions & 8 deletions sway-ir/src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::{
block::BlockArgument,
constant::Constant,
context::Context,
instruction::{FuelVmInstruction, InstOp},
instruction::InstOp,
irtype::Type,
metadata::{combine, MetadataIndex},
pretty::DebugWithContext,
Expand Down Expand Up @@ -102,13 +102,7 @@ impl Value {
/// and is either a branch or return.
pub fn is_terminator(&self, context: &Context) -> bool {
match &context.values[self.0].value {
ValueDatum::Instruction(Instruction { op, .. }) => matches!(
op,
InstOp::Branch(_)
| InstOp::ConditionalBranch { .. }
| InstOp::Ret(_, _)
| InstOp::FuelVm(FuelVmInstruction::Revert(_) | FuelVmInstruction::JmpMem)
),
ValueDatum::Instruction(Instruction { op, .. }) => op.is_terminator(),
ValueDatum::Argument(..) | ValueDatum::Constant(..) => false,
}
}
Expand Down
14 changes: 14 additions & 0 deletions sway-lib-std/src/primitive_conversions/str.sw
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,20 @@ library;
use ::option::Option::{self, *};

impl str {
/// Attempts to convert the string slice into a string array.
///
/// # Returns
///
/// * [Option<S>] - `Some(str_array)` if the lengths of the `S` str_array type and the string slice's lengths match. Else `None`.
///
/// # Examples
///
/// ```sway
/// fn foo() {
/// let string_slice = "abcd";
/// let string_array: str[4] = a.try_as_str_array().unwrap();
/// }
/// ```
pub fn try_as_str_array<S>(self) -> Option<S> {
__assert_is_str_array::<S>();
let str_size = __size_of_str_array::<S>();
Expand Down
22 changes: 22 additions & 0 deletions sway-lib-std/src/primitive_conversions/u16.sw
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,28 @@ use ::option::Option::{self, *};
use ::u128::U128;

impl u16 {
/// Attempts to convert the u16 value into a u8 value.
///
/// # Additional Information
///
/// The max value a u8 can represent is 255.
///
/// # Returns
///
/// [Option<u8>] - `Some(u8)` if the u16 is less than or equal to the max u8 value. Else `None`.
///
/// # Examples
///
/// ```sway
/// fn foo() {
/// let val = 255_u16.try_as_u8();
/// assert(val == Some(255_u8));
///
/// // Conversion fails as value is above the max a u8 can represent.
/// let val2 = 256_u16.try_as_u8();
/// assert(val == None);
/// }
/// ```
pub fn try_as_u8(self) -> Option<u8> {
if self <= u8::max().as_u16() {
Some(asm(input: self) {
Expand Down
44 changes: 44 additions & 0 deletions sway-lib-std/src/primitive_conversions/u32.sw
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,28 @@ use ::option::Option::{self, *};
use ::u128::U128;

impl u32 {
/// Attempts to convert the u32 value into a u8 value.
///
/// # Additional Information
///
/// The max value a u8 can represent is 255.
///
/// # Returns
///
/// [Option<u8>] - `Some(u8)` if the u32 is less than or equal to the max u8 value. Else `None`.
///
/// # Examples
///
/// ```sway
/// fn foo() {
/// let val = 255_u32.try_as_u8();
/// assert(val == Some(255_u8));
///
/// // Conversion fails as value is above the max a u8 can represent.
/// let val2 = 256_u32.try_as_u8();
/// assert(val == None);
/// }
/// ```
pub fn try_as_u8(self) -> Option<u8> {
if self <= u8::max().as_u32() {
Some(asm(input: self) {
Expand All @@ -15,6 +37,28 @@ impl u32 {
}
}

/// Attempts to convert the u32 value into a u16 value.
///
/// # Additional Information
///
/// The max value a u16 can represent is 65_535.
///
/// # Returns
///
/// [Option<u16>] - `Some(u16)` if the u32 is less than or equal to the max u16 value. Else `None`.
///
/// # Examples
///
/// ```sway
/// fn foo() {
/// let val = 65_535_u32.try_as_u16();
/// assert(val == Some(65_535_u16));
///
/// // Conversion fails as value is above the max a u16 can represent.
/// let val2 = 65_536_u32.try_as_u16();
/// assert(val == None);
/// }
/// ```
pub fn try_as_u16(self) -> Option<u16> {
if self <= u16::max().as_u32() {
Some(asm(input: self) {
Expand Down
Loading

0 comments on commit 3e0009c

Please sign in to comment.