diff --git a/move-compiler/src/sui_mode/mod.rs b/move-compiler/src/sui_mode/mod.rs index e0ffbc469a..8a7b257697 100644 --- a/move-compiler/src/sui_mode/mod.rs +++ b/move-compiler/src/sui_mode/mod.rs @@ -49,6 +49,7 @@ pub const TRANSFER_MODULE_NAME: Symbol = symbol!("transfer"); pub const TRANSFER_FUNCTION_NAME: Symbol = symbol!("transfer"); pub const FREEZE_FUNCTION_NAME: Symbol = symbol!("freeze_object"); pub const SHARE_FUNCTION_NAME: Symbol = symbol!("share_object"); +pub const RECEIVING_TYPE_NAME: Symbol = symbol!("Receiving"); pub const PRIVATE_TRANSFER_FUNCTIONS: &[Symbol] = &[ TRANSFER_FUNCTION_NAME, diff --git a/move-compiler/src/sui_mode/typing.rs b/move-compiler/src/sui_mode/typing.rs index 5a056a0acb..746884fc7b 100644 --- a/move-compiler/src/sui_mode/typing.rs +++ b/move-compiler/src/sui_mode/typing.rs @@ -641,7 +641,9 @@ fn entry_param_ty( // which should give a contextual error about `MyObject` having `key`, but the instantiation // `MyObject` not having `key` due to `InnerTypeWithoutStore` not having // `store` - let is_valid = is_entry_primitive_ty(param_ty) || is_entry_object_ty(param_ty); + let is_valid = is_entry_primitive_ty(param_ty) + || is_entry_object_ty(param_ty) + || is_entry_receiving_ty(param_ty); if is_mut_clock || !is_valid { let pmsg = format!( "Invalid 'entry' parameter type for parameter '{}'", @@ -656,7 +658,7 @@ fn entry_param_ty( ) } else { "'entry' parameters must be primitives (by-value), vectors of primitives, objects \ - (by-reference or by-value), or vectors of objects" + (by-reference or by-value), vectors of objects, or 'Receiving' arguments (by-reference or by-value)" .to_owned() }; let emsg = format!("'{name}' was declared 'entry' here"); @@ -682,6 +684,22 @@ fn is_mut_clock(param_ty: &Type) -> bool { } } +fn is_entry_receiving_ty(param_ty: &Type) -> bool { + match ¶m_ty.value { + Type_::Ref(_, t) => is_entry_receiving_ty(t), + Type_::Apply(_, sp!(_, n), targs) + if n.is(SUI_ADDR_NAME, TRANSFER_MODULE_NAME, RECEIVING_TYPE_NAME) => + { + debug_assert!(targs.len() == 1); + // Don't care about the type parameter, just that it's a receiving type -- since it has + // a `key` requirement on the type parameter it must be an object or type checking will + // fail. + true + } + _ => false, + } +} + fn is_entry_primitive_ty(param_ty: &Type) -> bool { use BuiltinTypeName_ as B; use TypeName_ as N; diff --git a/move-compiler/tests/sui_mode/entry_points/generic_obj_mut_ref_vector.exp b/move-compiler/tests/sui_mode/entry_points/generic_obj_mut_ref_vector.exp index 2905c590e4..606e3b0305 100644 --- a/move-compiler/tests/sui_mode/entry_points/generic_obj_mut_ref_vector.exp +++ b/move-compiler/tests/sui_mode/entry_points/generic_obj_mut_ref_vector.exp @@ -2,7 +2,7 @@ error[Sui E02002]: invalid 'entry' function signature ┌─ tests/sui_mode/entry_points/generic_obj_mut_ref_vector.move:5:32 │ 5 │ public entry fun no(_: &mut vector) { - │ ----- ^ -------------- 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), or vectors of objects + │ ----- ^ -------------- 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), vectors of objects, or 'Receiving' arguments (by-reference or by-value) │ │ │ │ │ Invalid 'entry' parameter type for parameter '_' │ 'no' was declared 'entry' here diff --git a/move-compiler/tests/sui_mode/entry_points/generic_obj_ref_vector.exp b/move-compiler/tests/sui_mode/entry_points/generic_obj_ref_vector.exp index 38fee9c595..323d92010f 100644 --- a/move-compiler/tests/sui_mode/entry_points/generic_obj_ref_vector.exp +++ b/move-compiler/tests/sui_mode/entry_points/generic_obj_ref_vector.exp @@ -2,7 +2,7 @@ error[Sui E02002]: invalid 'entry' function signature ┌─ tests/sui_mode/entry_points/generic_obj_ref_vector.move:4:32 │ 4 │ public entry fun no(_: &vector) { - │ ----- ^ ---------- 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), or vectors of objects + │ ----- ^ ---------- 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), vectors of objects, or 'Receiving' arguments (by-reference or by-value) │ │ │ │ │ Invalid 'entry' parameter type for parameter '_' │ 'no' was declared 'entry' here diff --git a/move-compiler/tests/sui_mode/entry_points/generic_with_key_invalid.exp b/move-compiler/tests/sui_mode/entry_points/generic_with_key_invalid.exp index 91443f5c8c..5e9ceb81a4 100644 --- a/move-compiler/tests/sui_mode/entry_points/generic_with_key_invalid.exp +++ b/move-compiler/tests/sui_mode/entry_points/generic_with_key_invalid.exp @@ -2,7 +2,7 @@ error[Sui E02002]: invalid 'entry' function signature ┌─ tests/sui_mode/entry_points/generic_with_key_invalid.move:6:31 │ 6 │ public entry fun t(_: option::Option) { - │ ----- ^ ----------------- 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), or vectors of objects + │ ----- ^ ----------------- 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), vectors of objects, or 'Receiving' arguments (by-reference or by-value) │ │ │ │ │ Invalid 'entry' parameter type for parameter '_' │ 't' was declared 'entry' here @@ -11,7 +11,7 @@ error[Sui E02002]: invalid 'entry' function signature ┌─ tests/sui_mode/entry_points/generic_with_key_invalid.move:10:32 │ 10 │ public entry fun t2(_: vector>) { - │ ----- ^ ------------------------- 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), or vectors of objects + │ ----- ^ ------------------------- 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), vectors of objects, or 'Receiving' arguments (by-reference or by-value) │ │ │ │ │ Invalid 'entry' parameter type for parameter '_' │ 't2' was declared 'entry' here diff --git a/move-compiler/tests/sui_mode/entry_points/immut_receiving_ref.move b/move-compiler/tests/sui_mode/entry_points/immut_receiving_ref.move new file mode 100644 index 0000000000..3af390d56a --- /dev/null +++ b/move-compiler/tests/sui_mode/entry_points/immut_receiving_ref.move @@ -0,0 +1,22 @@ +// valid, Receiving type by immut ref with object type param + +module a::m { + use sui::object; + use sui::transfer::Receiving; + + struct S has key { id: object::UID } + + public entry fun yes(_: &Receiving) { } +} + +module sui::object { + struct UID has store { + id: address, + } +} + +module sui::transfer { + struct Receiving has drop { + id: address + } +} diff --git a/move-compiler/tests/sui_mode/entry_points/mut_receiving_ref.move b/move-compiler/tests/sui_mode/entry_points/mut_receiving_ref.move new file mode 100644 index 0000000000..fbaead9a07 --- /dev/null +++ b/move-compiler/tests/sui_mode/entry_points/mut_receiving_ref.move @@ -0,0 +1,22 @@ +// valid, Receiving type by mut ref with object type param + +module a::m { + use sui::object; + use sui::transfer::Receiving; + + struct S has key { id: object::UID } + + public entry fun yes(_: &mut Receiving) { } +} + +module sui::object { + struct UID has store { + id: address, + } +} + +module sui::transfer { + struct Receiving has drop { + id: address + } +} diff --git a/move-compiler/tests/sui_mode/entry_points/nested_key_generic_vector_param.exp b/move-compiler/tests/sui_mode/entry_points/nested_key_generic_vector_param.exp index 53cc2246ed..5600e180cd 100644 --- a/move-compiler/tests/sui_mode/entry_points/nested_key_generic_vector_param.exp +++ b/move-compiler/tests/sui_mode/entry_points/nested_key_generic_vector_param.exp @@ -2,7 +2,7 @@ error[Sui E02002]: invalid 'entry' function signature ┌─ tests/sui_mode/entry_points/nested_key_generic_vector_param.move:3:34 │ 3 │ public entry fun foo(_: vector>) { - │ ----- ^ ----------------- 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), or vectors of objects + │ ----- ^ ----------------- 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), vectors of objects, or 'Receiving' arguments (by-reference or by-value) │ │ │ │ │ Invalid 'entry' parameter type for parameter '_' │ 'foo' was declared 'entry' here diff --git a/move-compiler/tests/sui_mode/entry_points/non_key_struct.exp b/move-compiler/tests/sui_mode/entry_points/non_key_struct.exp index e5a5dc3124..9c37637512 100644 --- a/move-compiler/tests/sui_mode/entry_points/non_key_struct.exp +++ b/move-compiler/tests/sui_mode/entry_points/non_key_struct.exp @@ -2,7 +2,7 @@ error[Sui E02002]: invalid 'entry' function signature ┌─ tests/sui_mode/entry_points/non_key_struct.move:6:25 │ 6 │ public entry fun no(_: S) { - │ ----- ^ - 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), or vectors of objects + │ ----- ^ - 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), vectors of objects, or 'Receiving' arguments (by-reference or by-value) │ │ │ │ │ Invalid 'entry' parameter type for parameter '_' │ 'no' was declared 'entry' here diff --git a/move-compiler/tests/sui_mode/entry_points/non_key_struct_generic.exp b/move-compiler/tests/sui_mode/entry_points/non_key_struct_generic.exp index 7199dc2e4a..8b4c4a45d2 100644 --- a/move-compiler/tests/sui_mode/entry_points/non_key_struct_generic.exp +++ b/move-compiler/tests/sui_mode/entry_points/non_key_struct_generic.exp @@ -2,7 +2,7 @@ error[Sui E02002]: invalid 'entry' function signature ┌─ tests/sui_mode/entry_points/non_key_struct_generic.move:9:25 │ 9 │ public entry fun t1(_: Obj) { - │ ----- ^ ------------ 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), or vectors of objects + │ ----- ^ ------------ 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), vectors of objects, or 'Receiving' arguments (by-reference or by-value) │ │ │ │ │ Invalid 'entry' parameter type for parameter '_' │ 't1' was declared 'entry' here @@ -11,7 +11,7 @@ error[Sui E02002]: invalid 'entry' function signature ┌─ tests/sui_mode/entry_points/non_key_struct_generic.move:14:28 │ 14 │ public entry fun t2(_: Obj) { - │ ----- ^ ------ 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), or vectors of objects + │ ----- ^ ------ 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), vectors of objects, or 'Receiving' arguments (by-reference or by-value) │ │ │ │ │ Invalid 'entry' parameter type for parameter '_' │ 't2' was declared 'entry' here diff --git a/move-compiler/tests/sui_mode/entry_points/non_key_struct_vector.exp b/move-compiler/tests/sui_mode/entry_points/non_key_struct_vector.exp index 824114c7ed..f3d21d93e4 100644 --- a/move-compiler/tests/sui_mode/entry_points/non_key_struct_vector.exp +++ b/move-compiler/tests/sui_mode/entry_points/non_key_struct_vector.exp @@ -2,7 +2,7 @@ error[Sui E02002]: invalid 'entry' function signature ┌─ tests/sui_mode/entry_points/non_key_struct_vector.move:6:25 │ 6 │ public entry fun no(_: vector) { - │ ----- ^ --------- 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), or vectors of objects + │ ----- ^ --------- 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), vectors of objects, or 'Receiving' arguments (by-reference or by-value) │ │ │ │ │ Invalid 'entry' parameter type for parameter '_' │ 'no' was declared 'entry' here diff --git a/move-compiler/tests/sui_mode/entry_points/obj_mut_ref_vector.exp b/move-compiler/tests/sui_mode/entry_points/obj_mut_ref_vector.exp index 135d377806..8a7d091e35 100644 --- a/move-compiler/tests/sui_mode/entry_points/obj_mut_ref_vector.exp +++ b/move-compiler/tests/sui_mode/entry_points/obj_mut_ref_vector.exp @@ -2,7 +2,7 @@ error[Sui E02002]: invalid 'entry' function signature ┌─ tests/sui_mode/entry_points/obj_mut_ref_vector.move:8:25 │ 8 │ public entry fun no(_: &mut vector) { - │ ----- ^ -------------- 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), or vectors of objects + │ ----- ^ -------------- 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), vectors of objects, or 'Receiving' arguments (by-reference or by-value) │ │ │ │ │ Invalid 'entry' parameter type for parameter '_' │ 'no' was declared 'entry' here diff --git a/move-compiler/tests/sui_mode/entry_points/obj_ref_vector.exp b/move-compiler/tests/sui_mode/entry_points/obj_ref_vector.exp index 8f6e4cff22..8f772bd613 100644 --- a/move-compiler/tests/sui_mode/entry_points/obj_ref_vector.exp +++ b/move-compiler/tests/sui_mode/entry_points/obj_ref_vector.exp @@ -2,7 +2,7 @@ error[Sui E02002]: invalid 'entry' function signature ┌─ tests/sui_mode/entry_points/obj_ref_vector.move:8:25 │ 8 │ public entry fun no(_: &vector) { - │ ----- ^ ---------- 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), or vectors of objects + │ ----- ^ ---------- 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), vectors of objects, or 'Receiving' arguments (by-reference or by-value) │ │ │ │ │ Invalid 'entry' parameter type for parameter '_' │ 'no' was declared 'entry' here diff --git a/move-compiler/tests/sui_mode/entry_points/receiving_non_object_type.exp b/move-compiler/tests/sui_mode/entry_points/receiving_non_object_type.exp new file mode 100644 index 0000000000..3422c96ab4 --- /dev/null +++ b/move-compiler/tests/sui_mode/entry_points/receiving_non_object_type.exp @@ -0,0 +1,12 @@ +error[E05001]: ability constraint not satisfied + ┌─ tests/sui_mode/entry_points/receiving_non_object_type.move:6:28 + │ + 6 │ public entry fun no(_: Receiving) { abort 0 } + │ ^^^^^^^^^^^^^^ + │ │ │ + │ │ The type 'u64' does not have the ability 'key' + │ 'key' constraint not satisifed + · +10 │ struct Receiving has drop { + │ --- 'key' constraint declared here + diff --git a/move-compiler/tests/sui_mode/entry_points/receiving_non_object_type.move b/move-compiler/tests/sui_mode/entry_points/receiving_non_object_type.move new file mode 100644 index 0000000000..56aad03267 --- /dev/null +++ b/move-compiler/tests/sui_mode/entry_points/receiving_non_object_type.move @@ -0,0 +1,13 @@ +// invalid, Receiving type with non-object type param + +module a::m { + use sui::transfer::Receiving; + + public entry fun no(_: Receiving) { abort 0 } +} + +module sui::transfer { + struct Receiving has drop { + id: address + } +} diff --git a/move-compiler/tests/sui_mode/entry_points/receiving_with_object_type.move b/move-compiler/tests/sui_mode/entry_points/receiving_with_object_type.move new file mode 100644 index 0000000000..9979bdc607 --- /dev/null +++ b/move-compiler/tests/sui_mode/entry_points/receiving_with_object_type.move @@ -0,0 +1,22 @@ +// valid, Receiving type with object type param + +module a::m { + use sui::object; + use sui::transfer::Receiving; + + struct S has key { id: object::UID } + + public entry fun yes(_: Receiving) { } +} + +module sui::object { + struct UID has store { + id: address, + } +} + +module sui::transfer { + struct Receiving has drop { + id: address + } +} diff --git a/move-symbol-pool/src/lib.rs b/move-symbol-pool/src/lib.rs index ea7749f17c..688e1a8d9a 100644 --- a/move-symbol-pool/src/lib.rs +++ b/move-symbol-pool/src/lib.rs @@ -78,6 +78,7 @@ static_symbols!( "share_object", "event", "emit", + "Receiving", ); /// The global, unique cache of strings.