Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 17 additions & 109 deletions language/move-compiler/src/typing/translate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ use crate::{
diagnostics::{codes::*, Diagnostic},
expansion::ast::{Fields, ModuleIdent, Value_},
naming::ast::{self as N, TParam, TParamID, Type, TypeName_, Type_},
parser::ast::{
Ability_, BinOp_, ConstantName, Field, FunctionName, StructName, UnaryOp_, Var, Visibility,
},
parser::ast::{Ability_, BinOp_, ConstantName, Field, FunctionName, StructName, UnaryOp_, Var},
shared::{unique_map::UniqueMap, *},
typing::ast as T,
FullyCompiledProgram,
Expand Down Expand Up @@ -117,61 +115,6 @@ fn script(context: &mut Context, nscript: N::Script) -> T::Script {
}
}

#[derive(Clone, Copy)]
// enum representing the case for functions that are invocable by the VM script API
enum Invocable {
// a normal script block
Script,
// a public(script) function in a module
PublicScript,
}

fn check_primitive_script_arg(
context: &mut Context,
case: Invocable,
mloc: Loc,
seen_non_signer: &mut bool,
ty: &Type,
) {
let current_function = context.current_function.unwrap();
let mk_msg = move || {
format!(
"Invalid parameter for script function '{}'",
current_function
)
};
let code = match case {
Invocable::Script => TypeSafety::ScriptSignature,
Invocable::PublicScript => TypeSafety::NonInvocablePublicScript,
};

let loc = ty.loc;
let signer = Type_::signer(loc);
let is_signer = {
let old_subst = context.subst.clone();
let result = subtype_no_report(context, ty.clone(), signer.clone());
context.subst = old_subst;
result.is_ok()
};
if is_signer {
if *seen_non_signer {
let msg = mk_msg();
let tmsg = format!(
"{}s must be a prefix of the arguments to a script--they must come before any \
non-signer types",
core::error_format(&signer, &Subst::empty()),
);
context.env.add_diag(diag!(code, (mloc, msg), (loc, tmsg)));
}

return;
} else {
*seen_non_signer = true;
}

check_valid_constant::signature(context, mloc, mk_msg, code, ty);
}

//**************************************************************************************************
// Functions
//**************************************************************************************************
Expand All @@ -193,58 +136,23 @@ fn function(
assert!(context.constraints.is_empty());
context.reset_for_module_item();
context.current_function = Some(name);
let invocable_opt = match (is_script, &visibility) {
(true, _) => Some(Invocable::Script),
(_, Visibility::Script(_)) => Some(Invocable::PublicScript),
_ => None,
};

function_signature(context, &signature);
if let Some(case) = invocable_opt {
let mut seen_non_signer = false;
for (_, param_ty) in signature.parameters.iter() {
check_primitive_script_arg(context, case, loc, &mut seen_non_signer, param_ty);
}
match case {
Invocable::Script => {
subtype(
context,
loc,
|| {
let tu = core::error_format_(&Type_::Unit, &Subst::empty());
format!(
"Invalid 'script' function return type. The function entry point to a \
'script' must have the return type {}",
tu
)
},
signature.return_type.clone(),
sp(loc, Type_::Unit),
);
}
Invocable::PublicScript => {
let res =
subtype_no_report(context, signature.return_type.clone(), sp(loc, Type_::Unit));
if let Err(err) = res {
let mut diag = typing_error(
context,
true,
loc,
|| {
let tu = core::error_format_(&Type_::Unit, &Subst::empty());
format!(
"'public(script)' functions must have a return type of {} in \
order to be invocable as a script entry point",
tu,
)
},
err,
);
diag = diag.set_code(TypeSafety::NonInvocablePublicScript);
context.env.add_diag(diag)
}
}
}
if is_script {
let mk_msg = || {
let tu = core::error_format_(&Type_::Unit, &Subst::empty());
format!(
"Invalid 'script' function return type. The function entry point to a \
'script' must have the return type {}",
tu
)
};
subtype(
context,
loc,
mk_msg,
signature.return_type.clone(),
sp(loc, Type_::Unit),
);
}
expand::function_signature(context, &mut signature);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,41 +1,25 @@
error[E05001]: ability constraint not satisfied
┌─ tests/move_check/translated_ir_tests/move/signer/address_arg_is_not_signer.move:3:27
┌─ tests/move_check/translated_ir_tests/move/signer/address_arg_is_not_signer.move:5:27
3 │ struct R has key { s: signer }
5 │ struct R has key { s: signer }
│ ^^^^^^
│ │
│ Invalid field type. The struct was declared with the ability 'key' so all fields require the ability 'store'
│ The type 'signer' does not have the ability 'store'

error[E04011]: invalid script signature
┌─ tests/move_check/translated_ir_tests/move/signer/address_arg_is_not_signer.move:11:9
11 │ fun t1(s: &signer) {
│ ^^ ------- Found: '&signer'. But expected one of: 'u8', 'u64', 'u128', 'bool', 'address', 'vector<_>'
│ │
│ Invalid parameter for script function 't1'

error[E04016]: too few arguments
┌─ tests/move_check/translated_ir_tests/move/signer/address_arg_is_not_signer.move:12:9
┌─ tests/move_check/translated_ir_tests/move/signer/address_arg_is_not_signer.move:14:9
12 │ 0x2::M::store_signer(s)
14 │ 0x2::M::store_signer(s)
│ ^^^^^^^^^^^^^^^^^^^^^^^
│ │ │
│ │ Found 1 argument(s) here
│ Invalid call of '0x2::M::store_signer'. The call expected 2 argument(s) but got 1

error[E04011]: invalid script signature
┌─ tests/move_check/translated_ir_tests/move/signer/address_arg_is_not_signer.move:18:9
18 │ fun t2(_s: signer, s2: &signer) {
│ ^^ ------- Found: '&signer'. But expected one of: 'u8', 'u64', 'u128', 'bool', 'address', 'vector<_>'
│ │
│ Invalid parameter for script function 't2'

error[E04016]: too few arguments
┌─ tests/move_check/translated_ir_tests/move/signer/address_arg_is_not_signer.move:19:9
┌─ tests/move_check/translated_ir_tests/move/signer/address_arg_is_not_signer.move:21:9
19 │ 0x2::M::store_signer(s2)
21 │ 0x2::M::store_signer(s2)
│ ^^^^^^^^^^^^^^^^^^^^^^^^
│ │ │
│ │ Found 1 argument(s) here
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// script functions no longer have any built in checks outside of visibility rules

address 0x2 {
module M {
struct R has key { s: signer }
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
// script functions no longer have any built in checks outside of visibility rules

script {
fun t0(_s: signer, _s2: signer) {
}
}
// check: INVALID_MAIN_FUNCTION_SIGNATURE

script {
fun t1(_s: signer, _s2: signer, _u: u64) {
}
}
// check: INVALID_MAIN_FUNCTION_SIGNATURE

script {
fun t2(_s: signer, _u: u64, _s2: signer) {
}
}
// check: INVALID_MAIN_FUNCTION_SIGNATURE

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// script functions no longer have any built in checks outside of visibility rules

script {
fun t0(_u: u64, _s: signer) {
}
}
// check: INVALID_MAIN_FUNCTION_SIGNATURE

script {
fun t1(_u: u64, _s: signer, _u2: u64) {
}
}
// check: INVALID_MAIN_FUNCTION_SIGNATURE

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// script functions no longer have any built in checks outside of visibility rules

script {
fun t0(_s: signer, _s2: signer, _s3: signer) {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ module M {

script {
use 0x42::M::{S, R, Cup};

// script functions no longer have any built in checks outside of visibility rules
fun main<T: drop>(
_s: &signer,
_a0: T,
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
error[E04007]: incompatible types
┌─ tests/move_check/typing/main_return_type_invalid.move:2:5
┌─ tests/move_check/typing/main_return_type_not_unit.move:4:5
2 │ fun main(): u64 {
4 │ fun main(): u64 {
│ ^^^^ --- Given: 'u64'
│ │
│ Invalid 'script' function return type. The function entry point to a 'script' must have the return type '()'
Expand Down
Loading