Skip to content

Commit 08c1a55

Browse files
authored
bugfix: fix spurious discarded field errors in --stable-compatible check (#3645)
Fix bug in stable-compatiblity check reported here: https://forum.dfinity.org/t/weird-warning-message-when-deploying-existing-canister/17276/5. The problem is that the verbose check (that emits multiple diagnostic errors) would, on finding a discarded field from the lhs, recurse only on the tail of the rhs, not the rhs itself, causing all remaining fields of the lhs to be reported as discarded, even when present in the (original) rhs. Added a small repro and manually verified it fixes the issue on the full `*.most` files shared by the user in a private forum message. The bug itself is benign though obviously confusing to the user.
1 parent c87082c commit 08c1a55

15 files changed

+312
-10
lines changed

Changelog.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Motoko compiler changelog
22

3+
* motoko (`moc`)
4+
5+
* bugfix: silence bogus cascading errors in stable compatibility check (#3645).
6+
37
## 0.7.4 (2022-12-07)
48

59
* motoko (`moc`)

src/mo_frontend/stability.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ let match_stab_sig tfs1 tfs2 : unit Diag.result =
5959
go tfs1' tfs2'
6060
| -1 ->
6161
error_discard s tf1;
62-
go tfs1' tfs2'
62+
go tfs1' tfs2
6363
| _ ->
6464
go tfs1 tfs2' (* new field ok, recurse on tfs2' *)
6565
)

test/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
QUICK_DIRS = fail idl ld mo-idl repl run
1+
QUICK_DIRS = cmp fail idl ld mo-idl repl run
22
OTHER_DIRS = bench perf run-deser run-drun trap
33
TEST_DIRS = $(QUICK_DIRS) $(OTHER_DIRS)
44
SOURCE_PATHS ?= ../src # will be overridden when building coverage report with nix

test/cmp/files/new.most

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
// Version: 1.0.0
2+
type AccountIdentifier = Text;
3+
type AccountIdentifier__1 = AccountIdentifier;
4+
type AccountIdentifier__2 = AccountIdentifier__1;
5+
type AssetHandle = Text;
6+
type AssetId = Nat32;
7+
type AssetType =
8+
{
9+
#canister : {canister : Text; id : AssetId};
10+
#direct : [ChunkId];
11+
#other : Text
12+
};
13+
type Asset__1 = {atype : AssetType; ctype : Text; filename : Text};
14+
type CapDetailValue =
15+
{
16+
#False;
17+
#Float : Float;
18+
#I64 : Int64;
19+
#Principal : Principal;
20+
#Slice : [Nat8];
21+
#Text : Text;
22+
#True;
23+
#U64 : Nat64;
24+
#Vec : [CapDetailValue]
25+
};
26+
type CapIndefiniteEvent =
27+
{caller : Principal; details : [(Text, CapDetailValue)]; operation : Text};
28+
type ChunkId = Nat32;
29+
type Listing = {locked : ?Time__1; price : Nat64; seller : Principal};
30+
type MetadataContainer =
31+
{#blob : Blob; #data : [MetadataValue]; #json : Text};
32+
type MetadataValue =
33+
(Text, {#blob : Blob; #nat : Nat; #nat8 : Nat8; #text : Text});
34+
type Metadata__1 =
35+
{
36+
#fungible :
37+
{
38+
decimals : Nat8;
39+
metadata : ?MetadataContainer;
40+
name : Text;
41+
symbol : Text
42+
};
43+
#nonfungible :
44+
{
45+
asset : Text;
46+
metadata : ?MetadataContainer;
47+
name : Text;
48+
thumbnail : Text
49+
}
50+
};
51+
type Payment =
52+
{
53+
amount : Nat64;
54+
expires : Time__1;
55+
payer : AccountIdentifier__2;
56+
purchase : PaymentType;
57+
subaccount : SubAccount__2
58+
};
59+
type PaymentType =
60+
{#nft : TokenIndex__1; #nfts : [TokenIndex__1]; #sale : Nat64};
61+
type Sale =
62+
{
63+
end : Time__1;
64+
groups : [SalePricingGroup];
65+
quantity : Nat;
66+
remaining : SaleRemaining;
67+
start : Time__1
68+
};
69+
type SalePricingGroup =
70+
{
71+
end : Time__1;
72+
limit : (Nat64, Nat64);
73+
name : Text;
74+
participants : [AccountIdentifier__2];
75+
pricing : [(Nat64, Nat64)];
76+
start : Time__1
77+
};
78+
type SaleRemaining = {#burn; #retain; #send : AccountIdentifier__2};
79+
type SaleTransaction =
80+
{
81+
buyer : AccountIdentifier__2;
82+
price : Nat64;
83+
seller : Principal;
84+
time : Time__1;
85+
tokens : [TokenIndex__1]
86+
};
87+
type SubAccount = [Nat8];
88+
type SubAccount__1 = SubAccount;
89+
type SubAccount__2 = SubAccount__1;
90+
type Time = Int;
91+
type Time__1 = Time;
92+
type TokenIndex = Nat32;
93+
type TokenIndex__1 = TokenIndex;
94+
type Transaction =
95+
{
96+
buyer : AccountIdentifier__2;
97+
price : Nat64;
98+
seller : AccountIdentifier__2;
99+
time : Time__1;
100+
token : TokenIndex__1
101+
};
102+
actor {
103+
stable var cap_rootBucketId : ?Text;
104+
stable var config_admin : Principal;
105+
stable var config_canCreateAssetCanister : Bool;
106+
stable var config_collection_data : Text;
107+
stable var config_collection_name : Text;
108+
stable var config_initial_sale_royalty_address : Text;
109+
stable var config_marketplace_open : Int;
110+
stable var config_owner : Principal;
111+
stable var config_royalty : [(AccountIdentifier__2, Nat64)];
112+
stable var data_assetCanistersTableState : [(Principal, Nat)];
113+
stable var data_assetsTableState : [(AssetHandle, Asset__1)];
114+
stable var data_capEventsQueueState : [CapIndefiniteEvent];
115+
stable var data_chunksTableState : [(ChunkId, Blob)];
116+
stable var data_disbursementQueueState :
117+
[(TokenIndex__1, AccountIdentifier__2, SubAccount__2, Nat64)];
118+
stable var data_expiredPayments : [(AccountIdentifier__2, SubAccount__2)];
119+
stable var data_internalNextChunkId : Nat32;
120+
stable var data_internalNextSubAccount : Nat;
121+
stable var data_internalNextTokenId : Nat32;
122+
stable var data_internalRunHeartbeat : Bool;
123+
stable var data_ownersTableState :
124+
[(AccountIdentifier__2, [TokenIndex__1])];
125+
stable var data_paymentSettlementsTableState :
126+
[(AccountIdentifier__2, Payment)];
127+
stable var data_registryTableState :
128+
[(TokenIndex__1, AccountIdentifier__2)];
129+
stable var data_saleCurrent : ?Sale;
130+
stable var data_saleGroupsTableState : [(AccountIdentifier__2, Nat)];
131+
stable var data_saleSoldQuantity : Nat;
132+
stable var data_saleSoldTracker : [(Nat, AccountIdentifier__2, Nat64)];
133+
stable var data_saleTokensForSale : [TokenIndex__1];
134+
stable var data_saleTransactions : [SaleTransaction];
135+
stable var data_soldIcp : Nat64;
136+
stable var data_storedChunkSize : Nat;
137+
stable var data_supply : Nat;
138+
stable var data_tokenListingTableState : [(TokenIndex__1, Listing)];
139+
stable var data_tokenMetadataTableState : [(TokenIndex__1, Metadata__1)];
140+
stable var data_transactions : [Transaction];
141+
};

test/cmp/files/old.most

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
// Version: 1.0.0
2+
type AccountIdentifier = Text;
3+
type AccountIdentifier__1 = AccountIdentifier;
4+
type AccountIdentifier__2 = AccountIdentifier__1;
5+
type AssetHandle = Text;
6+
type AssetId = Nat32;
7+
type AssetType =
8+
{
9+
#canister : {canister : Text; id : AssetId};
10+
#direct : [ChunkId];
11+
#other : Text
12+
};
13+
type Asset__1 = {atype : AssetType; ctype : Text; filename : Text};
14+
type CapDetailValue =
15+
{
16+
#False;
17+
#Float : Float;
18+
#I64 : Int64;
19+
#Principal : Principal;
20+
#Slice : [Nat8];
21+
#Text : Text;
22+
#True;
23+
#U64 : Nat64;
24+
#Vec : [CapDetailValue]
25+
};
26+
type CapIndefiniteEvent =
27+
{caller : Principal; details : [(Text, CapDetailValue)]; operation : Text};
28+
type ChunkId = Nat32;
29+
type Listing = {locked : ?Time__1; price : Nat64; seller : Principal};
30+
type MetadataContainer =
31+
{#blob : Blob; #data : [MetadataValue]; #json : Text};
32+
type MetadataValue =
33+
(Text, {#blob : Blob; #nat : Nat; #nat8 : Nat8; #text : Text});
34+
type Metadata__1 =
35+
{
36+
#fungible :
37+
{
38+
decimals : Nat8;
39+
metadata : ?MetadataContainer;
40+
name : Text;
41+
symbol : Text
42+
};
43+
#nonfungible :
44+
{
45+
asset : Text;
46+
metadata : ?MetadataContainer;
47+
name : Text;
48+
thumbnail : Text
49+
}
50+
};
51+
type Payment =
52+
{
53+
amount : Nat64;
54+
expires : Time__1;
55+
payer : AccountIdentifier__2;
56+
purchase : PaymentType;
57+
subaccount : SubAccount__2
58+
};
59+
type PaymentType =
60+
{#nft : TokenIndex__1; #nfts : [TokenIndex__1]; #sale : Nat64};
61+
type Sale =
62+
{
63+
end : Time__1;
64+
groups : [SalePricingGroup];
65+
quantity : Nat;
66+
remaining : SaleRemaining;
67+
start : Time__1
68+
};
69+
type SalePricingGroup =
70+
{
71+
end : Time__1;
72+
limit : (Nat64, Nat64);
73+
name : Text;
74+
participants : [AccountIdentifier__2];
75+
pricing : [(Nat64, Nat64)];
76+
start : Time__1
77+
};
78+
type SaleRemaining = {#burn; #retain; #send : AccountIdentifier__2};
79+
type SaleTransaction =
80+
{
81+
buyer : AccountIdentifier__2;
82+
price : Nat64;
83+
seller : Principal;
84+
time : Time__1;
85+
tokens : [TokenIndex__1]
86+
};
87+
type SubAccount = [Nat8];
88+
type SubAccount__1 = SubAccount;
89+
type SubAccount__2 = SubAccount__1;
90+
type Time = Int;
91+
type Time__1 = Time;
92+
type TokenIndex = Nat32;
93+
type TokenIndex__1 = TokenIndex;
94+
type Transaction =
95+
{
96+
buyer : AccountIdentifier__2;
97+
price : Nat64;
98+
seller : AccountIdentifier__2;
99+
time : Time__1;
100+
token : TokenIndex__1
101+
};
102+
actor {
103+
stable var cap_rootBucketId : ?Text;
104+
stable var config_admin : Principal;
105+
stable var config_canCreateAssetCanister : Bool;
106+
stable var config_collection_data : Text;
107+
stable var config_collection_name : Text;
108+
stable var config_marketplace_open : Int;
109+
stable var config_owner : Principal;
110+
stable var data_assetCanistersTableState : [(Principal, Nat)];
111+
stable var data_assetsTableState : [(AssetHandle, Asset__1)];
112+
stable var data_capEventsQueueState : [CapIndefiniteEvent];
113+
stable var data_chunksTableState : [(ChunkId, Blob)];
114+
stable var data_disbursementQueueState :
115+
[(TokenIndex__1, AccountIdentifier__2, SubAccount__2, Nat64)];
116+
stable var data_expiredPayments : [(AccountIdentifier__2, SubAccount__2)];
117+
stable var data_internalNextChunkId : Nat32;
118+
stable var data_internalNextSubAccount : Nat;
119+
stable var data_internalNextTokenId : Nat32;
120+
stable var data_internalRunHeartbeat : Bool;
121+
stable var data_ownersTableState :
122+
[(AccountIdentifier__2, [TokenIndex__1])];
123+
stable var data_paymentSettlementsTableState :
124+
[(AccountIdentifier__2, Payment)];
125+
stable var data_registryTableState :
126+
[(TokenIndex__1, AccountIdentifier__2)];
127+
stable var data_saleCurrent : ?Sale;
128+
stable var data_saleGroupsTableState : [(AccountIdentifier__2, Nat)];
129+
stable var data_saleSoldQuantity : Nat;
130+
stable var data_saleSoldTracker : [(Nat, AccountIdentifier__2, Nat64)];
131+
stable var data_saleTokensForSale : [TokenIndex__1];
132+
stable var data_saleTransactions : [SaleTransaction];
133+
stable var data_soldIcp : Nat64;
134+
stable var data_storedChunkSize : Nat;
135+
stable var data_supply : Nat;
136+
stable var data_tokenListingTableState : [(TokenIndex__1, Listing)];
137+
stable var data_tokenMetadataTableState : [(TokenIndex__1, Metadata__1)];
138+
stable var data_transactions : [Transaction];
139+
stable var config_royalty_address : Text;
140+
stable var config_royalty_fee : Nat64;
141+
};

test/cmp/neg-xyz-x.cmp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
files/xyz.most files/x.most

test/cmp/neg-xyz-y.cmp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
files/xyz.most files/x.most
1+
files/xyz.most files/y.most
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
(unknown location): Compatibility error [M0170], stable variable state of previous type
22
var {#v1 : [[var Cell]]; #v2 : {bits : [var Nat64]; size : Nat}}
33
cannot be consumed at new type
4-
var {#v1 : [[var Cell/1]]}
4+
var {#v1 : [[var Cell__1]]}
55
FALSE

test/cmp/ok/neg-life-mut-v3-v2.cmp.ok

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@
66
#v3 : {offset : Nat32; size : Nat}
77
}
88
cannot be consumed at new type
9-
var {#v1 : [[var Cell/1]]; #v2 : {bits : [var Nat64]; size : Nat}}
9+
var {#v1 : [[var Cell__1]]; #v2 : {bits : [var Nat64]; size : Nat}}
1010
FALSE

test/cmp/ok/neg-life-v2-v1.cmp.ok

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
(unknown location): Compatibility error [M0170], stable variable state of previous type
22
var {#v1 : [[Cell]]; #v2 : {bits : [Nat64]; size : Nat}}
33
cannot be consumed at new type
4-
var {#v1 : [[Cell/1]]}
4+
var {#v1 : [[Cell__1]]}
55
FALSE

0 commit comments

Comments
 (0)