Skip to main content

leo_errors/errors/
check_interfaces.rs

1// Copyright (C) 2019-2026 Provable Inc.
2// This file is part of the Leo library.
3
4// The Leo library is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// The Leo library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
16
17use std::fmt::{Debug, Display};
18
19create_messages!(
20    CheckInterfacesError,
21    code_mask: 12000i32,
22    code_prefix: "CHI",
23
24    @formatted
25    interface_not_found {
26        args: (name: impl Display),
27        msg: format!("Interface `{name}` not found."),
28        help: Some("Make sure the interface is defined in the current program or an imported program.".to_string()),
29    }
30
31    @formatted
32    conflicting_interface_member {
33        args: (member_name: impl Display, interface_name: impl Display, parent_name: impl Display),
34        msg: format!(
35            "Interface `{interface_name}` has a conflicting definition for `{member_name}` inherited from `{parent_name}`. \
36             Members with the same name must have identical signatures."
37        ),
38        help: Some("Ensure both interfaces define the same signature for this member, or rename one of them.".to_string()),
39    }
40
41    @formatted
42    missing_interface_function {
43        args: (func_name: impl Display, interface_name: impl Display, program_name: impl Display),
44        msg: format!(
45            "Program `{program_name}` implements interface `{interface_name}` but is missing the required function `{func_name}`."
46        ),
47        help: Some("Add the missing function with the exact signature specified in the interface.".to_string()),
48    }
49
50    @formatted
51    missing_interface_record {
52        args: (record_name: impl Display, interface_name: impl Display, program_name: impl Display),
53        msg: format!(
54            "Program `{program_name}` implements interface `{interface_name}` but is missing the required record `{record_name}`."
55        ),
56        help: Some("Add a record definition with the specified name.".to_string()),
57    }
58
59    @formatted
60    signature_mismatch {
61        args: (func_name: impl Display, interface_name: impl Display, expected: impl Display, found: impl Display),
62        msg: format!(
63            "Function `{func_name}` does not match the signature required by interface `{interface_name}`.\n\
64             Expected:\n\
65             {expected}\n\
66             Found:\n\
67             {found}"
68        ),
69        help: Some("Function signatures must match exactly: same parameter names, types, modes, order, and return type.".to_string()),
70    }
71
72    @formatted
73    not_an_interface {
74        args: (name: impl Display),
75        msg: format!("`{name}` is not an interface."),
76        help: Some("Only interface declarations can be inherited from.".to_string()),
77    }
78
79    @formatted
80    missing_interface_mapping {
81        args: (mapping_name: impl Display, interface_name: impl Display, program_name: impl Display),
82        msg: format!(
83            "Program `{program_name}` implements interface `{interface_name}` but is missing the required mapping `{mapping_name}`."
84        ),
85        help: Some("Add a mapping definition with the specified name.".to_string()),
86    }
87
88    @formatted
89    missing_interface_storage {
90        args: (storage_name: impl Display, interface_name: impl Display, program_name: impl Display),
91        msg: format!(
92            "Program `{program_name}` implements interface `{interface_name}` but is missing the required storage variable `{storage_name}`."
93        ),
94        help: Some("Add a storage variable definition with the specified name.".to_string()),
95    }
96
97    @formatted
98    mapping_type_mismatch {
99        args: (mapping_name: impl Display, interface_name: impl Display, expected_key: impl Display, expected_value: impl Display, found_key: impl Display, found_value: impl Display),
100        msg: format!(
101            "Mapping `{mapping_name}` does not match the type required by interface `{interface_name}`.\n\
102             Expected: {expected_key} => {expected_value}\n\
103             Found: {found_key} => {found_value}"
104        ),
105        help: Some("Mapping key and value types must match exactly.".to_string()),
106    }
107
108    @formatted
109    storage_type_mismatch {
110        args: (storage_name: impl Display, interface_name: impl Display, expected: impl Display, found: impl Display),
111        msg: format!(
112            "Storage variable `{storage_name}` does not match the type required by interface `{interface_name}`.\n\
113             Expected: {expected}\n\
114             Found: {found}"
115        ),
116        help: Some("Storage variable types must match exactly.".to_string()),
117    }
118
119    @backtraced
120    cyclic_interface_inheritance {
121        args: (path: impl Display),
122        msg: format!("Cyclic interface inheritance detected: {path}"),
123        help: Some("Interface inheritance must be acyclic. Remove the circular dependency.".to_string()),
124    }
125
126    @formatted
127    conflicting_record_field {
128        args: (field_name: impl Display, record_name: impl Display, interface_name: impl Display, parent_name: impl Display),
129        msg: format!(
130            "Record `{record_name}` has a conflicting definition for field `{field_name}` in interface `{interface_name}` \
131             inherited from `{parent_name}`. Fields with the same name must have identical types and modes."
132        ),
133        help: Some("Ensure both interfaces define the same type and mode for this field, or rename one of them.".to_string()),
134    }
135
136    @formatted
137    record_field_missing {
138        args: (field_name: impl Display, record_name: impl Display, interface_name: impl Display, program_name: impl Display),
139        msg: format!(
140            "Record `{record_name}` in program `{program_name}` is missing required field `{field_name}` \
141             specified by interface `{interface_name}`."
142        ),
143        help: Some("Add the missing field with the exact type and mode specified in the interface.".to_string()),
144    }
145
146    @formatted
147    record_field_type_mismatch {
148        args: (field_name: impl Display, record_name: impl Display, interface_name: impl Display,
149               expected: impl Display, found: impl Display),
150        msg: format!(
151            "Field `{field_name}` in record `{record_name}` does not match the type required by interface `{interface_name}`.\n\
152             Expected: {expected}\n\
153             Found: {found}"
154        ),
155        help: Some("Field types and modes must match exactly.".to_string()),
156    }
157
158    @formatted
159    record_prototype_owner_wrong_type {
160        args: (record_name: impl Display, found_type: impl Display),
161        msg: format!(
162            "Field `owner` in record prototype `{record_name}` must have type `address`, found `{found_type}`. \
163             The `owner` field of a record is always `address`."
164        ),
165        help: None,
166    }
167);