diff --git a/crates/sui/src/unit_tests/fixtures/upgrade_errors/additive_errors_v1/Move.toml b/crates/sui/src/unit_tests/fixtures/upgrade_errors/additive_errors_v1/Move.toml new file mode 100644 index 00000000000000..70f14c105d35cd --- /dev/null +++ b/crates/sui/src/unit_tests/fixtures/upgrade_errors/additive_errors_v1/Move.toml @@ -0,0 +1,6 @@ +[package] +name = "upgrades" +edition = "2024.beta" # edition = "legacy" to use legacy (pre-2024) Move + +[addresses] +upgrades = "0x0" \ No newline at end of file diff --git a/crates/sui/src/unit_tests/fixtures/upgrade_errors/additive_errors_v1/sources/UpgradeErrors.move b/crates/sui/src/unit_tests/fixtures/upgrade_errors/additive_errors_v1/sources/UpgradeErrors.move new file mode 100644 index 00000000000000..ce4ee48300fee5 --- /dev/null +++ b/crates/sui/src/unit_tests/fixtures/upgrade_errors/additive_errors_v1/sources/UpgradeErrors.move @@ -0,0 +1,30 @@ +// Copyright (c) Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +module upgrades::upgrades { + + public struct StructToChange { + new_field: u64 // change to u32 + } + + public struct StructToRemove { + new_field: u64 + } + + public enum EnumToChange { + A, // change to B + } + + public enum EnumToRemove { + A + } + + // no public on functions + fun function_to_change(): u64 { // change to u32 return + 0 + } + + fun function_to_remove(): u64 { + 0 + } +} \ No newline at end of file diff --git a/crates/sui/src/unit_tests/fixtures/upgrade_errors/additive_errors_v2/Move.toml b/crates/sui/src/unit_tests/fixtures/upgrade_errors/additive_errors_v2/Move.toml new file mode 100644 index 00000000000000..70f14c105d35cd --- /dev/null +++ b/crates/sui/src/unit_tests/fixtures/upgrade_errors/additive_errors_v2/Move.toml @@ -0,0 +1,6 @@ +[package] +name = "upgrades" +edition = "2024.beta" # edition = "legacy" to use legacy (pre-2024) Move + +[addresses] +upgrades = "0x0" \ No newline at end of file diff --git a/crates/sui/src/unit_tests/fixtures/upgrade_errors/additive_errors_v2/sources/UpgradeErrors.move b/crates/sui/src/unit_tests/fixtures/upgrade_errors/additive_errors_v2/sources/UpgradeErrors.move new file mode 100644 index 00000000000000..bf245be199aba2 --- /dev/null +++ b/crates/sui/src/unit_tests/fixtures/upgrade_errors/additive_errors_v2/sources/UpgradeErrors.move @@ -0,0 +1,23 @@ +// Copyright (c) Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +module upgrades::upgrades { + + public struct StructToChange { + new_field: u32 // changed to u32 + } + + // public struct StructToRemove {} + + public enum EnumToChange { + B, // changed to B + } + + // public enum EnumToRemove {} + + fun function_to_change(): u32 { // changed to u32 + 0 + } + + // fun function_to_remove(): u64 {} +} \ No newline at end of file diff --git a/crates/sui/src/unit_tests/fixtures/upgrade_errors/deponly_errors_v1/Move.toml b/crates/sui/src/unit_tests/fixtures/upgrade_errors/deponly_errors_v1/Move.toml new file mode 100644 index 00000000000000..70f14c105d35cd --- /dev/null +++ b/crates/sui/src/unit_tests/fixtures/upgrade_errors/deponly_errors_v1/Move.toml @@ -0,0 +1,6 @@ +[package] +name = "upgrades" +edition = "2024.beta" # edition = "legacy" to use legacy (pre-2024) Move + +[addresses] +upgrades = "0x0" \ No newline at end of file diff --git a/crates/sui/src/unit_tests/fixtures/upgrade_errors/deponly_errors_v1/sources/UpgradeErrors.move b/crates/sui/src/unit_tests/fixtures/upgrade_errors/deponly_errors_v1/sources/UpgradeErrors.move new file mode 100644 index 00000000000000..bffe1440b6ff4f --- /dev/null +++ b/crates/sui/src/unit_tests/fixtures/upgrade_errors/deponly_errors_v1/sources/UpgradeErrors.move @@ -0,0 +1,5 @@ +// Copyright (c) Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +module upgrades::upgrades { +} \ No newline at end of file diff --git a/crates/sui/src/unit_tests/fixtures/upgrade_errors/deponly_errors_v2/Move.toml b/crates/sui/src/unit_tests/fixtures/upgrade_errors/deponly_errors_v2/Move.toml new file mode 100644 index 00000000000000..70f14c105d35cd --- /dev/null +++ b/crates/sui/src/unit_tests/fixtures/upgrade_errors/deponly_errors_v2/Move.toml @@ -0,0 +1,6 @@ +[package] +name = "upgrades" +edition = "2024.beta" # edition = "legacy" to use legacy (pre-2024) Move + +[addresses] +upgrades = "0x0" \ No newline at end of file diff --git a/crates/sui/src/unit_tests/fixtures/upgrade_errors/deponly_errors_v2/sources/UpgradeErrors.move b/crates/sui/src/unit_tests/fixtures/upgrade_errors/deponly_errors_v2/sources/UpgradeErrors.move new file mode 100644 index 00000000000000..38b7fe550fc84a --- /dev/null +++ b/crates/sui/src/unit_tests/fixtures/upgrade_errors/deponly_errors_v2/sources/UpgradeErrors.move @@ -0,0 +1,21 @@ +// Copyright (c) Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +module upgrades::upgrades { + + // created new struct + public struct NewStruct { + new_field: u64 + } + + // created new enum + public enum NewEnum { + A, + } + + // created new function + fun new_function(): u64 { + 0 + } + +} \ No newline at end of file diff --git a/crates/sui/src/unit_tests/snapshots/sui__upgrade_compatibility__upgrade_compatibility_tests__additive.snap b/crates/sui/src/unit_tests/snapshots/sui__upgrade_compatibility__upgrade_compatibility_tests__additive.snap new file mode 100644 index 00000000000000..6dfd7a009a1523 --- /dev/null +++ b/crates/sui/src/unit_tests/snapshots/sui__upgrade_compatibility__upgrade_compatibility_tests__additive.snap @@ -0,0 +1,53 @@ +--- +source: crates/sui/src/unit_tests/upgrade_compatibility_tests.rs +expression: normalize_path(err.to_string()) +--- +error[Compatibility E01008]: missing declaration + ┌─ /fixtures/upgrade_errors/additive_errors_v2/sources/UpgradeErrors.move:4:18 + │ +4 │ module upgrades::upgrades { + │ ^^^^^^^^ enum 'EnumToRemove' is missing + │ + = enums cannot be removed or changed during an 'additive' or 'dependency only' upgrade. + = add missing enum 'EnumToRemove' back to the module 'upgrades'. + +error[Compatibility E01008]: missing declaration + ┌─ /fixtures/upgrade_errors/additive_errors_v2/sources/UpgradeErrors.move:4:18 + │ +4 │ module upgrades::upgrades { + │ ^^^^^^^^ function 'function_to_remove' is missing + │ + = functions cannot be removed or changed during an 'additive' or 'dependency only' upgrade. + = add missing function 'function_to_remove' back to the module 'upgrades'. + +error[Compatibility E01008]: missing declaration + ┌─ /fixtures/upgrade_errors/additive_errors_v2/sources/UpgradeErrors.move:4:18 + │ +4 │ module upgrades::upgrades { + │ ^^^^^^^^ struct 'StructToRemove' is missing + │ + = structs cannot be removed or changed during an 'additive' or 'dependency only' upgrade. + = add missing struct 'StructToRemove' back to the module 'upgrades'. + +error[Compatibility E01002]: type mismatch + ┌─ /fixtures/upgrade_errors/additive_errors_v2/sources/UpgradeErrors.move:7:9 + │ +6 │ public struct StructToChange { + │ -------------- Struct definition +7 │ new_field: u32 // changed to u32 + │ ^^^^^^^^^ Mismatched field type 'u32', expected 'u64'. + │ + = Structs cannot be removed or changed during an 'additive' or 'dependency only' upgrade. + = Restore the original struct's field for struct 'StructToChange' including the ordering. + +error[Compatibility E03001]: function signature mismatch + ┌─ /fixtures/upgrade_errors/additive_errors_v2/sources/UpgradeErrors.move:18:31 + │ +18 │ fun function_to_change(): u32 { // changed to u32 + │ ^^^ Unexpected return type 'u32', expected 'u64' + │ + = Functions cannot be removed or changed during an 'additive' or 'dependency only' upgrade. + = Restore the original function's return type for function 'function_to_change'. + + +Upgrade failed, this package requires changes to be compatible with the existing package. Its upgrade policy is set to 'additive'. diff --git a/crates/sui/src/unit_tests/snapshots/sui__upgrade_compatibility__upgrade_compatibility_tests__all.snap b/crates/sui/src/unit_tests/snapshots/sui__upgrade_compatibility__upgrade_compatibility_tests__all.snap index 2056f4bb81a290..e61275713863c8 100644 --- a/crates/sui/src/unit_tests/snapshots/sui__upgrade_compatibility__upgrade_compatibility_tests__all.snap +++ b/crates/sui/src/unit_tests/snapshots/sui__upgrade_compatibility__upgrade_compatibility_tests__all.snap @@ -8,7 +8,7 @@ error[Compatibility E01001]: missing public declaration 6 │ module upgrades::upgrades { │ ^^^^^^^^ enum 'EnumToBeRemoved' is missing │ - = enums are part of a module's public interface and cannot be removed or changed during an upgrade. + = enums are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = add missing enum 'EnumToBeRemoved' back to the module 'upgrades'. error[Compatibility E01001]: missing public declaration @@ -17,7 +17,7 @@ error[Compatibility E01001]: missing public declaration 6 │ module upgrades::upgrades { │ ^^^^^^^^ struct 'StructToBeRemoved' is missing │ - = structs are part of a module's public interface and cannot be removed or changed during an upgrade. + = structs are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = add missing struct 'StructToBeRemoved' back to the module 'upgrades'. error[Compatibility E01003]: ability mismatch @@ -26,7 +26,7 @@ error[Compatibility E01003]: ability mismatch 11 │ public struct StructAbilityMismatchAdd has copy {} // added the copy ability where none existed │ ^^^^^^^^^^^^^^^^^^^^^^^^ Unexpected ability: 'copy' │ - = Structs are part of a module's public interface and cannot be changed during an upgrade. + = Structs are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original abilities of struct 'StructAbilityMismatchAdd': none. error[Compatibility E01003]: ability mismatch @@ -35,7 +35,7 @@ error[Compatibility E01003]: ability mismatch 14 │ public struct StructAbilityMismatchRemove {} // removed the copy ability │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Missing ability: 'copy' │ - = Structs are part of a module's public interface and cannot be changed during an upgrade. + = Structs are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original ability of struct 'StructAbilityMismatchRemove': 'copy'. error[Compatibility E01003]: ability mismatch @@ -44,7 +44,7 @@ error[Compatibility E01003]: ability mismatch 17 │ public struct StructAbilityMismatchChange has drop {} // changed from drop to copy │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Mismatched abilities: missing 'copy', unexpected 'drop' │ - = Structs are part of a module's public interface and cannot be changed during an upgrade. + = Structs are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original ability of struct 'StructAbilityMismatchChange': 'copy'. error[Compatibility E01005]: type parameter mismatch @@ -53,7 +53,7 @@ error[Compatibility E01005]: type parameter mismatch 20 │ public struct StructTypeParamMismatch { a: T } // changed S to T │ ^^^^^^^^^^^^^^^^^^^^^^^ Incorrect number of type parameters: expected 2, found 1 │ - = Structs are part of a module's public interface and cannot be changed during an upgrade. + = Structs are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original struct's type parameters for struct 'StructTypeParamMismatch' including the ordering. error[Compatibility E01002]: type mismatch @@ -62,7 +62,7 @@ error[Compatibility E01002]: type mismatch 23 │ public struct StructFieldMismatchAdd { │ ^^^^^^^^^^^^^^^^^^^^^^ Incorrect number of fields: expected 2, found 3 │ - = Structs are part of a module's public interface and cannot be changed during an upgrade. + = Structs are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original struct's fields for struct 'StructFieldMismatchAdd' including the ordering. error[Compatibility E01002]: type mismatch @@ -71,7 +71,7 @@ error[Compatibility E01002]: type mismatch 30 │ public struct StructFieldMismatchRemove { │ ^^^^^^^^^^^^^^^^^^^^^^^^^ Incorrect number of fields: expected 2, found 1 │ - = Structs are part of a module's public interface and cannot be changed during an upgrade. + = Structs are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original struct's fields for struct 'StructFieldMismatchRemove' including the ordering. error[Compatibility E01002]: type mismatch @@ -83,7 +83,7 @@ error[Compatibility E01002]: type mismatch 38 │ b: u8 // changed b from u64 to u8 │ ^ Mismatched field type 'u8', expected 'u64'. │ - = Structs are part of a module's public interface and cannot be changed during an upgrade. + = Structs are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original struct's fields for struct 'StructFieldMismatchChange' including the ordering. error[Compatibility E01003]: ability mismatch @@ -92,7 +92,7 @@ error[Compatibility E01003]: ability mismatch 45 │ public enum EnumAbilityMismatchAdd has copy { │ ^^^^^^^^^^^^^^^^^^^^^^ Unexpected ability: 'copy' │ - = Enums are part of a module's public interface and cannot be changed during an upgrade. + = Enums are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original abilities of the enum: none for enum 'EnumAbilityMismatchAdd'. error[Compatibility E01003]: ability mismatch @@ -101,7 +101,7 @@ error[Compatibility E01003]: ability mismatch 50 │ public enum EnumAbilityMismatchRemove { │ ^^^^^^^^^^^^^^^^^^^^^^^^^ Missing ability: 'copy' │ - = Enums are part of a module's public interface and cannot be changed during an upgrade. + = Enums are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original ability of the enum: 'copy' for enum 'EnumAbilityMismatchRemove'. error[Compatibility E01003]: ability mismatch @@ -110,7 +110,7 @@ error[Compatibility E01003]: ability mismatch 55 │ public enum EnumAbilityMismatchChange has drop { │ ^^^^^^^^^^^^^^^^^^^^^^^^^ Mismatched abilities: missing 'copy', unexpected 'drop' │ - = Enums are part of a module's public interface and cannot be changed during an upgrade. + = Enums are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original ability of the enum: 'copy' for enum 'EnumAbilityMismatchChange'. error[Compatibility E02001]: variant mismatch @@ -122,7 +122,7 @@ error[Compatibility E02001]: variant mismatch 64 │ D // new variant │ ^ New unexpected variant 'D'. │ - = Enums are part of a module's public interface and cannot be changed during an upgrade. + = Enums are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original enum's variants for enum 'EnumNewVariant' including the ordering. error[Compatibility E02001]: variant mismatch @@ -140,7 +140,7 @@ error[Compatibility E01001]: missing public declaration 74 │ fun function_to_have_public_removed() {} │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Function 'function_to_have_public_removed' has lost its public visibility │ - = Functions are part of a module's public interface and cannot be changed during an upgrade. + = Functions are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original function's 'public' visibility for function 'function_to_have_public_removed'. error[Compatibility E03001]: function signature mismatch @@ -149,7 +149,7 @@ error[Compatibility E03001]: function signature mismatch 82 │ public fun function_add_arg(a: u64) {} │ ^^^^^^^^^^^^^^^^ Expected 0 parameters, found 1 │ - = Functions are part of a module's public interface and cannot be changed during an upgrade. + = Functions are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original function's parameters for function 'function_add_arg', expected 0 parameters. error[Compatibility E03001]: function signature mismatch @@ -158,7 +158,7 @@ error[Compatibility E03001]: function signature mismatch 85 │ public fun function_remove_arg() {} │ ^^^^^^^^^^^^^^^^^^^ Expected 1 parameter, found 0 │ - = Functions are part of a module's public interface and cannot be changed during an upgrade. + = Functions are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original function's parameter for function 'function_remove_arg', expected 1 parameter. error[Compatibility E03001]: function signature mismatch @@ -167,7 +167,7 @@ error[Compatibility E03001]: function signature mismatch 88 │ public fun function_change_arg(a: u8) {} // now has u8 instead of u64 │ ^ Unexpected parameter 'u8', expected 'u64' │ - = Functions are part of a module's public interface and cannot be changed during an upgrade. + = Functions are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original function's parameter for function 'function_change_arg'. diff --git a/crates/sui/src/unit_tests/snapshots/sui__upgrade_compatibility__upgrade_compatibility_tests__declarations_missing.snap b/crates/sui/src/unit_tests/snapshots/sui__upgrade_compatibility__upgrade_compatibility_tests__declarations_missing.snap index 02bbbb1eab5c90..9bfb076c465fb8 100644 --- a/crates/sui/src/unit_tests/snapshots/sui__upgrade_compatibility__upgrade_compatibility_tests__declarations_missing.snap +++ b/crates/sui/src/unit_tests/snapshots/sui__upgrade_compatibility__upgrade_compatibility_tests__declarations_missing.snap @@ -8,7 +8,7 @@ error[Compatibility E01001]: missing public declaration 4 │ module upgrades::enum_ { │ ^^^^^ enum 'EnumToBeRemoved' is missing │ - = enums are part of a module's public interface and cannot be removed or changed during an upgrade. + = enums are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = add missing enum 'EnumToBeRemoved' back to the module 'enum_'. error[Compatibility E01001]: missing public declaration @@ -17,7 +17,7 @@ error[Compatibility E01001]: missing public declaration 4 │ module upgrades::func_ { │ ^^^^^ public function 'fun_to_be_removed' is missing │ - = public functions are part of a module's public interface and cannot be removed or changed during an upgrade. + = public functions are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = add missing public function 'fun_to_be_removed' back to the module 'func_'. error[Compatibility E01001]: missing public declaration @@ -26,7 +26,7 @@ error[Compatibility E01001]: missing public declaration 7 │ fun fun_to_lose_public(): u64 { │ ^^^^^^^^^^^^^^^^^^ Function 'fun_to_lose_public' has lost its public visibility │ - = Functions are part of a module's public interface and cannot be changed during an upgrade. + = Functions are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original function's 'public' visibility for function 'fun_to_lose_public'. error[Compatibility E01001]: missing public declaration @@ -35,7 +35,7 @@ error[Compatibility E01001]: missing public declaration 4 │ module upgrades::struct_ { │ ^^^^^^^ struct 'StructToBeRemoved' is missing │ - = structs are part of a module's public interface and cannot be removed or changed during an upgrade. + = structs are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = add missing struct 'StructToBeRemoved' back to the module 'struct_'. error[Compatibility E01007]: module missing diff --git a/crates/sui/src/unit_tests/snapshots/sui__upgrade_compatibility__upgrade_compatibility_tests__deponly.snap b/crates/sui/src/unit_tests/snapshots/sui__upgrade_compatibility__upgrade_compatibility_tests__deponly.snap new file mode 100644 index 00000000000000..e653f6ae7be2f3 --- /dev/null +++ b/crates/sui/src/unit_tests/snapshots/sui__upgrade_compatibility__upgrade_compatibility_tests__deponly.snap @@ -0,0 +1,33 @@ +--- +source: crates/sui/src/unit_tests/upgrade_compatibility_tests.rs +expression: normalize_path(err.to_string()) +--- +error[Compatibility E01002]: type mismatch + ┌─ /fixtures/upgrade_errors/deponly_errors_v2/sources/UpgradeErrors.move:4:18 + │ +4 │ module upgrades::upgrades { + │ ^^^^^^^^ New unexpected struct 'NewStruct'. + │ + = Structs are part of a module's public interface and cannot be removed or changed during an upgrade. + = Restore the original struct 'NewStruct' including the ordering. + +error[Compatibility E02001]: variant mismatch + ┌─ /fixtures/upgrade_errors/deponly_errors_v2/sources/UpgradeErrors.move:4:18 + │ +4 │ module upgrades::upgrades { + │ ^^^^^^^^ New unexpected enum 'NewEnum'. + │ + = Enums are part of a module's public interface and cannot be changed during an upgrade. + = Restore the original enum 'NewEnum' including the ordering. + +error[Compatibility E03001]: function signature mismatch + ┌─ /fixtures/upgrade_errors/deponly_errors_v2/sources/UpgradeErrors.move:4:18 + │ +4 │ module upgrades::upgrades { + │ ^^^^^^^^ New unexpected function 'new_function'. + │ + = Functions are part of a module's public interface and cannot be changed during an upgrade. + = Restore the original function 'new_function' including the ordering. + + +Upgrade failed, this package requires changes to be compatible with the existing package. Its upgrade policy is set to 'dependency only'. diff --git a/crates/sui/src/unit_tests/snapshots/sui__upgrade_compatibility__upgrade_compatibility_tests__enum.snap b/crates/sui/src/unit_tests/snapshots/sui__upgrade_compatibility__upgrade_compatibility_tests__enum.snap index b4db9c28596727..4e5820f7e0a712 100644 --- a/crates/sui/src/unit_tests/snapshots/sui__upgrade_compatibility__upgrade_compatibility_tests__enum.snap +++ b/crates/sui/src/unit_tests/snapshots/sui__upgrade_compatibility__upgrade_compatibility_tests__enum.snap @@ -8,7 +8,7 @@ error[Compatibility E01003]: ability mismatch 9 │ public enum EnumAddAbility has copy, drop { // add drop │ ^^^^^^^^^^^^^^ Unexpected ability: 'drop' │ - = Enums are part of a module's public interface and cannot be changed during an upgrade. + = Enums are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original ability of the enum: 'copy' for enum 'EnumAddAbility'. error[Compatibility E01003]: ability mismatch @@ -17,7 +17,7 @@ error[Compatibility E01003]: ability mismatch 13 │ public enum EnumRemoveAbility has copy { // drop removed │ ^^^^^^^^^^^^^^^^^ Missing ability: 'drop' │ - = Enums are part of a module's public interface and cannot be changed during an upgrade. + = Enums are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original abilities of the enum: 'copy' and 'drop' for enum 'EnumRemoveAbility'. error[Compatibility E01003]: ability mismatch @@ -26,7 +26,7 @@ error[Compatibility E01003]: ability mismatch 17 │ public enum EnumAddAndRemoveAbility has copy, store { // change drop to store │ ^^^^^^^^^^^^^^^^^^^^^^^ Mismatched abilities: missing 'drop', unexpected 'store' │ - = Enums are part of a module's public interface and cannot be changed during an upgrade. + = Enums are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original abilities of the enum: 'copy' and 'drop' for enum 'EnumAddAndRemoveAbility'. error[Compatibility E02001]: variant mismatch @@ -38,7 +38,7 @@ error[Compatibility E02001]: variant mismatch 23 │ B, // added │ ^ New unexpected variant 'B'. │ - = Enums are part of a module's public interface and cannot be changed during an upgrade. + = Enums are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original enum's variant for enum 'EnumAddVariant' including the ordering. error[Compatibility E02001]: variant mismatch @@ -59,7 +59,7 @@ error[Compatibility E02001]: variant mismatch 33 │ C, // changed from B │ ^ Mismatched variant name 'C', expected 'B'. │ - = Enums are part of a module's public interface and cannot be changed during an upgrade. + = Enums are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original enum's variants for enum 'EnumChangeVariant' including the ordering. error[Compatibility E02001]: variant mismatch @@ -71,7 +71,7 @@ error[Compatibility E02001]: variant mismatch 38 │ C, // to be changed to C │ ^ Mismatched variant name 'C', expected 'B'. │ - = Enums are part of a module's public interface and cannot be changed during an upgrade. + = Enums are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original enum's variants for enum 'EnumChangeAndAddVariant' including the ordering. error[Compatibility E02001]: variant mismatch @@ -83,7 +83,7 @@ error[Compatibility E02001]: variant mismatch 38 │ C, // to be changed to C │ ^ New unexpected variant 'C'. │ - = Enums are part of a module's public interface and cannot be changed during an upgrade. + = Enums are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original enum's variants for enum 'EnumChangeAndAddVariant' including the ordering. error[Compatibility E02001]: variant mismatch @@ -95,7 +95,7 @@ error[Compatibility E02001]: variant mismatch 39 │ D // added │ ^ New unexpected variant 'D'. │ - = Enums are part of a module's public interface and cannot be changed during an upgrade. + = Enums are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original enum's variants for enum 'EnumChangeAndAddVariant' including the ordering. error[Compatibility E02001]: variant mismatch @@ -116,7 +116,7 @@ error[Compatibility E02001]: variant mismatch 44 │ C, // changed to C │ ^ Mismatched variant name 'C', expected 'B'. │ - = Enums are part of a module's public interface and cannot be changed during an upgrade. + = Enums are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original enum's variants for enum 'EnumChangeAndRemoveVariant' including the ordering. error[Compatibility E01003]: ability mismatch @@ -125,7 +125,7 @@ error[Compatibility E01003]: ability mismatch 49 │ public enum EnumAddAbilityWithTypes has copy, drop { // drop added │ ^^^^^^^^^^^^^^^^^^^^^^^ Unexpected ability: 'drop' │ - = Enums are part of a module's public interface and cannot be changed during an upgrade. + = Enums are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original ability of the enum: 'copy' for enum 'EnumAddAbilityWithTypes'. error[Compatibility E01003]: ability mismatch @@ -134,7 +134,7 @@ error[Compatibility E01003]: ability mismatch 53 │ public enum EnumRemoveAbilityWithTypes has copy { // drop removed │ ^^^^^^^^^^^^^^^^^^^^^^^^^^ Missing ability: 'drop' │ - = Enums are part of a module's public interface and cannot be changed during an upgrade. + = Enums are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original abilities of the enum: 'copy' and 'drop' for enum 'EnumRemoveAbilityWithTypes'. error[Compatibility E02001]: variant mismatch @@ -146,7 +146,7 @@ error[Compatibility E02001]: variant mismatch 59 │ B { b: u8 }, // added │ ^^^^^^^^^^^ New unexpected variant 'B'. │ - = Enums are part of a module's public interface and cannot be changed during an upgrade. + = Enums are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original enum's variant for enum 'EnumAddVariantWithTypes' including the ordering. error[Compatibility E02001]: variant mismatch @@ -167,7 +167,7 @@ error[Compatibility E02001]: variant mismatch 69 │ C { b: u8 }, // changed to C │ ^^^^^^^^^^^ Mismatched variant name 'C', expected 'B'. │ - = Enums are part of a module's public interface and cannot be changed during an upgrade. + = Enums are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original enum's variants for enum 'EnumChangeVariantWithTypes' including the ordering. error[Compatibility E02001]: variant mismatch @@ -179,7 +179,7 @@ error[Compatibility E02001]: variant mismatch 74 │ C { b: u8 }, // to be changed to C │ ^^^^^^^^^^^ Mismatched variant name 'C', expected 'B'. │ - = Enums are part of a module's public interface and cannot be changed during an upgrade. + = Enums are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original enum's variants for enum 'EnumChangeAndAddVariantWithTypes' including the ordering. error[Compatibility E02001]: variant mismatch @@ -191,7 +191,7 @@ error[Compatibility E02001]: variant mismatch 74 │ C { b: u8 }, // to be changed to C │ ^^^^^^^^^^^ New unexpected variant 'C'. │ - = Enums are part of a module's public interface and cannot be changed during an upgrade. + = Enums are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original enum's variants for enum 'EnumChangeAndAddVariantWithTypes' including the ordering. error[Compatibility E02001]: variant mismatch @@ -203,7 +203,7 @@ error[Compatibility E02001]: variant mismatch 75 │ D { d: u8 }, // added │ ^^^^^^^^^^^ New unexpected variant 'D'. │ - = Enums are part of a module's public interface and cannot be changed during an upgrade. + = Enums are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original enum's variants for enum 'EnumChangeAndAddVariantWithTypes' including the ordering. error[Compatibility E02001]: variant mismatch @@ -224,7 +224,7 @@ error[Compatibility E02001]: variant mismatch 80 │ C(u8), // changed to C │ ^^^^^ Mismatched variant name 'C', expected 'B'. │ - = Enums are part of a module's public interface and cannot be changed during an upgrade. + = Enums are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original enum's variants for enum 'EnumChangeAndRemoveVariantWithPositionalTypes' including the ordering. error[Compatibility E01004]: field mismatch @@ -235,7 +235,7 @@ error[Compatibility E01004]: field mismatch 85 │ A(u8), // add u8 │ ^^^^^ Mismatched variant field count, expected 0, found 1. │ - = Enums are part of a module's public interface and cannot be changed during an upgrade. + = Enums are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original enum's variants for enum 'EnumChangePositionalType' including the ordering. error[Compatibility E01004]: field mismatch @@ -247,7 +247,7 @@ error[Compatibility E01004]: field mismatch 86 │ B(u16), // to be changed to u16 │ ^^^^^^ Mismatched field 'u8' at position 0, expected 'u16'. │ - = Enums are part of a module's public interface and cannot be changed during an upgrade. + = Enums are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original enum's variants for enum 'EnumChangePositionalType' including the ordering. error[Compatibility E01004]: field mismatch @@ -259,7 +259,7 @@ error[Compatibility E01004]: field mismatch 87 │ C(u8), // removed u8 │ ^^^^^ Mismatched variant field count, expected 2, found 1. │ - = Enums are part of a module's public interface and cannot be changed during an upgrade. + = Enums are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original enum's variants for enum 'EnumChangePositionalType' including the ordering. error[Compatibility E01004]: field mismatch @@ -271,7 +271,7 @@ error[Compatibility E01004]: field mismatch 88 │ D, // removed last u8 │ ^ Mismatched variant field count, expected 1, found 0. │ - = Enums are part of a module's public interface and cannot be changed during an upgrade. + = Enums are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original enum's variants for enum 'EnumChangePositionalType' including the ordering. error[Compatibility E01004]: field mismatch @@ -282,7 +282,7 @@ error[Compatibility E01004]: field mismatch 100 │ A(ChangeFieldB), // changed to ChangeFieldB │ ^^^^^^^^^^^^^^^ Mismatched field '0x0::upgrades::ChangeFieldA' at position 0, expected '0x0::upgrades::ChangeFieldB'. │ - = Enums are part of a module's public interface and cannot be changed during an upgrade. + = Enums are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original enum's variant for enum 'EnumWithPositionalChanged' including the ordering. error[Compatibility E01004]: field mismatch @@ -297,7 +297,7 @@ error[Compatibility E01004]: field mismatch 108 │ │ }, │ ╰─────────^ Mismatched field 'z: 0x0::upgrades::ChangeFieldA', expected '0x0::upgrades::ChangeFieldB'. │ - = Enums are part of a module's public interface and cannot be changed during an upgrade. + = Enums are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original enum's variant for enum 'EnumWithNamedChanged' including the ordering. diff --git a/crates/sui/src/unit_tests/snapshots/sui__upgrade_compatibility__upgrade_compatibility_tests__function.snap b/crates/sui/src/unit_tests/snapshots/sui__upgrade_compatibility__upgrade_compatibility_tests__function.snap index 460c63b466bbde..6303dd3aee84e9 100644 --- a/crates/sui/src/unit_tests/snapshots/sui__upgrade_compatibility__upgrade_compatibility_tests__function.snap +++ b/crates/sui/src/unit_tests/snapshots/sui__upgrade_compatibility__upgrade_compatibility_tests__function.snap @@ -8,7 +8,7 @@ error[Compatibility E03001]: function signature mismatch 9 │ public fun func_with_wrong_param(a: u32): u64 { │ ^ Unexpected parameter 'u32', expected 'u64' │ - = Functions are part of a module's public interface and cannot be changed during an upgrade. + = Functions are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original function's parameter for function 'func_with_wrong_param'. error[Compatibility E03001]: function signature mismatch @@ -17,7 +17,7 @@ error[Compatibility E03001]: function signature mismatch 14 │ public fun func_with_wrong_return(): u32 { │ ^^^ Unexpected return type 'u32', expected 'u64' │ - = Functions are part of a module's public interface and cannot be changed during an upgrade. + = Functions are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original function's return type for function 'func_with_wrong_return'. error[Compatibility E03001]: function signature mismatch @@ -26,7 +26,7 @@ error[Compatibility E03001]: function signature mismatch 19 │ public fun func_with_wrong_param_and_return(a: u32): u32 { │ ^ Unexpected parameter 'u32', expected 'u64' │ - = Functions are part of a module's public interface and cannot be changed during an upgrade. + = Functions are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original function's parameter for function 'func_with_wrong_param_and_return'. error[Compatibility E03001]: function signature mismatch @@ -35,7 +35,7 @@ error[Compatibility E03001]: function signature mismatch 19 │ public fun func_with_wrong_param_and_return(a: u32): u32 { │ ^^^ Unexpected return type 'u32', expected 'u64' │ - = Functions are part of a module's public interface and cannot be changed during an upgrade. + = Functions are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original function's return type for function 'func_with_wrong_param_and_return'. error[Compatibility E03001]: function signature mismatch @@ -44,7 +44,7 @@ error[Compatibility E03001]: function signature mismatch 24 │ public fun func_with_wrong_param_length(a: u64): u64 { │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Expected 2 parameters, found 1 │ - = Functions are part of a module's public interface and cannot be changed during an upgrade. + = Functions are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original function's parameters for function 'func_with_wrong_param_length', expected 2 parameters. error[Compatibility E03001]: function signature mismatch @@ -53,7 +53,7 @@ error[Compatibility E03001]: function signature mismatch 29 │ public fun func_with_wrong_return_length(): u64 { │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Expected 2 return types, found 1 │ - = Functions are part of a module's public interface and cannot be changed during an upgrade. + = Functions are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original function's return types for function 'func_with_wrong_return_length'. error[Compatibility E03001]: function signature mismatch @@ -62,7 +62,7 @@ error[Compatibility E03001]: function signature mismatch 42 │ public fun func_with_wrong_struct_param(a: StructB): u64 { │ ^ Unexpected parameter '0x0::upgrades::StructB', expected '0x0::upgrades::StructA' │ - = Functions are part of a module's public interface and cannot be changed during an upgrade. + = Functions are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original function's parameter for function 'func_with_wrong_struct_param'. error[Compatibility E03001]: function signature mismatch @@ -71,7 +71,7 @@ error[Compatibility E03001]: function signature mismatch 47 │ public fun ref_to_value(a: u32): u64 { │ ^ Unexpected parameter 'u32', expected '&u32' │ - = Functions are part of a module's public interface and cannot be changed during an upgrade. + = Functions are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original function's parameter for function 'ref_to_value'. error[Compatibility E03001]: function signature mismatch @@ -80,7 +80,7 @@ error[Compatibility E03001]: function signature mismatch 52 │ public fun value_to_ref(a: &u32): u64 { │ ^ Unexpected parameter '&u32', expected 'u32' │ - = Functions are part of a module's public interface and cannot be changed during an upgrade. + = Functions are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original function's parameter for function 'value_to_ref'. error[Compatibility E03001]: function signature mismatch @@ -89,7 +89,7 @@ error[Compatibility E03001]: function signature mismatch 57 │ public fun mutable_to_immutable_ref(a: &u32): u64 { │ ^ Unexpected parameter '&u32', expected '&mut u32' │ - = Functions are part of a module's public interface and cannot be changed during an upgrade. + = Functions are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original function's parameter for function 'mutable_to_immutable_ref'. error[Compatibility E03001]: function signature mismatch @@ -98,7 +98,7 @@ error[Compatibility E03001]: function signature mismatch 62 │ public fun immutable_to_mutable_ref(a: &mut u32): u64 { │ ^ Unexpected parameter '&mut u32', expected '&u32' │ - = Functions are part of a module's public interface and cannot be changed during an upgrade. + = Functions are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original function's parameter for function 'immutable_to_mutable_ref'. diff --git a/crates/sui/src/unit_tests/snapshots/sui__upgrade_compatibility__upgrade_compatibility_tests__struct.snap b/crates/sui/src/unit_tests/snapshots/sui__upgrade_compatibility__upgrade_compatibility_tests__struct.snap index e8fd48dee65622..dabb1ac7c25e51 100644 --- a/crates/sui/src/unit_tests/snapshots/sui__upgrade_compatibility__upgrade_compatibility_tests__struct.snap +++ b/crates/sui/src/unit_tests/snapshots/sui__upgrade_compatibility__upgrade_compatibility_tests__struct.snap @@ -8,7 +8,7 @@ error[Compatibility E01003]: ability mismatch 10 │ public struct AddExtraAbility has copy {} // added copy │ ^^^^^^^^^^^^^^^ Unexpected ability: 'copy' │ - = Structs are part of a module's public interface and cannot be changed during an upgrade. + = Structs are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original abilities of struct 'AddExtraAbility': none. error[Compatibility E01003]: ability mismatch @@ -17,7 +17,7 @@ error[Compatibility E01003]: ability mismatch 11 │ public struct RemoveAbility has drop {} // removed copy │ ^^^^^^^^^^^^^ Missing ability: 'copy' │ - = Structs are part of a module's public interface and cannot be changed during an upgrade. + = Structs are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original abilities of struct 'RemoveAbility': 'copy' and 'drop'. error[Compatibility E01003]: ability mismatch @@ -26,7 +26,7 @@ error[Compatibility E01003]: ability mismatch 12 │ public struct AddAndRemoveAbility has drop, store {} // remove copy, add store │ ^^^^^^^^^^^^^^^^^^^ Mismatched abilities: missing 'copy', unexpected 'store' │ - = Structs are part of a module's public interface and cannot be changed during an upgrade. + = Structs are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original abilities of struct 'AddAndRemoveAbility': 'copy' and 'drop'. error[Compatibility E01003]: ability mismatch @@ -35,7 +35,7 @@ error[Compatibility E01003]: ability mismatch 13 │ public struct RemoveMultipleAbilities has drop {} // remove copy, store │ ^^^^^^^^^^^^^^^^^^^^^^^ Missing abilities: 'copy' and 'store' │ - = Structs are part of a module's public interface and cannot be changed during an upgrade. + = Structs are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original abilities of struct 'RemoveMultipleAbilities': 'copy', 'drop', and 'store'. error[Compatibility E01003]: ability mismatch @@ -44,7 +44,7 @@ error[Compatibility E01003]: ability mismatch 14 │ public struct AddMultipleAbilities has drop, copy {} │ ^^^^^^^^^^^^^^^^^^^^ Unexpected abilities: 'copy' and 'drop' │ - = Structs are part of a module's public interface and cannot be changed during an upgrade. + = Structs are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original abilities of struct 'AddMultipleAbilities': none. error[Compatibility E01002]: type mismatch @@ -53,7 +53,7 @@ error[Compatibility E01002]: type mismatch 18 │ public struct AddFieldToEmpty { │ ^^^^^^^^^^^^^^^ Incorrect number of fields: expected 0, found 1 │ - = Structs are part of a module's public interface and cannot be changed during an upgrade. + = Structs are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original struct's fields for struct 'AddFieldToEmpty' including the ordering. error[Compatibility E01002]: type mismatch @@ -62,7 +62,7 @@ error[Compatibility E01002]: type mismatch 23 │ public struct AddField { │ ^^^^^^^^ Incorrect number of fields: expected 1, found 2 │ - = Structs are part of a module's public interface and cannot be changed during an upgrade. + = Structs are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original struct's field for struct 'AddField' including the ordering. error[Compatibility E01002]: type mismatch @@ -71,7 +71,7 @@ error[Compatibility E01002]: type mismatch 29 │ public struct RemoveOnlyField { │ ^^^^^^^^^^^^^^^ Incorrect number of fields: expected 1, found 0 │ - = Structs are part of a module's public interface and cannot be changed during an upgrade. + = Structs are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original struct's field for struct 'RemoveOnlyField' including the ordering. error[Compatibility E01002]: type mismatch @@ -80,7 +80,7 @@ error[Compatibility E01002]: type mismatch 34 │ public struct RemoveField { │ ^^^^^^^^^^^ Incorrect number of fields: expected 2, found 1 │ - = Structs are part of a module's public interface and cannot be changed during an upgrade. + = Structs are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original struct's fields for struct 'RemoveField' including the ordering. error[Compatibility E01004]: field mismatch @@ -92,7 +92,7 @@ error[Compatibility E01004]: field mismatch 42 │ c: u64, // changed from b to c │ ^ Mismatched field name 'c', expected 'b'. │ - = Structs are part of a module's public interface and cannot be changed during an upgrade. + = Structs are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original struct's fields for struct 'ChangeFieldName' including the ordering. error[Compatibility E01002]: type mismatch @@ -104,7 +104,7 @@ error[Compatibility E01002]: type mismatch 48 │ b: u32, // changed to u32 │ ^ Mismatched field type 'u32', expected 'u64'. │ - = Structs are part of a module's public interface and cannot be changed during an upgrade. + = Structs are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original struct's fields for struct 'ChangeFieldType' including the ordering. error[Compatibility E01004]: field mismatch @@ -116,7 +116,7 @@ error[Compatibility E01004]: field mismatch 54 │ c: u32, // changed from b to c and u64 to u32 │ ^ Mismatched field 'c: u32', expected 'b: u64'. │ - = Structs are part of a module's public interface and cannot be changed during an upgrade. + = Structs are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original struct's fields for struct 'ChangeFieldNameAndType' including the ordering. error[Compatibility E01002]: type mismatch @@ -125,7 +125,7 @@ error[Compatibility E01002]: type mismatch 58 │ public struct EmptyPositionalAdd(u64) // removed the u64 │ ^^^^^^^^^^^^^^^^^^ Incorrect number of fields: expected 0, found 1 │ - = Structs are part of a module's public interface and cannot be changed during an upgrade. + = Structs are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original struct's fields for struct 'EmptyPositionalAdd' including the ordering. error[Compatibility E01002]: type mismatch @@ -134,7 +134,7 @@ error[Compatibility E01002]: type mismatch 61 │ public struct PositionalAdd(u64, u64, u64) // added a u64 │ ^^^^^^^^^^^^^ Incorrect number of fields: expected 2, found 3 │ - = Structs are part of a module's public interface and cannot be changed during an upgrade. + = Structs are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original struct's fields for struct 'PositionalAdd' including the ordering. error[Compatibility E01002]: type mismatch @@ -143,7 +143,7 @@ error[Compatibility E01002]: type mismatch 64 │ public struct PositionalRemove(u64, u64) // removed a u64 │ ^^^^^^^^^^^^^^^^ Incorrect number of fields: expected 3, found 2 │ - = Structs are part of a module's public interface and cannot be changed during an upgrade. + = Structs are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original struct's fields for struct 'PositionalRemove' including the ordering. error[Compatibility E01002]: type mismatch @@ -154,7 +154,7 @@ error[Compatibility E01002]: type mismatch │ │ │ Struct definition │ - = Structs are part of a module's public interface and cannot be changed during an upgrade. + = Structs are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original struct's fields for struct 'PositionalChange' including the ordering. error[Compatibility E01002]: type mismatch @@ -163,7 +163,7 @@ error[Compatibility E01002]: type mismatch 70 │ public struct PositionalAddNamed{ a: u64 } // changed to named from empty positional │ ^^^^^^^^^^^^^^^^^^ Incorrect number of fields: expected 0, found 1 │ - = Structs are part of a module's public interface and cannot be changed during an upgrade. + = Structs are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original struct's fields for struct 'PositionalAddNamed' including the ordering. error[Compatibility E01004]: field mismatch @@ -174,7 +174,7 @@ error[Compatibility E01004]: field mismatch │ │ │ Struct definition │ - = Structs are part of a module's public interface and cannot be changed during an upgrade. + = Structs are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original struct's field for struct 'PositionalToNamed' including the ordering. error[Compatibility E01004]: field mismatch @@ -185,7 +185,7 @@ error[Compatibility E01004]: field mismatch │ │ │ Struct definition │ - = Structs are part of a module's public interface and cannot be changed during an upgrade. + = Structs are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original struct's field for struct 'PositionalToNamedAndChangeType' including the ordering. error[Compatibility E01002]: type mismatch @@ -196,7 +196,7 @@ error[Compatibility E01002]: type mismatch │ │ │ Struct definition │ - = Structs are part of a module's public interface and cannot be changed during an upgrade. + = Structs are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original struct's field for struct 'ChangePositionalStruct' including the ordering. error[Compatibility E01002]: type mismatch @@ -207,7 +207,7 @@ error[Compatibility E01002]: type mismatch 91 │ a: ChangeFieldB, // changed to ChangeFieldB │ ^ Mismatched field type '0x0::upgrades::ChangeFieldB', expected '0x0::upgrades::ChangeFieldA'. │ - = Structs are part of a module's public interface and cannot be changed during an upgrade. + = Structs are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original struct's field for struct 'ChangeNameNestedStruct' including the ordering. diff --git a/crates/sui/src/unit_tests/snapshots/sui__upgrade_compatibility__upgrade_compatibility_tests__type_param.snap b/crates/sui/src/unit_tests/snapshots/sui__upgrade_compatibility__upgrade_compatibility_tests__type_param.snap index a548148d0591b9..9c3f2f96aaee5e 100644 --- a/crates/sui/src/unit_tests/snapshots/sui__upgrade_compatibility__upgrade_compatibility_tests__type_param.snap +++ b/crates/sui/src/unit_tests/snapshots/sui__upgrade_compatibility__upgrade_compatibility_tests__type_param.snap @@ -8,7 +8,7 @@ error[Compatibility E01005]: type parameter mismatch 13 │ public struct StructTypeParamAddU has copy, drop { x : T } │ ^^^^^^^^^^^^^^^^^^^ Incorrect number of type parameters: expected 1, found 2 │ - = Structs are part of a module's public interface and cannot be changed during an upgrade. + = Structs are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original struct's type parameter for struct 'StructTypeParamAddU' including the ordering. error[Compatibility E01005]: type parameter mismatch @@ -19,7 +19,7 @@ error[Compatibility E01005]: type parameter mismatch │ │ │ Struct definition │ - = Structs are part of a module's public interface and cannot be changed during an upgrade. + = Structs are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original type parameter constraint: 'copy' error[Compatibility E01005]: type parameter mismatch @@ -30,7 +30,7 @@ error[Compatibility E01005]: type parameter mismatch │ │ │ Struct definition │ - = Structs are part of a module's public interface and cannot be changed during an upgrade. + = Structs are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original type parameter constraints: 'copy' and 'drop' error[Compatibility E01005]: type parameter mismatch @@ -41,7 +41,7 @@ error[Compatibility E01005]: type parameter mismatch │ │ │ Struct definition │ - = Structs are part of a module's public interface and cannot be changed during an upgrade. + = Structs are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original 'phantom' modifier error[Compatibility E01005]: type parameter mismatch @@ -52,7 +52,7 @@ error[Compatibility E01005]: type parameter mismatch │ │ │ Struct definition │ - = Structs are part of a module's public interface and cannot be changed during an upgrade. + = Structs are part of a module's public interface and cannot be removed or changed during an upgrade. = Remove the 'phantom' modifier error[Compatibility E01005]: type parameter mismatch @@ -61,7 +61,7 @@ error[Compatibility E01005]: type parameter mismatch 29 │ public enum EnumTypeParamAddU has copy, drop { │ ^^^^^^^^^^^^^^^^^ Incorrect number of type parameters: expected 1, found 2 │ - = Enums are part of a module's public interface and cannot be changed during an upgrade. + = Enums are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original enum's type parameter for enum 'EnumTypeParamAddU' including the ordering. error[Compatibility E01005]: type parameter mismatch @@ -70,7 +70,7 @@ error[Compatibility E01005]: type parameter mismatch 34 │ public enum EnumTypeParamRemoveU has copy, drop { │ ^^^^^^^^^^^^^^^^^^^^ Incorrect number of type parameters: expected 2, found 1 │ - = Enums are part of a module's public interface and cannot be changed during an upgrade. + = Enums are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original enum's type parameters for enum 'EnumTypeParamRemoveU' including the ordering. error[Compatibility E01005]: type parameter mismatch @@ -81,7 +81,7 @@ error[Compatibility E01005]: type parameter mismatch │ │ │ Enum definition │ - = Enums are part of a module's public interface and cannot be changed during an upgrade. + = Enums are part of a module's public interface and cannot be removed or changed during an upgrade. = Restore the original type parameter constraint: 'copy' error[Compatibility E01005]: type parameter mismatch @@ -90,7 +90,7 @@ error[Compatibility E01005]: type parameter mismatch 46 │ public fun add_type_param(a: T): T { return a } │ ^^^^^^^^^^^^^^ Expected 1 type parameter, found 2 │ - = Functions are part of a module's public interface and cannot be changed during an upgrade. + = Functions are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original function's type parameter for function 'add_type_param', expected 1 type parameter. error[Compatibility E01005]: type parameter mismatch @@ -99,7 +99,7 @@ error[Compatibility E01005]: type parameter mismatch 49 │ public fun remove_type_param(a: T): T { return a } │ ^^^^^^^^^^^^^^^^^ Expected 2 type parameters, found 1 │ - = Functions are part of a module's public interface and cannot be changed during an upgrade. + = Functions are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original function's type parameters for function 'remove_type_param', expected 2 type parameters. error[Compatibility E01005]: type parameter mismatch @@ -108,7 +108,7 @@ error[Compatibility E01005]: type parameter mismatch 52 │ public fun add_constraint(a: T): T { return a } │ ^ Unexpected type parameter constraint: 'copy', expected none │ - = Functions are part of a module's public interface and cannot be changed during an upgrade. + = Functions are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original function's type parameter for function 'add_constraint'. error[Compatibility E03001]: function signature mismatch @@ -119,7 +119,7 @@ error[Compatibility E03001]: function signature mismatch │ │ │ Type parameter 'T' is defined here │ - = Functions are part of a module's public interface and cannot be changed during an upgrade. + = Functions are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original function's parameters for function 'swap_type_params'. error[Compatibility E03001]: function signature mismatch @@ -130,7 +130,7 @@ error[Compatibility E03001]: function signature mismatch │ │ │ Type parameter 'U' is defined here │ - = Functions are part of a module's public interface and cannot be changed during an upgrade. + = Functions are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original function's parameters for function 'swap_type_params'. error[Compatibility E03001]: function signature mismatch @@ -141,7 +141,7 @@ error[Compatibility E03001]: function signature mismatch │ │ │ Type parameter 'T' is defined here │ - = Functions are part of a module's public interface and cannot be changed during an upgrade. + = Functions are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original function's return type for function 'swap_type_params_return'. error[Compatibility E03001]: function signature mismatch @@ -152,7 +152,7 @@ error[Compatibility E03001]: function signature mismatch │ │ │ Type parameter 'T' is defined here │ - = Functions are part of a module's public interface and cannot be changed during an upgrade. + = Functions are part of a module's public interface and cannot be removed or changed during a 'compatible' upgrade. = Restore the original function's parameter for function 'vec_changed_type_param'. diff --git a/crates/sui/src/unit_tests/snapshots/sui__upgrade_compatibility__upgrade_compatibility_tests__version_mismatch.snap b/crates/sui/src/unit_tests/snapshots/sui__upgrade_compatibility__upgrade_compatibility_tests__version_mismatch.snap new file mode 100644 index 00000000000000..ad31f8daf1b4f5 --- /dev/null +++ b/crates/sui/src/unit_tests/snapshots/sui__upgrade_compatibility__upgrade_compatibility_tests__version_mismatch.snap @@ -0,0 +1,15 @@ +--- +source: crates/sui/src/unit_tests/upgrade_compatibility_tests.rs +expression: normalize_path(result.unwrap_err().to_string()) +--- +error[Compatibility E01009]: file format version downgrade + ┌─ /fixtures/upgrade_errors/deponly_errors_v2/sources/UpgradeErrors.move:4:18 + │ +4 │ module upgrades::upgrades { + │ ^^^^^^^^ Downgrading from file format version 1 to 0 is not supported. + │ + = File format version downgrades are not supported. + = Please upgrade to the latest version of the move language tooling. + + +Upgrade failed, this package requires changes to be compatible with the existing package. Its upgrade policy is set to 'additive'. diff --git a/crates/sui/src/unit_tests/upgrade_compatibility_tests.rs b/crates/sui/src/unit_tests/upgrade_compatibility_tests.rs index bbc9148fa391db..4e79efa4b50bd1 100644 --- a/crates/sui/src/unit_tests/upgrade_compatibility_tests.rs +++ b/crates/sui/src/unit_tests/upgrade_compatibility_tests.rs @@ -76,6 +76,38 @@ fn test_type_param() { assert_snapshot!(normalize_path(err.to_string())); } +#[test] +fn test_additive() { + let (pkg_v1, pkg_v2, p) = get_packages("additive_errors"); + let result = compare_packages(pkg_v1, pkg_v2, p, UpgradePolicy::Additive); + + assert!(result.is_err()); + let err = result.unwrap_err(); + assert_snapshot!(normalize_path(err.to_string())); +} + +#[test] +fn test_deponly() { + let (pkg_v1, pkg_v2, p) = get_packages("deponly_errors"); + let result = compare_packages(pkg_v1, pkg_v2, p, UpgradePolicy::DepOnly); + + assert!(result.is_err()); + let err = result.unwrap_err(); + assert_snapshot!(normalize_path(err.to_string())); +} +#[test] +fn test_version_mismatch() { + // use deponly errors package, but change the version of the package and the module + // to trigger _only_ a version mismatch error (not a deponly error) + let (mut pkg_v1, mut pkg_v2, p) = get_packages("deponly_errors"); + pkg_v1[0].version = 1; // previous version was 1 + pkg_v2.package.root_compiled_units[0].unit.module.version = 0; // downgraded to version 0 + + let result = compare_packages(pkg_v1, pkg_v2, p, UpgradePolicy::Additive); + assert!(result.is_err()); + assert_snapshot!(normalize_path(result.unwrap_err().to_string())); +} + #[test] fn test_friend_link_ok() { let (pkg_v1, pkg_v2, path) = get_packages("friend_linking"); diff --git a/crates/sui/src/upgrade_compatibility.rs b/crates/sui/src/upgrade_compatibility.rs index 84bd897d465e8f..4c90d87e020691 100644 --- a/crates/sui/src/upgrade_compatibility.rs +++ b/crates/sui/src/upgrade_compatibility.rs @@ -12,16 +12,15 @@ use std::fs; use std::path::PathBuf; use std::sync::Arc; -use move_binary_format::compatibility::InclusionCheck; use move_binary_format::file_format::{ AbilitySet, DatatypeTyParameter, EnumDefinitionIndex, FunctionDefinitionIndex, StructDefinitionIndex, TableIndex, }; -use move_binary_format::normalized::Type; use move_binary_format::{ - compatibility::Compatibility, + compatibility::{Compatibility, InclusionCheck}, compatibility_mode::CompatibilityMode, file_format::Visibility, + inclusion_mode::InclusionCheckMode, normalized::{Enum, Field, Function, Module, Struct, Type, Variant}, CompiledModule, }; @@ -33,7 +32,7 @@ use move_compiler::{ codes::{custom, Severity}, report_diagnostics_to_buffer, Diagnostic, Diagnostics, }, - shared::files::{FileName, FilesSourceText}, + shared::files::FileName, }; use move_core_types::{ account_address::AccountAddress, @@ -126,50 +125,140 @@ pub(crate) enum UpgradeCompatibilityModeError { name: Identifier, old_function: Function, }, + + // inclusion check specific errors + FileFormatVersionDowngrade { + old_version: u32, + new_version: u32, + }, + StructNew { + name: Identifier, + new_struct: Struct, + }, + StructChange { + name: Identifier, + old_struct: Struct, + new_struct: Struct, + }, + EnumNew { + name: Identifier, + new_enum: Enum, + }, + EnumChange { + name: Identifier, + new_enum: Enum, + }, + FunctionNew { + name: Identifier, + new_func: Function, + }, + FunctionChange { + name: Identifier, + old_func: Function, + new_func: Function, + }, + FunctionMissing { + name: Identifier, + }, + FriendNew, + FriendMissing, } -impl UpgradeCompatibilityModeError { - /// check if the error breaks compatibility for a given [`Compatibility`] - fn breaks_compatibility(&self, compatability: &Compatibility) -> bool { - match self { - UpgradeCompatibilityModeError::ModuleMissing { .. } - | UpgradeCompatibilityModeError::ModuleMismatch { .. } => true, - - UpgradeCompatibilityModeError::StructAbilityMismatch { .. } - | UpgradeCompatibilityModeError::StructTypeParamMismatch { .. } - | UpgradeCompatibilityModeError::EnumAbilityMismatch { .. } - | UpgradeCompatibilityModeError::EnumTypeParamMismatch { .. } - | UpgradeCompatibilityModeError::FunctionMissingPublic { .. } - | UpgradeCompatibilityModeError::FunctionLostPublicVisibility { .. } => true, - - UpgradeCompatibilityModeError::StructFieldMismatch { .. } - | UpgradeCompatibilityModeError::EnumVariantMissing { .. } - | UpgradeCompatibilityModeError::EnumVariantMismatch { .. } => { - compatability.check_datatype_layout - } +/// Check if a specifc error breaks 'compatible' upgrades +fn breaks_compatibility( + error: &UpgradeCompatibilityModeError, + compatability: &Compatibility, +) -> bool { + match error { + UpgradeCompatibilityModeError::ModuleMissing { .. } + | UpgradeCompatibilityModeError::ModuleMismatch { .. } => true, + + UpgradeCompatibilityModeError::StructAbilityMismatch { .. } + | UpgradeCompatibilityModeError::StructTypeParamMismatch { .. } + | UpgradeCompatibilityModeError::EnumAbilityMismatch { .. } + | UpgradeCompatibilityModeError::EnumTypeParamMismatch { .. } + | UpgradeCompatibilityModeError::FunctionMissingPublic { .. } + | UpgradeCompatibilityModeError::FunctionLostPublicVisibility { .. } => true, + + UpgradeCompatibilityModeError::StructFieldMismatch { .. } + | UpgradeCompatibilityModeError::EnumVariantMissing { .. } + | UpgradeCompatibilityModeError::EnumVariantMismatch { .. } => { + compatability.check_datatype_layout + } - UpgradeCompatibilityModeError::StructMissing { .. } - | UpgradeCompatibilityModeError::EnumMissing { .. } => true, + UpgradeCompatibilityModeError::StructMissing { .. } + | UpgradeCompatibilityModeError::EnumMissing { .. } => true, - UpgradeCompatibilityModeError::FunctionSignatureMismatch { old_function, .. } => { - if old_function.visibility == Visibility::Public { - return true; - } - if old_function.is_entry { - compatability.check_private_entry_linking - } else { - false - } + UpgradeCompatibilityModeError::FunctionSignatureMismatch { old_function, .. } => { + if old_function.visibility == Visibility::Public { + return true; } - - UpgradeCompatibilityModeError::FunctionMissingEntry { .. } - | UpgradeCompatibilityModeError::FunctionEntryCompatibility { .. } => { + if old_function.is_entry { compatability.check_private_entry_linking + } else { + false } - UpgradeCompatibilityModeError::EnumNewVariant { .. } => { - compatability.check_datatype_layout - } } + + UpgradeCompatibilityModeError::FunctionMissingEntry { .. } + | UpgradeCompatibilityModeError::FunctionEntryCompatibility { .. } => { + compatability.check_private_entry_linking + } + UpgradeCompatibilityModeError::EnumNewVariant { .. } => compatability.check_datatype_layout, + + UpgradeCompatibilityModeError::FileFormatVersionDowngrade { .. } + | UpgradeCompatibilityModeError::StructNew { .. } + | UpgradeCompatibilityModeError::StructChange { .. } + | UpgradeCompatibilityModeError::EnumNew { .. } + | UpgradeCompatibilityModeError::EnumChange { .. } + | UpgradeCompatibilityModeError::FunctionNew { .. } + | UpgradeCompatibilityModeError::FunctionChange { .. } + | UpgradeCompatibilityModeError::FunctionMissing { .. } + | UpgradeCompatibilityModeError::FriendNew { .. } + | UpgradeCompatibilityModeError::FriendMissing { .. } => false, + } +} + +/// Check if a specifc error breaks inclusion checks for 'additive' (Subset) or 'dependency only' (Equal) upgrades +fn breaks_inclusion_check( + error: &UpgradeCompatibilityModeError, + inclusion_check: &InclusionCheck, +) -> bool { + match error { + UpgradeCompatibilityModeError::StructNew { .. } => { + matches!(inclusion_check, InclusionCheck::Equal) + } + UpgradeCompatibilityModeError::EnumNew { .. } => { + matches!(inclusion_check, InclusionCheck::Equal) + } + UpgradeCompatibilityModeError::FunctionNew { .. } => { + matches!(inclusion_check, InclusionCheck::Equal) + } + + UpgradeCompatibilityModeError::ModuleMissing { .. } + | UpgradeCompatibilityModeError::ModuleMismatch { .. } + | UpgradeCompatibilityModeError::StructMissing { .. } + | UpgradeCompatibilityModeError::StructAbilityMismatch { .. } + | UpgradeCompatibilityModeError::StructTypeParamMismatch { .. } + | UpgradeCompatibilityModeError::StructFieldMismatch { .. } + | UpgradeCompatibilityModeError::EnumMissing { .. } + | UpgradeCompatibilityModeError::EnumAbilityMismatch { .. } + | UpgradeCompatibilityModeError::EnumTypeParamMismatch { .. } + | UpgradeCompatibilityModeError::EnumNewVariant { .. } + | UpgradeCompatibilityModeError::EnumVariantMissing { .. } + | UpgradeCompatibilityModeError::EnumVariantMismatch { .. } + | UpgradeCompatibilityModeError::FunctionMissingPublic { .. } + | UpgradeCompatibilityModeError::FunctionMissingEntry { .. } + | UpgradeCompatibilityModeError::FunctionSignatureMismatch { .. } + | UpgradeCompatibilityModeError::FunctionLostPublicVisibility { .. } + | UpgradeCompatibilityModeError::FunctionEntryCompatibility { .. } + | UpgradeCompatibilityModeError::FileFormatVersionDowngrade { .. } + | UpgradeCompatibilityModeError::StructChange { .. } + | UpgradeCompatibilityModeError::EnumChange { .. } + | UpgradeCompatibilityModeError::FunctionChange { .. } + | UpgradeCompatibilityModeError::FunctionMissing { .. } + | UpgradeCompatibilityModeError::FriendNew { .. } + | UpgradeCompatibilityModeError::FriendMissing { .. } => true, } } @@ -341,7 +430,119 @@ impl CompatibilityMode for CliCompatibilityMode { let errors: Vec = self .errors .into_iter() - .filter(|e| e.breaks_compatibility(compatability)) + .filter(|e| breaks_compatibility(e, compatability)) + .collect(); + + if !errors.is_empty() { + return Err(errors); + } + Ok(()) + } +} + +/// A Compatibility mode used for checking inclusion checks for 'additive' (Subset) or 'dependency only' (Equal) upgrades +#[derive(Default)] +struct CliInclusionCheckMode { + errors: Vec, +} + +impl InclusionCheckMode for CliInclusionCheckMode { + type Error = Vec; + + fn module_name_mismatch(&mut self, _old_address: &Identifier, _new_address: &Identifier) {} + + // ignored address is not populated pre-tx + fn module_address_mismatch( + &mut self, + _old_address: &AccountAddress, + _new_address: &AccountAddress, + ) { + } + + fn file_format_version_downgrade(&mut self, old_version: u32, new_version: u32) { + self.errors + .push(UpgradeCompatibilityModeError::FileFormatVersionDowngrade { + old_version, + new_version, + }); + } + + fn struct_new(&mut self, name: &Identifier, new_struct: &Struct) { + self.errors.push(UpgradeCompatibilityModeError::StructNew { + name: name.clone(), + new_struct: new_struct.clone(), + }); + } + + fn struct_change(&mut self, name: &Identifier, old_struct: &Struct, new_struct: &Struct) { + self.errors + .push(UpgradeCompatibilityModeError::StructChange { + name: name.clone(), + old_struct: old_struct.clone(), + new_struct: new_struct.clone(), + }); + } + + fn struct_missing(&mut self, name: &Identifier, old_struct: &Struct) { + self.errors + .push(UpgradeCompatibilityModeError::StructMissing { name: name.clone() }); + } + + fn enum_new(&mut self, name: &Identifier, new_enum: &Enum) { + self.errors.push(UpgradeCompatibilityModeError::EnumNew { + name: name.clone(), + new_enum: new_enum.clone(), + }); + } + + fn enum_change(&mut self, name: &Identifier, new_enum: &Enum) { + self.errors.push(UpgradeCompatibilityModeError::EnumChange { + name: name.clone(), + new_enum: new_enum.clone(), + }); + } + + fn enum_missing(&mut self, name: &Identifier, old_enum: &Enum) { + self.errors + .push(UpgradeCompatibilityModeError::EnumMissing { name: name.clone() }); + } + + fn function_new(&mut self, name: &Identifier, new_func: &Function) { + self.errors + .push(UpgradeCompatibilityModeError::FunctionNew { + name: name.clone(), + new_func: new_func.clone(), + }); + } + + fn function_change(&mut self, name: &Identifier, old_func: &Function, new_func: &Function) { + self.errors + .push(UpgradeCompatibilityModeError::FunctionChange { + name: name.clone(), + old_func: old_func.clone(), + new_func: new_func.clone(), + }); + } + + fn function_missing(&mut self, name: &Identifier, old_func: &Function) { + self.errors + .push(UpgradeCompatibilityModeError::FunctionMissing { name: name.clone() }); + } + + fn friend_mismatch(&mut self, old_count: usize, new_count: usize) { + if old_count < new_count { + self.errors.push(UpgradeCompatibilityModeError::FriendNew); + } else { + self.errors + .push(UpgradeCompatibilityModeError::FriendMissing); + } + } + + fn finish(self, inclusion: &InclusionCheck) -> Result<(), Self::Error> { + let errors: Vec = self + .errors + .into_iter() + .filter(|e| breaks_inclusion_check(e, inclusion)) .collect(); if !errors.is_empty() { @@ -351,6 +552,7 @@ impl CompatibilityMode for CliCompatibilityMode { } } +#[derive(Debug, Clone)] struct IdentifierTableLookup { struct_identifier_to_index: BTreeMap, enum_identifier_to_index: BTreeMap, @@ -458,6 +660,9 @@ upgrade_codes!( TypeParamMismatch: { msg: "type parameter mismatch" }, ModuleMismatch: { msg: "module incompatible" }, ModuleMissing: { msg: "module missing" }, + Missing: { msg: "missing declaration" }, + VersionMismatch: { msg: "file format version downgrade" }, + FriendMismatch: { msg: "friend mismatch" }, ], Enums: [ VariantMismatch: { msg: "variant mismatch" }, @@ -507,77 +712,24 @@ pub(crate) async fn check_compatibility( compare_packages(existing_modules, new_package, package_path, policy) } +/// Collect all the errors into a single error message. fn compare_packages( existing_modules: Vec, mut new_package: CompiledPackage, package_path: PathBuf, policy: UpgradePolicy, ) -> Result<(), Error> { + // create a map from the new modules let new_modules_map: HashMap = new_package .get_modules() .map(|m| (m.self_id().name().to_owned(), m.clone())) .collect(); - let lookup: HashMap = new_package - .get_modules() + let lookup: HashMap = new_modules_map + .values() .map(|m| (m.self_id().name().to_owned(), table_index(m))) .collect(); - let errors: Vec<(Identifier, UpgradeCompatibilityModeError)> = existing_modules - .iter() - .flat_map(|existing_module| { - let name = existing_module.self_id().name().to_owned(); - - // find the new module with the same name - match new_modules_map.get(&name) { - Some(new_module) => { - let existing_module = Module::new(existing_module); - let new_module = Module::new(new_module); - - match policy { - UpgradePolicy::Compatible => errors_or_empty_vec( - name, - Compatibility::upgrade_check().check_with_mode::( - &existing_module, - &new_module, - ), - ), - // TODO improve on this error message - UpgradePolicy::Additive => errors_or_empty_vec( - name, - InclusionCheck::Subset - .check(&existing_module, &new_module) - .map_err(|_| { - vec![UpgradeCompatibilityModeError::ModuleMismatch { - policy: UpgradePolicy::Additive, - }] - }), - ), - // TODO improve on this error message - UpgradePolicy::DepOnly => errors_or_empty_vec( - name, - InclusionCheck::Equal - .check(&existing_module, &new_module) - .map_err(|_| { - vec![UpgradeCompatibilityModeError::ModuleMismatch { - policy: UpgradePolicy::DepOnly, - }] - }), - ), - } - } - None => vec![( - name.clone(), - UpgradeCompatibilityModeError::ModuleMissing { name }, - )], - } - }) - .collect(); - - if errors.is_empty() { - return Ok(()); - } - let mut diags = Diagnostics::new(); // add move toml @@ -595,48 +747,97 @@ fn compare_packages( Arc::clone(&move_toml_contents), ); - for (name, err) in errors { - if let UpgradeCompatibilityModeError::ModuleMissing { name, .. } = &err { - diags.extend(missing_module_diag( - name, - &move_toml_hash, - &move_toml_contents, - )?); - continue; - } - - let compiled_unit_with_source = new_package - .package - .get_module_by_name_from_root(name.as_str()) - .context("Unable to get module")?; + for existing_module in existing_modules { + let name = existing_module.self_id().name().to_owned(); + match new_modules_map.get(&name) { + Some(new_module) => { + let compiled_unit_with_source = new_package + .package + .get_module_by_name_from_root(name.as_str()) + .context("Unable to get module")?; + + let module_diags = modules_into_diags( + &existing_module, + new_module, + compiled_unit_with_source, + &lookup[&name], + policy, + )?; - diags.extend(diag_from_error( - &err, - compiled_unit_with_source, - &lookup[&name], - )?); + diags.extend(module_diags); + } + None => { + diags.extend(missing_module_diag( + &name, + &move_toml_hash, + &move_toml_contents, + )?); + } + } } - // use colors but inline - Err(anyhow!( - "{}\nUpgrade failed, this package requires changes to be compatible with the existing package. \ - Its upgrade policy is set to '{}'.", - if !diags.is_empty() { + if diags.is_empty() { + Ok(()) + } else { + Err(anyhow!( + "{}\nUpgrade failed, this package requires changes to be compatible with the existing package. \ + Its upgrade policy is set to '{}'.", String::from_utf8(report_diagnostics_to_buffer( &new_package.package.file_map, diags, use_colors() - )) - .context("Unable to convert buffer to string")? - } else { - "".to_string() - }, - match policy { - UpgradePolicy::Compatible => "compatible", - UpgradePolicy::Additive => "additive", - UpgradePolicy::DepOnly => "dependency only", - } - )) + )).context("Unable to convert buffer to string")?, + match policy { + UpgradePolicy::Compatible => "compatible", + UpgradePolicy::Additive => "additive", + UpgradePolicy::DepOnly => "dependency only", + } + )) + } +} + +/// Runs the compatibility check between two modules and flattens the errors into a single error message. +fn modules_into_diags( + existing_module: &CompiledModule, + new_module: &CompiledModule, + compiled_unit_with_source: &CompiledUnitWithSource, + lookup: &IdentifierTableLookup, + policy: UpgradePolicy, +) -> Result { + let diags_list = match policy { + UpgradePolicy::DepOnly => InclusionCheck::Equal.check_with_mode::( + &Module::new(existing_module), + &Module::new(new_module), + ), + UpgradePolicy::Additive => InclusionCheck::Subset.check_with_mode::( + &Module::new(existing_module), + &Module::new(new_module), + ), + _ => Compatibility::upgrade_check().check_with_mode::( + &Module::new(existing_module), + &Module::new(new_module), + ), + } + .err() + .unwrap_or_default() + .into_iter() + .map(|e| { + compatibility_diag_from_error( + &e, + compiled_unit_with_source, + matches!(policy, UpgradePolicy::Compatible), + lookup, + ) + }) + .collect::, _>>()?; + + let mut diags = Diagnostics::new(); + + for diag in diags_list { + diags.extend(diag); + } + + Ok(diags) } fn errors_or_empty_vec( @@ -650,14 +851,16 @@ fn errors_or_empty_vec( } /// Convert an error to a diagnostic using the specific error type's function. -fn diag_from_error( +fn compatibility_diag_from_error( error: &UpgradeCompatibilityModeError, compiled_unit_with_source: &CompiledUnitWithSource, + is_compatible: bool, lookup: &IdentifierTableLookup, ) -> Result { + let module_name = compiled_unit_with_source.unit.name.as_str(); match error { UpgradeCompatibilityModeError::StructMissing { name, .. } => { - missing_definition_diag("struct", name, compiled_unit_with_source) + missing_definition_diag("struct", name, is_compatible, compiled_unit_with_source) } UpgradeCompatibilityModeError::StructAbilityMismatch { name, @@ -667,6 +870,7 @@ fn diag_from_error( name, old_struct, new_struct, + is_compatible, compiled_unit_with_source, lookup, ), @@ -678,9 +882,13 @@ fn diag_from_error( name, old_struct, new_struct, + is_compatible, compiled_unit_with_source, lookup, ), + UpgradeCompatibilityModeError::EnumMissing { name, .. } => { + missing_definition_diag("enum", name, is_compatible, compiled_unit_with_source) + } UpgradeCompatibilityModeError::StructTypeParamMismatch { name, @@ -690,20 +898,24 @@ fn diag_from_error( name, old_struct, new_struct, + is_compatible, compiled_unit_with_source, lookup, ), - UpgradeCompatibilityModeError::EnumMissing { name, .. } => { - missing_definition_diag("enum", name, compiled_unit_with_source) - } UpgradeCompatibilityModeError::EnumAbilityMismatch { name, old_enum, new_enum, - } => { - enum_ability_mismatch_diag(name, old_enum, new_enum, compiled_unit_with_source, lookup) - } + } => enum_ability_mismatch_diag( + name, + old_enum, + new_enum, + is_compatible, + compiled_unit_with_source, + lookup, + ), + UpgradeCompatibilityModeError::EnumNewVariant { name, old_enum, @@ -726,19 +938,41 @@ fn diag_from_error( old_enum, new_enum, .. - } => { - enum_variant_mismatch_diag(name, old_enum, new_enum, compiled_unit_with_source, lookup) - } + } => enum_variant_mismatch_diag( + name, + old_enum, + new_enum, + is_compatible, + compiled_unit_with_source, + lookup, + ), UpgradeCompatibilityModeError::EnumTypeParamMismatch { name, old_enum, new_enum, - } => enum_type_param_mismatch(name, old_enum, new_enum, compiled_unit_with_source, lookup), + } => enum_type_param_mismatch( + name, + old_enum, + new_enum, + is_compatible, + compiled_unit_with_source, + lookup, + ), UpgradeCompatibilityModeError::FunctionMissingPublic { name, .. } => { - missing_definition_diag("public function", name, compiled_unit_with_source) + missing_definition_diag( + "public function", + name, + is_compatible, + compiled_unit_with_source, + ) } UpgradeCompatibilityModeError::FunctionMissingEntry { name, .. } => { - missing_definition_diag("entry function", name, compiled_unit_with_source) + missing_definition_diag( + "entry function", + name, + is_compatible, + compiled_unit_with_source, + ) } UpgradeCompatibilityModeError::FunctionLostPublicVisibility { name, .. } => { function_lost_public(name, compiled_unit_with_source, lookup) @@ -751,6 +985,7 @@ fn diag_from_error( name, old_function, new_function, + is_compatible, compiled_unit_with_source, lookup, ), @@ -766,10 +1001,53 @@ fn diag_from_error( UpgradeCompatibilityModeError::ModuleMissing { .. } => { unreachable!("Module Missing should be handled by outer function") } + + UpgradeCompatibilityModeError::StructNew { name, .. } => { + struct_new_diag(name, compiled_unit_with_source) + } + UpgradeCompatibilityModeError::StructChange { + name, + old_struct, + new_struct, + } => struct_changed_diag( + name, + old_struct, + new_struct, + compiled_unit_with_source, + lookup, + ), + + UpgradeCompatibilityModeError::EnumNew { name, new_enum } => { + enum_new_diag(name, new_enum, compiled_unit_with_source) + } + UpgradeCompatibilityModeError::EnumChange { name, new_enum } => { + enum_changed_diag(name, new_enum, new_enum, compiled_unit_with_source, lookup) + } + + UpgradeCompatibilityModeError::FunctionNew { name, .. } => { + function_new_diag(name, compiled_unit_with_source) + } + UpgradeCompatibilityModeError::FunctionChange { + name, + old_func, + new_func, + } => function_changed_diag(name, old_func, new_func, compiled_unit_with_source, lookup), + UpgradeCompatibilityModeError::FunctionMissing { name } => { + missing_definition_diag("function", name, is_compatible, compiled_unit_with_source) + } + UpgradeCompatibilityModeError::FileFormatVersionDowngrade { + old_version, + new_version, + } => { + file_format_version_downgrade_diag(old_version, new_version, compiled_unit_with_source) + } + UpgradeCompatibilityModeError::FriendNew { .. } + | UpgradeCompatibilityModeError::FriendMissing { .. } => { + friend_link_diag(compiled_unit_with_source) + } } } -// TODO provide more depth in the diagnostics // give specifics about the declarations which do not match fn module_compatibility_error_diag( policy: UpgradePolicy, @@ -808,6 +1086,7 @@ fn module_compatibility_error_diag( Ok(diags) } +/// Return a diagnostic when a module is missing from a package. fn missing_module_diag( module_name: &Identifier, move_toml_hash: &FileHash, @@ -826,7 +1105,7 @@ fn missing_module_diag( .map(|(idx, _)| start + idx) .unwrap_or(start + PACKAGE_TABLE.len()); - let loc = Loc::new(move_toml_hash.clone(), start as ByteIndex, end as ByteIndex); + let loc = Loc::new(*move_toml_hash, start as ByteIndex, end as ByteIndex); diags.add(Diagnostic::new( Declarations::ModuleMissing, @@ -845,18 +1124,49 @@ fn missing_module_diag( fn missing_definition_diag( declaration_kind: &str, identifier_name: &Identifier, + public_visibility_related_error: bool, // give a different code for errors which are public visibility related compiled_unit_with_source: &CompiledUnitWithSource, ) -> Result { let mut diags = Diagnostics::new(); - let module_name = compiled_unit_with_source.unit.name; + let module_name = compiled_unit_with_source.unit.name.as_str(); let loc = compiled_unit_with_source .unit .source_map .definition_location; + let (code, reason_notes) = if public_visibility_related_error { + ( + Declarations::PublicMissing, + vec![ + format!( + "{declaration_kind}s are part of a module's public interface \ + and cannot be removed or changed during a 'compatible' upgrade.", + ), + format!( + "add missing {declaration_kind} '{identifier_name}' \ + back to the module '{module_name}'.", + ), + ], + ) + } else { + ( + Declarations::Missing, + vec![ + format!( + "{declaration_kind}s cannot be removed or changed during an 'additive' or \ + 'dependency only' upgrade.", + ), + format!( + "add missing {declaration_kind} '{identifier_name}' \ + back to the module '{module_name}'.", + ), + ], + ) + }; + diags.add(Diagnostic::new( - Declarations::PublicMissing, + code, ( loc, format!( @@ -866,16 +1176,7 @@ fn missing_definition_diag( ), ), std::iter::empty::<(Loc, String)>(), - vec![ - format!( - "{declaration_kind}s are part of a module's public interface \ - and cannot be removed or changed during an upgrade.", - ), - format!( - "add missing {declaration_kind} '{identifier_name}' \ - back to the module '{module_name}'.", - ), - ], + [reason_notes].concat(), )); Ok(diags) @@ -911,7 +1212,7 @@ fn function_lost_public( Vec::<(Loc, String)>::new(), vec![ "Functions are part of a module's public interface \ - and cannot be changed during an upgrade." + and cannot be removed or changed during an upgrade." .to_string(), format!( "Restore the original function's 'public' visibility for \ @@ -954,12 +1255,13 @@ fn format_param( } /// Return a diagnostic for a function signature mismatch. -/// start by checking the lengths of the parameters and returns and return a diagnostic if they are different -/// if the lengths are the same check each parameter piece wise and return a diagnostic for each mismatch +/// Start by checking the lengths of the parameters and returns and return a diagnostic if they are different. +/// If the lengths are the same check each parameter piece wise and return a diagnostic for each mismatch. fn function_signature_mismatch_diag( function_name: &Identifier, old_function: &Function, new_function: &Function, + public_visibility_related_error: bool, compiled_unit_with_source: &CompiledUnitWithSource, lookup: &IdentifierTableLookup, ) -> Result { @@ -978,6 +1280,14 @@ fn function_signature_mismatch_diag( let def_loc = func_sourcemap.definition_location; + let reason = if public_visibility_related_error { + "Functions are part of a module's public interface \ + and cannot be removed or changed during a 'compatible' upgrade." + } else { + "Functions cannot be removed or changed during an 'additive' or \ + 'dependency only' upgrade." + }; + // handle function arguments if old_function.parameters.len() != new_function.parameters.len() { diags.add(Diagnostic::new( @@ -993,9 +1303,7 @@ fn function_signature_mismatch_diag( ), Vec::<(Loc, String)>::new(), vec![ - "Functions are part of a module's public interface and cannot be \ - changed during an upgrade." - .to_string(), + reason.to_string(), format!( "Restore the original function's {} for \ function '{function_name}', expected {} {}.", @@ -1039,9 +1347,7 @@ fn function_signature_mismatch_diag( (param_loc, label), secondary, vec![ - "Functions are part of a module's public interface \ - and cannot be changed during an upgrade." - .to_string(), + reason.to_string(), format!( "Restore the original function's {} \ for function '{function_name}'.", @@ -1075,9 +1381,7 @@ fn function_signature_mismatch_diag( ), Vec::<(Loc, String)>::new(), vec![ - "Functions are part of a module's public interface \ - and cannot be changed during an upgrade." - .to_string(), + reason.to_string(), format!( "Restore the original function's type {} for \ function '{function_name}', expected {} type {}.", @@ -1131,9 +1435,7 @@ fn function_signature_mismatch_diag( ), Vec::<(Loc, String)>::new(), vec![ - "Functions are part of a module's public interface \ - and cannot be changed during an upgrade." - .to_string(), + reason.to_string(), format!( "Restore the original function's type {} \ for function '{function_name}'.", @@ -1164,9 +1466,7 @@ fn function_signature_mismatch_diag( ), Vec::<(Loc, String)>::new(), vec![ - "Functions are part of a module's public interface \ - and cannot be changed during an upgrade." - .to_string(), + reason.to_string(), format!( "Restore the original function's return {} \ for function '{function_name}'.", @@ -1188,7 +1488,6 @@ fn function_signature_mismatch_diag( if old_return != new_return { let mut secondary = Vec::new(); - let old_return = format_param( old_return, func_sourcemap.type_parameters.clone(), @@ -1213,9 +1512,7 @@ fn function_signature_mismatch_diag( (*return_, label), secondary, vec![ - "Functions are part of a module's public interface \ - and cannot be changed during an upgrade." - .to_string(), + reason.to_string(), format!( "Restore the original function's return \ {} for function '{function_name}'.", @@ -1263,7 +1560,7 @@ fn function_entry_mismatch( ), Vec::<(Loc, String)>::new(), vec![ - "Entry functions cannot be changed during an upgrade.".to_string(), + "Entry functions cannot be removed or changed during an upgrade.".to_string(), format!( "Restore the original function's 'entry' visibility for \ function '{function_name}'.", @@ -1321,6 +1618,7 @@ fn struct_ability_mismatch_diag( struct_name: &Identifier, old_struct: &Struct, new_struct: &Struct, + public_visibility_related_error: bool, compiled_unit_with_source: &CompiledUnitWithSource, lookup: &IdentifierTableLookup, ) -> Result { @@ -1359,9 +1657,14 @@ fn struct_ability_mismatch_diag( ), Vec::<(Loc, String)>::new(), vec![ - "Structs are part of a module's public interface and \ - cannot be changed during an upgrade." - .to_string(), + if public_visibility_related_error { + "Structs are part of a module's public interface and \ + cannot be removed or changed during a 'compatible' upgrade." + } else { + "Structs cannot be removed or changed during an 'additive' or \ + 'dependency only' upgrade." + } + .to_string(), format!( "Restore the original {} of struct '{struct_name}': {}.", singular_or_plural(old_abilities.len(), "ability", "abilities"), @@ -1434,12 +1737,13 @@ fn field_mismatch_message(old_field: &Field, new_field: &Field) -> (Declarations } /// Return a diagnostic for a field mismatch -/// Start by checking the lengths of the fields and return a diagnostic if they are different. -/// If the lengths are the same check each field piece wise and return a diagnostic for each mismatch. +/// start by checking the lengths of the fields and return a diagnostic if they are different +/// if the lengths are the same check each field piece wise and return a diagnostic for each mismatch fn struct_field_mismatch_diag( struct_name: &Identifier, old_struct: &Struct, new_struct: &Struct, + public_visibility_related_error: bool, compiled_unit_with_source: &CompiledUnitWithSource, lookup: &IdentifierTableLookup, ) -> Result { @@ -1470,6 +1774,14 @@ fn struct_field_mismatch_diag( .filter(|f| f.name != Identifier::new("dummy_field").unwrap() && f.type_ != Type::Bool) .collect(); + let reason = if public_visibility_related_error { + "Structs are part of a module's public interface \ + and cannot be removed or changed during an upgrade." + } else { + "Structs cannot be removed or changed during an 'additive' or 'dependency only' upgrade." + } + .to_string(); + if old_fields.len() != new_fields.len() { diags.add(Diagnostic::new( Declarations::TypeMismatch, @@ -1483,9 +1795,7 @@ fn struct_field_mismatch_diag( ), Vec::<(Loc, String)>::new(), vec![ - "Structs are part of a module's public interface and \ - cannot be changed during an upgrade." - .to_string(), + reason, format!( "Restore the original struct's {} \ for struct '{struct_name}' including the ordering.", @@ -1508,9 +1818,7 @@ fn struct_field_mismatch_diag( (*field_loc, label), vec![(def_loc, "Struct definition".to_string())], vec![ - "Structs are part of a module's public interface \ - and cannot be changed during an upgrade." - .to_string(), + reason.to_string(), format!( "Restore the original struct's {} for \ struct '{struct_name}' including the ordering.", @@ -1532,6 +1840,7 @@ fn struct_type_param_mismatch_diag( name: &Identifier, old_struct: &Struct, new_struct: &Struct, + public_visibility_related_error: bool, // give a different code for errors which are public visibility related compiled_unit_with_source: &CompiledUnitWithSource, lookup: &IdentifierTableLookup, ) -> Result { @@ -1553,6 +1862,7 @@ fn struct_type_param_mismatch_diag( name, &old_struct.type_parameters, &new_struct.type_parameters, + public_visibility_related_error, def_loc, &struct_sourcemap.type_parameters, ) @@ -1563,6 +1873,7 @@ fn enum_ability_mismatch_diag( enum_name: &Identifier, old_enum: &Enum, new_enum: &Enum, + public_visibility_related_error: bool, // give a different code for errors which are public visibility related compiled_unit_with_source: &CompiledUnitWithSource, lookup: &IdentifierTableLookup, ) -> Result { @@ -1588,6 +1899,15 @@ fn enum_ability_mismatch_diag( .map(|a| format!("'{:?}'", a).to_lowercase()) .collect(); + let reason = if public_visibility_related_error { + "Enums are part of a module's public interface \ + and cannot be removed or changed during a 'compatible' upgrade." + .to_string() + } else { + "Enums cannot be removed or changed during an 'additive' or 'dependency only' upgrade." + .to_string() + }; + diags.add(Diagnostic::new( Declarations::AbilityMismatch, ( @@ -1601,9 +1921,7 @@ fn enum_ability_mismatch_diag( ), Vec::<(Loc, String)>::new(), vec![ - "Enums are part of a module's public interface \ - and cannot be changed during an upgrade." - .to_string(), + reason, format!( "Restore the original {} of the enum: {} \ for enum '{enum_name}'.", @@ -1689,6 +2007,7 @@ fn enum_variant_mismatch_diag( enum_name: &Identifier, old_enum: &Enum, new_enum: &Enum, + public_visibility_related_error: bool, // give a different code for errors which are public visibility related compiled_unit_with_source: &CompiledUnitWithSource, lookup: &IdentifierTableLookup, ) -> Result { @@ -1730,12 +2049,18 @@ fn enum_variant_mismatch_diag( (variant_loc, label), vec![(def_loc, "Enum definition".to_string())], vec![ - "Enums are part of a module's public interface \ - and cannot be changed during an upgrade." - .to_string(), + if public_visibility_related_error { + "Enums are part of a module's public interface \ + and cannot be removed or changed during an upgrade." + .to_string() + } else { + "Enums cannot be removed or changed during an 'additive' \ + or 'dependency only' upgrade." + .to_string() + }, format!( "Restore the original enum's {} for \ - enum '{enum_name}' including the ordering.", + enum '{enum_name}' including the ordering.", singular_or_plural(old_enum.variants.len(), "variant", "variants") ), ], @@ -1793,8 +2118,8 @@ fn enum_new_variant_diag( ), vec![(def_loc, "Enum definition".to_string())], vec![ - "Enums are part of a module's public interface and cannot be \ - changed during an upgrade." + "Enums are part of a module's public interface \ + and cannot be removed or changed during an upgrade." .to_string(), format!( "Restore the original enum's {} for enum \ @@ -1857,11 +2182,216 @@ fn enum_variant_missing_diag( Ok(diags) } +fn struct_new_diag( + struct_name: &Identifier, + compiled_unit_with_source: &CompiledUnitWithSource, +) -> Result { + let mut diags = Diagnostics::new(); + + let def_loc = compiled_unit_with_source + .unit + .source_map + .definition_location; + + diags.add(Diagnostic::new( + Declarations::TypeMismatch, + (def_loc, format!("New unexpected struct '{}'.", struct_name)), + Vec::<(Loc, String)>::new(), + vec![ + "Structs are part of a module's public interface \ + and cannot be removed or changed during an upgrade." + .to_string(), + format!( + "Restore the original struct '{struct_name}' including the ordering.", + struct_name = struct_name, + ), + ], + )); + + Ok(diags) +} + +fn struct_changed_diag( + struct_name: &Identifier, + old_struct: &Struct, + new_struct: &Struct, + compiled_unit_with_source: &CompiledUnitWithSource, + lookup: &IdentifierTableLookup, +) -> Result { + let mut diags = Diagnostics::new(); + + if old_struct.abilities != new_struct.abilities { + diags.extend(struct_ability_mismatch_diag( + struct_name, + old_struct, + new_struct, + false, + compiled_unit_with_source, + lookup, + )?); + } + + if old_struct.type_parameters != new_struct.type_parameters { + diags.extend(struct_type_param_mismatch_diag( + struct_name, + old_struct, + new_struct, + true, + compiled_unit_with_source, + lookup, + )?); + } + + if old_struct.fields != new_struct.fields { + diags.extend(struct_field_mismatch_diag( + struct_name, + old_struct, + new_struct, + false, + compiled_unit_with_source, + lookup, + )?); + } + + Ok(diags) +} + +fn enum_new_diag( + enum_name: &Identifier, + _new_enum: &Enum, + compiled_unit_with_source: &CompiledUnitWithSource, +) -> Result { + let mut diags = Diagnostics::new(); + + let def_loc = compiled_unit_with_source + .unit + .source_map + .definition_location; + + diags.add(Diagnostic::new( + Enums::VariantMismatch, + (def_loc, format!("New unexpected enum '{}'.", enum_name)), + Vec::<(Loc, String)>::new(), + vec![ + "Enums are part of a module's public interface and cannot \ + be changed during an upgrade." + .to_string(), + format!( + "Restore the original enum '{enum_name}' including the ordering.", + enum_name = enum_name, + ), + ], + )); + + Ok(diags) +} + +fn enum_changed_diag( + enum_name: &Identifier, + old_enum: &Enum, + new_enum: &Enum, + compiled_unit_with_source: &CompiledUnitWithSource, + lookup: &IdentifierTableLookup, +) -> Result { + let mut diags = Diagnostics::new(); + + if old_enum.abilities != new_enum.abilities { + diags.extend(enum_ability_mismatch_diag( + enum_name, + old_enum, + new_enum, + false, + compiled_unit_with_source, + lookup, + )?); + } + + if old_enum.type_parameters != new_enum.type_parameters { + diags.extend(enum_ability_mismatch_diag( + enum_name, + old_enum, + new_enum, + false, + compiled_unit_with_source, + lookup, + )?); + } + + if old_enum.variants != new_enum.variants { + diags.extend(enum_variant_mismatch_diag( + enum_name, + old_enum, + new_enum, + false, + compiled_unit_with_source, + lookup, + )?); + } + + Ok(diags) +} + +fn function_new_diag( + function_name: &Identifier, + compiled_unit_with_source: &CompiledUnitWithSource, +) -> Result { + let mut diags = Diagnostics::new(); + + let def_loc = compiled_unit_with_source + .unit + .source_map + .definition_location; + + diags.add(Diagnostic::new( + Functions_::SignatureMismatch, + ( + def_loc, + format!("New unexpected function '{}'.", function_name), + ), + Vec::<(Loc, String)>::new(), + vec![ + "Functions are part of a module's public interface and cannot \ + be changed during an upgrade." + .to_string(), + format!( + "Restore the original function '{function_name}' including the ordering.", + function_name = function_name, + ), + ], + )); + + Ok(diags) +} + +fn function_changed_diag( + function_name: &Identifier, + old_function: &Function, + new_function: &Function, + compiled_unit_with_source: &CompiledUnitWithSource, + lookup: &IdentifierTableLookup, +) -> Result { + let mut diags = Diagnostics::new(); + + if old_function != new_function { + diags.extend(function_signature_mismatch_diag( + function_name, + old_function, + new_function, + false, + compiled_unit_with_source, + lookup, + )?); + } + + Ok(diags) +} + /// Return a diagnostic for a type parameter mismatch fn enum_type_param_mismatch( enum_name: &Identifier, old_enum: &Enum, new_enum: &Enum, + public_visibility_related_error: bool, // give a different code for errors which are public visibility related compiled_unit_with_source: &CompiledUnitWithSource, lookup: &IdentifierTableLookup, ) -> Result { @@ -1883,6 +2413,7 @@ fn enum_type_param_mismatch( enum_name, &old_enum.type_parameters, &new_enum.type_parameters, + public_visibility_related_error, def_loc, &enum_sourcemap.type_parameters, ) @@ -1894,6 +2425,7 @@ fn type_parameter_diag( name: &Identifier, old_type_parameters: &[DatatypeTyParameter], new_type_parameters: &[DatatypeTyParameter], + public_visibility_related_error: bool, // give a different code for errors which are public visibility related def_loc: Loc, type_parameter_locs: &[SourceName], ) -> Result { @@ -1925,10 +2457,17 @@ fn type_parameter_diag( ), Vec::<(Loc, String)>::new(), vec![ - format!( - "{capital_declaration_kind}s are part of a module's public interface and \ - cannot be changed during an upgrade." - ), + if public_visibility_related_error { + format!( + "{capital_declaration_kind}s are part of a module's public interface \ + and cannot be removed or changed during a 'compatible' upgrade.", + ) + } else { + format!( + "{capital_declaration_kind}s cannot be removed or changed during an 'additive' or \ + 'dependency only' upgrade." + ) + }, format!( "Restore the original {declaration_kind}'s type {} \ for {declaration_kind} '{name}' including the ordering.", @@ -1956,7 +2495,7 @@ fn type_parameter_diag( vec![ format!( "{capital_declaration_kind}s are part of a module's public interface \ - and cannot be changed during an upgrade." + and cannot be removed or changed during an upgrade." ), fix_note, ], @@ -1973,7 +2512,7 @@ fn type_parameter_diag( vec![ format!( "{capital_declaration_kind}s are part of a module's public interface \ - and cannot be changed during an upgrade." + and cannot be removed or changed during an upgrade." ), fix_note, ], @@ -2031,6 +2570,59 @@ fn type_param_phantom_labels(old_phantom: bool, new_phantom: bool) -> Option<(St }) } +/// Return a diagnostic for package file format version mismatch +fn file_format_version_downgrade_diag( + old_version: &u32, + new_version: &u32, + compiled_unit_with_source: &CompiledUnitWithSource, +) -> Result { + let mut diags = Diagnostics::new(); + + let def_loc = compiled_unit_with_source + .unit + .source_map + .definition_location; + + diags.add(Diagnostic::new( + Declarations::VersionMismatch, + ( + def_loc, + format!( + "Downgrading from file format version {} to {} is not supported.", + old_version, new_version + ), + ), + Vec::<(Loc, String)>::new(), + vec![ + "File format version downgrades are not supported.".to_string(), + "Please upgrade to the latest version of the move language tooling.".to_string(), + ], + )); + + Ok(diags) +} + +/// Return a diagnostic for a friend link mismatch +fn friend_link_diag( + compiled_unit_with_source: &CompiledUnitWithSource, +) -> Result { + let mut diags = Diagnostics::new(); + + let def_loc = compiled_unit_with_source + .unit + .source_map + .definition_location; + + diags.add(Diagnostic::new( + Declarations::FriendMismatch, + (def_loc, "Friends links are mismatched".to_string()), + Vec::<(Loc, String)>::new(), + vec!["Restore the original friend declarations.".to_string()], + )); + + Ok(diags) +} + /// Format a list of items into a human-readable string. fn format_list( items: impl IntoIterator, diff --git a/external-crates/move/crates/move-binary-format/src/compatibility.rs b/external-crates/move/crates/move-binary-format/src/compatibility.rs index a243dc4704b058..9aec29e7e7c9c4 100644 --- a/external-crates/move/crates/move-binary-format/src/compatibility.rs +++ b/external-crates/move/crates/move-binary-format/src/compatibility.rs @@ -425,7 +425,7 @@ impl InclusionCheck { Mark::Missing(name, old) => context.function_missing(name, old), Mark::Existing(name, old, new) => { if old != new { - context.function_change(name, old); + context.function_change(name, old, new); } } } diff --git a/external-crates/move/crates/move-binary-format/src/inclusion_mode.rs b/external-crates/move/crates/move-binary-format/src/inclusion_mode.rs index e229d765ef7b9d..669395b202a146 100644 --- a/external-crates/move/crates/move-binary-format/src/inclusion_mode.rs +++ b/external-crates/move/crates/move-binary-format/src/inclusion_mode.rs @@ -19,12 +19,12 @@ pub trait InclusionCheckMode: Default { fn enum_change(&mut self, name: &Identifier, new_enum: &Enum); fn enum_missing(&mut self, name: &Identifier, old_enum: &Enum); fn function_new(&mut self, name: &Identifier, new_func: &Function); - fn function_change(&mut self, name: &Identifier, new_func: &Function); + fn function_change(&mut self, name: &Identifier, old_func: &Function, new_func: &Function); fn function_missing(&mut self, name: &Identifier, old_func: &Function); fn friend_mismatch(&mut self, old_count: usize, new_count: usize); - fn finish(&self, inclusion: &InclusionCheck) -> Result<(), Self::Error>; + fn finish(self, inclusion: &InclusionCheck) -> Result<(), Self::Error>; } pub struct InclusionCheckExecutionMode { @@ -96,7 +96,7 @@ impl InclusionCheckMode for InclusionCheckExecutionMode { self.is_equal = false; } - fn function_change(&mut self, _name: &Identifier, _new_func: &Function) { + fn function_change(&mut self, _name: &Identifier, _old_func: &Function, _new_func: &Function) { self.is_subset = false; self.is_equal = false; } @@ -110,7 +110,7 @@ impl InclusionCheckMode for InclusionCheckExecutionMode { self.is_equal = false; } - fn finish(&self, inclusion: &InclusionCheck) -> Result<(), Self::Error> { + fn finish(self, inclusion: &InclusionCheck) -> Result<(), Self::Error> { match inclusion { InclusionCheck::Subset if !self.is_subset => Err(()), InclusionCheck::Equal if !self.is_equal => Err(()),