Skip to main content

leo_errors/errors/type_checker/
type_checker_error.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
19// TODO: Consolidate errors.
20
21create_messages!(
22    TypeCheckerError,
23    code_mask: 2000i32,
24    code_prefix: "TYC",
25
26    /// For when the type checker encountered an invalid assignment target.
27    @formatted
28    invalid_assignment_target {
29        args: (target: impl Display),
30        msg: format!("Invalid assignment target: {target}."),
31        help: Some("Valid assignment targets are identifiers, tuple accesses, array accesses, and struct accesses.".to_string()),
32    }
33
34    /// For when the user tries to assign to a const input.
35    @formatted
36    cannot_assign_to_const_input {
37        args: (input: impl Display),
38        msg: format!(
39            "Cannot assign to const input `{input}`",
40        ),
41        help: None,
42    }
43
44    /// For when the user tries to assign to a const input.
45    @formatted
46    cannot_assign_to_const_var {
47        args: (var: impl Display),
48        msg: format!(
49            "Cannot assign to const variable `{var}`",
50        ),
51        help: None,
52    }
53
54    /// For when the user tries to assign to a const input.
55    @formatted
56    type_should_be {
57        args: (type_: impl Display, expected: impl Display),
58        msg: format!(
59            "Expected type `{expected}` but type `{type_}` was found",
60        ),
61        help: None,
62    }
63
64    /// For when the type checker cannot determine the type of an expression.
65    @formatted
66    could_not_determine_type {
67        args: (expr: impl Display),
68        msg: format!(
69            "Could not determine the type of `{expr}`",
70        ),
71        help: Some("Consider using explicit type annotations.".into()),
72    }
73
74    /// For when the user tries to return a unknown variable.
75    @formatted
76    unknown_sym {
77        args: (kind: impl Display, sym: impl Display),
78        msg: format!(
79            "Unknown {kind} `{sym}`",
80        ),
81        help: None,
82    }
83
84    /// For when the user tries calls a function with the incorrect number of args.
85    @formatted
86    incorrect_num_args_to_call {
87        args: (expected: impl Display, received: impl Display),
88        msg: format!(
89            "Call expected `{expected}` args, but got `{received}`",
90        ),
91        help: None,
92    }
93
94    /// For when one of the following types was expected.
95    @formatted
96    expected_one_type_of {
97        args: (expected: impl Display, received: impl Display),
98        msg: format!(
99            "Expected one type from `{expected}`, but got `{received}`",
100        ),
101        help: None,
102    }
103
104    /// For when an integer is not in a valid range.
105    /// Also repurposing for when a group value is not valid.
106    @formatted
107    invalid_int_value {
108        args: (value: impl Display, type_: impl Display),
109        msg: format!(
110            "The value {value} is not a valid `{type_}`",
111        ),
112        help: None,
113    }
114
115    /// For when an invalid core function is used.
116    @formatted
117    invalid_core_function {
118        args: (struct_: impl Display, function: impl Display),
119        msg: format!(
120            "{struct_}::{function} is not a valid core function.",
121        ),
122        help: None,
123    }
124
125    /// For when a struct is created with the same name as a core type.
126    @formatted
127    core_type_name_conflict {
128        args: (type_: impl Display),
129        msg: format!(
130            "The type {type_} is a reserved core type name.",
131        ),
132        help: None,
133    }
134
135    /// For when a function doesn't have a return statement.
136    @formatted
137    function_has_no_return {
138        args: (func: impl Display),
139        msg: format!(
140            "The function {func} has no return statement.",
141        ),
142        help: None,
143    }
144
145    /// For when the user tries initialize a composite with the incorrect number of args.
146    @formatted
147    incorrect_num_composite_members {
148        args: (expected: impl Display, received: impl Display),
149        msg: format!(
150            "Composite expected `{expected}` members, but got `{received}`",
151        ),
152        help: None,
153    }
154
155    /// For when the user is missing a composite member during initialization.
156    @formatted
157    missing_composite_member {
158        args: (composite: impl Display, member: impl Display),
159        msg: format!(
160            "Composite initialization expression for `{composite}` is missing member `{member}`.",
161        ),
162        help: None,
163    }
164
165    /// An invalid access call is made e.g., `SHA256::hash()
166    @formatted
167    invalid_core_function_call {
168        args: (expr: impl Display),
169        msg: format!(
170            "{expr} is not a valid core function call."
171        ),
172        help: None,
173    }
174
175    /// Attempted to define more that one struct member with the same name.
176    @formatted
177    duplicate_struct_member {
178        args: (member_name: impl Display),
179        msg: format!(
180            "Struct field `{member_name}` is already declared."
181        ),
182        help: None,
183    }
184
185    /// Attempted to define more that one record variable with the same name.
186    @formatted
187    duplicate_record_variable {
188        args: (variable_name: impl Display),
189        msg: format!(
190            "Record variable `{variable_name}` is already declared."
191        ),
192        help: None,
193    }
194
195    /// Attempted to access an invalid struct.
196    @formatted
197    undefined_type {
198        args: (type_: impl Display),
199        msg: format!(
200            "The type `{type_}` is not found in the current scope."
201        ),
202        help: Some("If you are using an external type, make sure to preface with the program name. Ex: `credits.aleo::credits` instead of `credits`".to_string()),
203    }
204
205    /// Attempted to access an invalid composite variable.
206    @formatted
207    invalid_composite_variable {
208        args: (variable: impl Display, composite: impl Display),
209        msg: format!(
210            "Variable {variable} is not a member of {composite}."
211        ),
212        help: None,
213    }
214
215    @formatted
216    required_record_variable {
217        args: (name: impl Display, type_: impl Display),
218        msg: format!("The `record` type requires the variable `{name}: {type_}`."),
219        help: None,
220    }
221
222    @formatted
223    record_var_wrong_type {
224        args: (name: impl Display, type_: impl Display),
225        msg: format!("The field `{name}` in a `record` must have type `{type_}`."),
226        help: None,
227    }
228
229    @formatted
230    compare_address {
231        args: (operator: impl Display),
232        msg: format!("Comparison `{operator}` is not supported for the address type."),
233        help: None,
234    }
235
236    @formatted
237    incorrect_tuple_length {
238        args: (expected: impl Display, actual: impl Display),
239        msg: format!("Expected a tuple of length `{expected}` found length `{actual}`"),
240        help: None,
241    }
242
243    @formatted
244    invalid_tuple {
245        args: (),
246        msg: "Tuples must be explicitly typed in Leo".to_string(),
247        help: Some("The function definition must match the function return statement".to_string()),
248    }
249
250    @formatted
251    tuple_out_of_range {
252        args: (index: impl Display, length: impl Display),
253        msg: format!("Tuple index `{index}` out of range for a tuple with length `{length}`"),
254        help: None,
255    }
256
257    @formatted
258    unreachable_code_after_return {
259        args: (),
260        msg: format!("Cannot reach the following statement."),
261        help: Some("Remove the unreachable code.".to_string()),
262    }
263
264    @formatted
265    loop_body_contains_return {
266        args: (),
267        msg: format!("Loop body contains a return statement or always returns."),
268        help: Some("Remove the code in the loop body that always returns.".to_string()),
269    }
270
271    // TODO: Consider emitting a warning instead of an error.
272    @formatted
273    unknown_annotation {
274        args: (annotation: impl Display),
275        msg: format!("Unknown annotation: `{annotation}`."),
276        help: None,
277    }
278
279    @formatted
280    regular_function_inputs_cannot_have_modes {
281        args: (),
282        msg: format!("Regular fns cannot have modes associated with their inputs."),
283        help: Some("Consider removing the mode or moving this function inside the `program` block to make it an entry point fn.".to_string()),
284    }
285
286    // Not currently used
287    @formatted
288    final_function_input_cannot_be_private {
289        args: (),
290        msg: format!("Final fns cannot have private inputs."),
291        help: Some("Use a `public` modifier to the input variable declaration or remove the visibility modifier entirely.".to_string()),
292    }
293
294    @formatted
295    struct_or_record_cannot_contain_record {
296        args: (parent: impl Display, child: impl Display),
297        msg: format!("A struct or record cannot contain another record."),
298        help: Some(format!("Remove the record `{child}` from `{parent}`.")),
299    }
300
301    @formatted
302    invalid_mapping_type {
303        args: (component: impl Display, type_: impl Display),
304        msg: format!("A mapping's {component} cannot be a {type_}"),
305        help: None,
306    }
307
308    @formatted
309    final_fn_input_must_be_public {
310        args: (),
311        msg: format!("An input to an final fn must be public."),
312        help: Some("Use a `public` modifier to the input variable declaration or remove the visibility modifier entirely.".to_string()),
313    }
314
315    // Not currently used
316    @formatted
317    finalize_output_mode_must_be_public {
318        args: (),
319        msg: format!("An output from a final block must be public."),
320        help: Some("Use a `public` modifier to the output type declaration or remove the visibility modifier entirely.".to_string()),
321    }
322
323    @formatted
324    invalid_operation_outside_finalize {
325        args: (operation: impl Display),
326        msg: format!("`{operation}` must be inside a `final fn` or a `final` block."),
327        help: None,
328    }
329
330    @formatted
331    loop_body_contains_final {
332        args: (),
333        msg: format!("Loop body contains a final context."),
334        help: Some("Remove the final context.".into()),
335    }
336
337    @formatted
338    missing_return {
339        args: (),
340        msg: format!("Function must return a value."),
341        help: None,
342    }
343
344    // TODO This error is unused. Remove it in a future version.
345    @formatted
346    finalize_block_must_not_be_empty {
347        args: (),
348        msg: format!("A final block cannot be empty."),
349        help: None,
350    }
351
352    @formatted
353    cannot_have_constant_output_mode {
354        args: (),
355        msg: format!("A returned value cannot be a constant."),
356        help: None,
357    }
358
359    @formatted
360    entry_point_fn_inputs_cannot_be_const {
361        args: (),
362        msg: format!("Entry point functions cannot have constant inputs."),
363        help: None,
364    }
365
366    @formatted
367    invalid_self_access {
368        args: (),
369        msg: format!("The allowed accesses to `self` are `self.{{caller, checksum, edition, program_owner, signer}}`."),
370        help: None,
371    }
372
373    @formatted
374    invalid_type {
375        args: (type_: impl Display),
376        msg: format!("Invalid type `{type_}`"),
377        help: None,
378    }
379
380    @formatted
381    can_only_call_inline_function {
382        args: (kind: impl Display),
383        msg: format!("Only regular fns can be called from {kind}."),
384        help: None,
385    }
386
387    @formatted
388    cannot_invoke_call_to_local_entry_point_fn {
389        args: (),
390        msg: format!("Cannot call a local entry point fn from an entry point fn."),
391        help: None,
392    }
393
394    @formatted
395    loop_bound_must_be_a_literal {
396        args: (),
397        msg: format!("Loop bound must be a literal."),
398        help: None,
399    }
400
401    @formatted
402    strings_are_not_supported {
403        args: (),
404        msg: format!("Strings are not yet supported."),
405        help: None,
406    }
407
408    @formatted
409    imported_program_cannot_import_program {
410        args: (),
411        msg: format!("An imported program cannot import another program."),
412        help: None,
413    }
414
415    @formatted
416    too_many_entry_points {
417        args: (max: impl Display),
418        msg: format!("The number of entry point fns exceeds the maximum. snarkVM allows up to {max} entry point fns within a single program."),
419        help: None,
420    }
421
422    // TODO This error is unused. Remove it in a future version.
423    @formatted
424    assign_unit_expression_to_variable {
425        args: (),
426        msg: format!("Cannot assign a unit expression to a variable."),
427        help: None,
428    }
429
430    @formatted
431    nested_tuple_type {
432        args: (),
433        msg: format!("A tuple type cannot contain a tuple."),
434        help: None,
435    }
436
437    @formatted
438    composite_data_type_cannot_contain_tuple {
439        args: (data_type: impl Display),
440        msg: format!("A {data_type} cannot contain a tuple."),
441        help: None,
442    }
443
444    @formatted
445    function_cannot_take_tuple_as_input {
446        args: (),
447        msg: format!("A function cannot take in a tuple as input."),
448        help: None,
449    }
450
451    @formatted
452    nested_tuple_expression {
453        args: (),
454        msg: format!("A tuple expression cannot contain another tuple expression."),
455        help: None,
456    }
457
458    @formatted
459    expression_statement_must_be_function_call {
460        args: (),
461        msg: format!("An expression statement must be a function call."),
462        help: None,
463    }
464
465    @formatted
466    lhs_tuple_element_must_be_an_identifier {
467        args: (),
468        msg: format!("Tuples on the left-hand side of a `DefinitionStatement` can only contain identifiers."),
469        help: None,
470    }
471
472    @formatted
473    lhs_must_be_identifier_or_tuple {
474        args: (),
475        msg: format!("The left-hand side of a `DefinitionStatement` can only be an identifier or tuple. Note that a tuple must contain at least two elements."),
476        help: None,
477    }
478
479    // TODO This error is unused. Remove it in a future version.
480    @formatted
481    unit_expression_only_in_return_statements {
482        args: (),
483        msg: format!("Unit expressions can only be used in return statements."),
484        help: None,
485    }
486
487    @formatted
488    function_cannot_input_or_output_a_record {
489        args: (),
490        msg: format!("Only entry point fns can have a record as input or output."),
491        help: None,
492    }
493
494    @backtraced
495    cyclic_composite_dependency {
496        args: (path: Vec<impl Display>),
497        msg: {
498            let path_string = path.into_iter().map(|name| format!("`{name}`")).collect::<Vec<String>>().join(" --> ");
499            format!("Cyclic dependency between composites: {path_string}")
500        },
501        help: None,
502    }
503
504    @backtraced
505    cyclic_function_dependency {
506        args: (path: Vec<impl Display>),
507        msg: {
508            let path_string = path.into_iter().map(|name| format!("`{name}`")).collect::<Vec<String>>().join(" --> ");
509            format!("Cyclic dependency between functions: {path_string}")
510        },
511        help: None,
512    }
513
514    @formatted
515    struct_cannot_have_member_mode {
516        args: (),
517        msg: format!("A struct cannot have a member with mode `constant`, `private`, or `public`."),
518        help: None,
519    }
520
521    // Unused
522    @formatted
523    cannot_call_external_inline_function {
524        args: (),
525        msg: format!("Cannot call an external inline function."),
526        help: None,
527    }
528
529    @formatted
530    too_many_mappings {
531        args: (max: impl Display),
532        msg: format!("The number of mappings exceeds the maximum. snarkVM allows up to {max} mappings within a single program."),
533        help: None,
534    }
535
536    /// A call to an invalid associated constant is made e.g., `bool::MAX`
537    @formatted
538    invalid_associated_constant {
539        args: (expr: impl Display),
540        msg: format!(
541            "{expr} is not a valid associated constant."
542        ),
543        help: None,
544    }
545
546    /// For when an invalid core constant is called.
547    @formatted
548    invalid_core_constant {
549        args: (type_: impl Display, constant: impl Display),
550        msg: format! (
551            "{type_}::{constant} is not a valid core constant.",
552        ),
553        help: None,
554    }
555
556    /// For when an invalid field of block is called.
557    @formatted
558    invalid_block_access {
559        args: (),
560        msg: format!("The allowed accesses to `block` are `block.height` and `block.timestamp`."),
561        help: None,
562    }
563
564    @formatted
565    invalid_operation_inside_finalize {
566        args: (operation: impl Display),
567        msg: format!("`{operation}` is not a valid operand in a finalization context."),
568        help: None,
569    }
570
571    @formatted
572    operation_must_be_in_final_block_or_function {
573        args: (),
574        msg: "This operation can only be used in a final fn, a final block, or script.".to_string(),
575        help: None,
576    }
577
578    @formatted
579    loop_range_decreasing {
580        args: (),
581        msg: format!("The loop range must be increasing."),
582        help: None,
583    }
584
585    @formatted
586    loop_bound_type_mismatch {
587        args: (),
588        msg: format!("The loop bounds must be same type"),
589        help: None,
590    }
591
592    // TODO This error is unused. Remove it in a future version.
593    @formatted
594    const_declaration_must_be_literal_or_tuple_of_literals {
595        args: (),
596        msg: format!("The value of a const declaration must be a literal"),
597        help: None,
598    }
599
600    // TODO This error is unused. Remove it in a future version.
601    @formatted
602    loop_bound_must_be_literal_or_const {
603        args: (),
604        msg: format!("The loop bound must be a literal or a const"),
605        help: None,
606    }
607
608    @formatted
609    incorrect_num_tuple_elements {
610        args: (identifiers: impl Display, types: impl Display),
611        msg: format!("Expected a tuple with {types} elements, found one with {identifiers} elements"),
612        help: None,
613    }
614
615    @formatted
616    const_declaration_can_only_have_one_binding {
617        args: (),
618        msg: format!("A constant declaration statement can only bind a single value"),
619        help: None,
620    }
621
622    @formatted
623    stub_functions_must_not_be_inlines {
624        args: (),
625        msg: format!("Function stubs must be entry point fns or regular fns"),
626        help: None,
627    }
628
629    @formatted
630    stub_functions_must_be_empty {
631        args: (),
632        msg: format!("Functions stubs must be empty"),
633        help: None,
634    }
635
636    @formatted
637    array_empty {
638        args: (),
639        msg: format!("An array cannot be empty"),
640        help: None,
641    }
642
643    @formatted
644    array_too_large {
645        args: (size: impl Display, max: impl Display),
646        msg: format!("An array cannot have more than {max} elements, found one with {size} elements"),
647        help: None,
648    }
649
650    @formatted
651    array_element_cannot_be_tuple {
652        args: (),
653        msg: format!("An array cannot have a tuple as an element type"),
654        help: None,
655    }
656
657    @formatted
658    array_element_cannot_be_record {
659        args: (),
660        msg: format!("An array cannot have a record as an element type"),
661        help: None,
662    }
663
664    @formatted
665    stubs_cannot_have_non_record_structs {
666        args: (),
667        msg: format!("Stubs can only have records, entry point fns, regular fns, mappings and imports -- found non-record struct"),
668        help: None,
669    }
670
671    @formatted
672    stubs_cannot_have_const_declarations {
673        args: (),
674        msg: format!("Stubs can only have records, entry point fns, regular fns, mappings and imports -- found const declaration"),
675        help: None,
676    }
677
678    @formatted
679    stub_name_mismatch {
680        args: (stub_name: impl Display, program_name: impl Display),
681        msg: format!("`stub` name `{stub_name}` does not match program name `{program_name}`"),
682        help: Some("Check that the name you used as a dependency in program.json matches the name you used to import the program in the main leo file.".to_string()),
683    }
684
685    @formatted
686    no_entry_points {
687        args: (),
688        msg: "A program must have at least one entry point fn.".to_string(),
689        help: None,
690    }
691
692    @formatted
693    cannot_define_external_struct {
694        args: (struct_: impl Display),
695        msg: format!("Cannot define external struct `{struct_}`"),
696        help: Some("Copy the external definition of the struct into the current program, and then define without the `.aleo` extension.".to_string()),
697    }
698
699    @formatted
700    struct_definitions_dont_match {
701        args: (struct_: impl Display, program_1: impl Display, program_2: impl Display),
702        msg: format!("The definition for `{struct_}` in program `{program_1}.aleo` does not match the definition in program `{program_2}.aleo`"),
703        help: Some("Check that the struct definition in the current program matches the definition in the imported program.".to_string()),
704    }
705
706    @formatted
707    entry_point_fn_final_invalid_output {
708        args: (),
709        msg: "An entry point fn returning Final must return a Final as the final output, and in no other position return a Final.".to_string(),
710        help: Some("Example: `fn foo() -> (u8, bool, Final) {...}`".to_string()),
711    }
712
713    @formatted
714    must_propagate_all_finals {
715        args: (never_propagated: impl Display),
716        msg: format!("All Finals generated from external calls must be inserted into a final block in the order they were called. The following were never were: {never_propagated}"),
717        help: Some("Example: `fn foo() -> Final { let a: Final = b.aleo::bar(); return final {{ a.run(); }}; }`".to_string()),
718    }
719
720    // deprecated
721    @formatted
722    missing_final_operation_in_entry_point_with_final {
723        args: (),
724        msg: "An entry point fn returning `Final` must contain at least one finalization operation — either a call to a `final fn` or a `final` block.".to_string(),
725        help: Some("Example: `fn foo() -> Final { return final {{ /* on-chain code */ }}; }`".to_string()),
726    }
727
728    // TODO This error is unused. Remove it in a future version.
729    @formatted
730    final_function_input_length_mismatch {
731        args: (expected: impl Display, received: impl Display),
732        msg: format!("Expected `{expected}` inputs, but got `{received}`"),
733        help: Some("Check that the number of arguments passed in are the same as the number in the function signature. Ex: `final fn foo(a: u8, b: u8)` has two input arguments.".to_string()),
734    }
735
736    @formatted
737    invalid_final_access {
738        args: (num: impl Display, len: impl Display),
739        msg: format!(
740            "Cannot access argument `{num}` from Final. The Final only has `{len}` arguments."
741        ),
742        help: None,
743    }
744
745    @formatted
746    final_access_must_be_number {
747        args: (name: impl Display),
748        msg: format!("Final access must be a number not `{name}`."),
749        help: Some(" Final arguments must be addressed by their index. Ex: `f.1.3`.".to_string()),
750    }
751
752    // TODO: This error is deprecated. Remove.
753    @formatted
754    no_path_awaits_all_finals_exactly_once {
755        args: (num_total_paths: impl Display),
756        msg: format!("Finals must be run exactly once. Out of `{num_total_paths}`, there does not exist a single path in which all Finals are run exactly once."),
757        help: Some("Ex: for `f: Final` call `f.run()` to run a Final. Remove duplicate Final run redundancies, and add Final runs for un-run Finals.".to_string()),
758    }
759
760    // TODO: This error is deprecated. Remove.
761    @formatted
762    final_runs_missing {
763        args: (unawaited: impl Display),
764        msg: format!("The following Finals were never run: {unawaited}"),
765        help: Some("Ex: for `f: Final` call `f.run()` to run a Final.".to_string()),
766    }
767
768    @formatted
769    cannot_reassign_final_variable {
770        args: (var: impl Display),
771        msg: format!("Cannot reassign variable `{var}` since it has type Final."),
772        help: Some("Finals can only be defined as the result of final fn calls or final blocks.".to_string()),
773    }
774
775    // TODO: This error is deprecated. Remove.
776    @formatted
777    invalid_await_call {
778        args: (),
779        msg: "Not a valid run call.".to_string(),
780        help: Some("Ex: for `f: Final` call `f.run()` to run a Final.".to_string()),
781    }
782
783    @formatted
784    can_only_run_one_final_at_a_time {
785        args: (),
786        msg: "Must run exactly one Final at a time".to_string(),
787        help: Some("Ex: for `f: Final` call `f.run()` to run a Final.".to_string()),
788    }
789
790    // TODO: This error is deprecated. Remove.
791    @formatted
792    expected_final {
793        args: (type_: impl Display),
794        msg: format!("Expected a Final, but found `{type_}`"),
795        help: Some("Only Finals can be run.".to_string()),
796    }
797
798    @formatted
799    invalid_method_call {
800        args: (),
801        msg: "Not a valid method call.".to_string(),
802        help: Some("For a `f: Final`, call the associated method `f.run()`.".to_string()),
803    }
804
805    // deprecated
806    @formatted
807    final_call_in_conditional {
808        args: (),
809        msg: "Cannot call a final fn in a conditional block.".to_string(),
810        help: Some("Move the final fn call outside of the conditional block.".to_string()),
811    }
812
813    // deprecated
814    @formatted
815    must_call_final_fn_once {
816        args: (),
817        msg: "Must call exactly one local final fn per entry point fn.".to_string(),
818        help: Some("Move the final fn call outside of the entry point fn.".to_string()),
819    }
820
821    // deprecated
822    @formatted
823    final_call_can_only_be_done_from_final_entry_point {
824        args: (),
825        msg: "Can only call a final fn from an entry point fn returning Final.".to_string(),
826        help: Some("Move the final fn call inside an entry point fn that returns Final.".to_string()),
827    }
828
829    @formatted
830    external_call_after_final {
831        args: (kind: impl Display),
832        msg: format!("External calls must appear before the local final {kind}."),
833        help: Some(format!("Reorder your code so the external entry point fn call happens before the local final {kind}.")),
834    }
835
836    @formatted
837    unknown_final_consumed {
838        args: (fin: impl Display),
839        msg: format!("Unknown Final consumed: `{fin}`"),
840        help: Some("Make sure the Final is defined and consumed exactly once.".to_string()),
841    }
842
843    @formatted
844    not_all_finals_consumed {
845        args: (unconsumed: impl Display),
846        msg: format!("Not all Finals were consumed: {unconsumed}"),
847        help: Some("Make sure all Finals are consumed exactly once. Consume by passing to a final fn call or final block.".to_string()),
848    }
849
850    @formatted
851    entry_point_missing_final_to_return {
852        args: (),
853        msg: "An entry point fn returning Final must return a Final.".to_string(),
854        help: Some("Instantiate a final block inside the entry point fn body so that there is a Final to return.".to_string()),
855    }
856
857    @formatted
858    final_fn_cannot_return_value {
859        args: (),
860        msg: "A final fn is not allowed to return a value.".to_string(),
861        help: Some("Remove an output type in the function signature, and remove the return statement from the function. Note that the Final returned by final fn is automatically inferred, and must not be explicitly written.".to_string()),
862    }
863
864    // deprecated
865    @formatted
866    return_type_of_finalize_function_is_final {
867        args: (),
868        msg: "The output of a final fn must be assigned to a `Final` type.".to_string(),
869        help: None,
870    }
871
872    @formatted
873    cannot_modify_external_container {
874        args: (operation: impl Display, kind: impl Display),
875        msg: format!("Cannot use operation `{operation}` on external {kind}s."),
876        help: Some(format!("The only valid operations on external {kind}s are {}.",
877            if kind.to_string() == "vector" {
878                "`get` and `len`"
879            } else if kind.to_string() == "mapping" {
880                "`contains`, `get`, and `get_or_use`"
881            } else {
882                panic!("no other kinds expected here")
883            }
884        )),
885    }
886
887    @formatted
888    final_cannot_assign_outside_conditional {
889        args: (variable: impl Display, kind: impl Display),
890        msg: format!("Cannot re-assign to `{variable}` from a conditional scope to an outer scope in a final {kind}."),
891        help: Some("This is a fundamental restriction that can often be avoided by using a ternary operator `?` or re-declaring the variable in the current scope. In the future, ARC XXXX (https://github.com/ProvableHQ/ARCs) will support more complex assignments in final fns.".to_string()),
892    }
893
894    @formatted
895    only_entry_point_can_return_final {
896        args: (),
897        msg: "Only entry point fns can return a Final.".to_string(),
898        help: Some("Move this function inside the `program` block to make it an entry point fn.".to_string()),
899    }
900
901    // deprecated
902    @formatted
903    final_fn_not_found {
904        args: (name: impl Display),
905        msg: format!("The final fn `{name}` does not exist."),
906        help: Some(format!("Ensure that `{name}` is defined as a `final fn` in the current program.")),
907    }
908
909    @formatted
910    empty_struct {
911        args: (),
912        msg: "A struct must have at least one member.".to_string(),
913        help: None,
914    }
915
916    @formatted
917    empty_function_arglist {
918        args: (),
919        msg: format!("Cannot define a function with no parameters."),
920        help: None,
921    }
922
923    @formatted
924    composite_data_type_cannot_contain_final {
925        args: (data_type: impl Display),
926        msg: format!("A {data_type} cannot contain a Final."),
927        help: None,
928    }
929
930    @formatted
931    array_element_cannot_be_final {
932        args: (),
933        msg: format!("An array cannot have a Final as an element type."),
934        help: None,
935    }
936
937    @formatted
938    no_final_parameters {
939        args: (),
940        msg: format!("Finals may only appear as parameters to final fn."),
941        help: None,
942    }
943
944    /// For when the user tries to assign to a const input.
945    ///
946    /// This is a replacement for `type_should_be` with a slightly better message.
947    @formatted
948    type_should_be2 {
949        args: (type_: impl Display, expected: impl Display),
950        msg: format!(
951            "Expected {expected} but type `{type_}` was found.",
952        ),
953        help: None,
954    }
955
956    @formatted
957    ternary_branch_mismatch {
958        args: (type1: impl Display, type2: impl Display),
959        msg: format!(
960            "Received different types `{type1}` and `{type2}` for the arms of a ternary conditional."
961        ),
962        help: Some("Make both branches the same type.".into()),
963    }
964
965    @formatted
966    operation_types_mismatch {
967        args: (operation: impl Display, type1: impl Display, type2: impl Display),
968        msg: format!(
969            "Received different types `{type1}` and `{type2}` for the operation `{operation}`."
970        ),
971        help: Some("Make both operands the same type.".into()),
972    }
973
974    @formatted
975    mul_types_mismatch {
976        args: (type1: impl Display, type2: impl Display),
977        msg: format!(
978            "Received types `{type1}` and `{type2}` for the operation `*`."
979        ),
980        help: Some("Valid operands are two integers of the same type, two fields, or a scalar and a group.".into()),
981    }
982
983    @formatted
984    pow_types_mismatch {
985        args: (type1: impl Display, type2: impl Display),
986        msg: format!(
987            "Received types `{type1}` and `{type2}` for the operation `pow`."
988        ),
989        help: Some("Valid operands are two fields, or an integer base and a `u8`, `u16`, or `u32` exponent.".into()),
990    }
991
992    @formatted
993    shift_type_magnitude {
994        args: (operation: impl Display, rhs_type: impl Display),
995        msg: format!(
996            "Received type `{rhs_type}` for the second operand of the operation `{operation}`."
997        ),
998        help: Some("Valid second operands are `u8`, `u16`, or `u32`".into()),
999    }
1000
1001    @formatted
1002    unit_type_only_return {
1003        args: (),
1004        msg: "The unit type () may appear only as the return type of a function.".to_string(),
1005        help: None,
1006    }
1007
1008    @formatted
1009    final_error_member {
1010        args: (num: impl Display),
1011        msg: format!("Cannot access argument `{num}` from Final."),
1012        help: Some(
1013            "Ensure that the final fn is not called multiple times with incompatible types.".to_string()
1014        ),
1015    }
1016
1017    @formatted
1018    cannot_reassign_mapping {
1019        args: (var: impl Display),
1020        msg: format!("Cannot assign to the mapping `{var}`."),
1021        help: None,
1022    }
1023
1024    @formatted
1025    records_not_allowed_inside_final {
1026        args: (),
1027        msg: format!("records cannot be instantiated in a final context."),
1028        help: None,
1029    }
1030
1031    @formatted
1032    script_in_non_test {
1033        args: (func: impl Display),
1034        msg: format!("`script` {func} appears in a non-test program."),
1035        help: Some("Move this to a test program, or replace it with a function.".to_string()),
1036    }
1037
1038    @formatted
1039    non_script_calls_script {
1040        args: (call: impl Display),
1041        msg: format!("`script` {call} is called by a non-`script`."),
1042        help: None,
1043    }
1044
1045    @formatted
1046    annotation_error {
1047        args: (message: impl Display),
1048        msg: format!("Invalid annotation: {message}."),
1049        help: None,
1050    }
1051
1052    @formatted
1053    ternary_over_external_records {
1054        args: (ty: impl Display),
1055        msg: format!("Cannot apply ternary conditional to type `{ty}`."),
1056        help: Some("Ternary conditionals may not contain an external record type.".to_string()),
1057    }
1058
1059    // TODO: unused.
1060    @formatted
1061    assignment_to_external_record {
1062        args: (ty: impl Display),
1063        msg: format!("Cannot assign to type `{ty}` or a member thereof."),
1064        help: Some("External record types and tuples containing them may not be assigned to.".to_string()),
1065    }
1066
1067    // TODO This error is unused. Remove it in a future version.
1068    @formatted
1069    illegal_name {
1070        args: (item_name: impl Display, item_type: impl Display, keyword: impl Display),
1071        msg: format!("`{item_name}` is an invalid {item_type} name. A {item_type} cannot have \"{keyword}\" in its name."),
1072        help: None,
1073    }
1074
1075    @formatted
1076    record_prefixed_by_other_record {
1077        args: (r1: impl Display, r2: impl Display),
1078        msg: format!("Record name `{r1}` is prefixed by the record name `{r2}`. Record names must not be prefixes of other record names."),
1079        help: None,
1080    }
1081
1082    @formatted
1083    range_bounds_type_mismatch {
1084        args: (),
1085        msg: format!("mismatched types in loop iterator range bounds"),
1086        help: None,
1087    }
1088
1089    @formatted
1090    assignment_to_external_record_member {
1091        args: (ty: impl Display),
1092        msg: format!("Cannot assign to a member of the external record `{ty}`."),
1093        help: None,
1094    }
1095
1096    @formatted
1097    assignment_to_external_record_cond {
1098        args: (ty: impl Display),
1099        msg: format!("Cannot assign to the external record type `{ty}` in this location."),
1100        help: Some("External record variables may not be assigned to in narrower conditional scopes than they were defined.".into()),
1101    }
1102
1103    @formatted
1104    assignment_to_external_record_tuple_cond {
1105        args: (ty: impl Display),
1106        msg: format!("Cannot assign to the tuple type `{ty}` containing an external record in this location."),
1107        help: Some("Tuples containing external records may not be assigned to in narrower conditional scopes than they were defined.".into()),
1108    }
1109
1110    @formatted
1111    hexbin_literal_nonintegers {
1112        args: (),
1113        msg: format!("Hex, octal, and binary literals may only be used for integer types."),
1114        help: None,
1115    }
1116
1117    @formatted
1118    unexpected_unsuffixed_numeral {
1119        args: (expected: impl Display),
1120        msg: format!(
1121            "Expected {expected} but an unsuffixed numeral was found.",
1122        ),
1123        help: None,
1124    }
1125
1126    @formatted
1127    incorrect_num_const_args {
1128        args: (kind: impl Display, expected: impl Display, received: impl Display),
1129        msg: format!(
1130            "{kind} expected `{expected}` const args, but got `{received}`",
1131        ),
1132        help: None,
1133    }
1134
1135    @formatted
1136    bad_const_generic_type {
1137        args: (found: impl Display),
1138        msg: format!("A generic const parameter must be a `bool`, an integer, a `scalar`, a `group`, a `field`, or an `address`, but {found} was found"),
1139        help: None,
1140    }
1141
1142    /// For when the user tries to assign to a generic const function parameter.
1143    @formatted
1144    cannot_assign_to_generic_const_function_parameter {
1145        args: (param: impl Display),
1146        msg: format!(
1147            "Cannot assign to const parameter `{param}`",
1148        ),
1149        help: None,
1150    }
1151
1152    @formatted
1153    only_inline_can_have_const_generics {
1154        args: (),
1155        msg: format!("Only inlined functions can have generic const parameters."),
1156        help: None,
1157    }
1158
1159    @formatted
1160    array_too_large_for_u32 {
1161        args: (),
1162        msg: format!("An array length must be small enough to fit in a `u32`"),
1163        help: None,
1164    }
1165
1166    @formatted
1167    unexpected_record_const_parameters {
1168        args: (),
1169        msg: format!("Records cannot be declared with generic const parameters."),
1170        help: None,
1171    }
1172
1173    @formatted
1174    unexpected_const_args {
1175        args: (item: impl Display),
1176        msg: format!("unexpected generic const argment for {item}."),
1177        help: Some("If this is an external struct, consider using a resolved non-generic version of it instead. External structs can't be instantiated with const arguments".to_string()),
1178    }
1179
1180    @formatted
1181    invalid_operation_inside_final_block {
1182        args: (operation: impl Display),
1183        msg: format!("Invalid expression in a final block. `{operation}` cannot be used directly here."),
1184        help: Some(format!("Bind `{operation}` to a variable before the `final` block: `let val = {operation};`")),
1185    }
1186
1187    @formatted
1188    illegal_final_block_location {
1189        args: (),
1190        msg: "`final` blocks are only allowed inside an entry point fn returning `Final` or a script function.".to_string(),
1191        help: Some("Try moving this `final` block into an entry point fn or a script function.".to_string()),
1192    }
1193
1194    // deprecated
1195    @formatted
1196    conflicting_final_call_and_block {
1197        args: (),
1198        msg: "An entry point fn cannot contain both a `final fn` call and a `final` block at the same time.".to_string(),
1199        help: Some("Refactor the entry point fn to use either a `final fn` call or a `final` block, but not both.".to_string()),
1200    }
1201
1202    @formatted
1203    multiple_final_blocks_not_allowed {
1204        args: (),
1205        msg: "An entry point fn cannot contain more than one `final` block.".to_string(),
1206        help: Some("Combine the logic into a single `final` block, or restructure your code to avoid multiple final blocks within the same entry point fn.".to_string()),
1207    }
1208
1209    @formatted
1210    final_block_in_conditional {
1211        args: (),
1212        msg: "`final` blocks are not allowed inside conditional blocks.".to_string(),
1213        help: Some("Refactor your code to move the `final` block outside of the conditional block.".to_string()),
1214    }
1215
1216    @formatted
1217    cannot_use_private_inpt_in_final_block {
1218        args: (),
1219        msg: format!("`private` inputs cannot be used inside final blocks."),
1220        help: None,
1221    }
1222
1223    @formatted
1224    final_block_cannot_return {
1225        args: (),
1226        msg: "A `final` block cannot contain a `return` statement.".to_string(),
1227        help: None,
1228    }
1229
1230    // deprecated
1231    @formatted
1232    invalid_final_block_final_access {
1233        args: (),
1234        msg: format!(
1235            "Cannot access argument from Final produced by a `final` block."
1236        ),
1237        help: None,
1238    }
1239
1240    @formatted
1241    cannot_assign_to_vars_outside_final_block {
1242        args: (input: impl Display),
1243        msg: format!(
1244            "Cannot assign to `{input}` inside a `final` block because it was declared outside the block."
1245        ),
1246        help: None,
1247    }
1248
1249    @formatted
1250    custom {
1251        args: (msg: impl Display),
1252        msg: msg.to_string(),
1253        help: None,
1254    }
1255
1256    @formatted
1257    constructor_can_only_return_unit {
1258        args: (expression: impl Display),
1259        msg: format!("Constructors can only return unit, but found `{expression}`."),
1260        help: None,
1261    }
1262
1263    @formatted
1264    none_found_non_optional {
1265        args: (expected: impl Display),
1266        msg: format!(
1267            "Found `none`, but the expected type `{expected}` is not an optional type.",
1268        ),
1269        help: None,
1270    }
1271
1272    // TODO This error is unused. Remove it in a future version.
1273    @formatted
1274    optional_wrapping_of_records_unsupported {
1275        args: (ty: impl Display),
1276        msg: format!(
1277            "The type `{ty}` cannot be wrapped in an optional because it is a record.",
1278        ),
1279        help: None,
1280    }
1281
1282    @formatted
1283    optional_wrapping_unsupported {
1284        args: (ty: impl Display),
1285        msg: format!(
1286            "The type `{ty}` cannot be wrapped in an optional.",
1287        ),
1288        help: Some("Optionals cannot wrap signatures, finals, mappings, tuples, vectors, records, arrays whose \
1289                    elements are optional-unsafe, or structures containing any such types.".to_string()),
1290    }
1291
1292    @formatted
1293    optional_type_not_allowed_in_mapping {
1294        args: (ty: impl Display, kind: impl Display),
1295        msg: format!(
1296            "The type `{ty}` is or contains an optional type which cannot be used as the {kind} in a mapping",
1297        ),
1298        help: None,
1299    }
1300
1301    @formatted
1302    record_field_cannot_be_optional {
1303        args: (name: impl Display, ty: impl Display),
1304        msg: format!(
1305            "The field `{name}` in this record has type `{ty}`, which is or contains an optional type.",
1306        ),
1307        help: Some(
1308            "Records cannot have fields that are optional or contain optionals. Consider moving the optionality outside the record.".to_string()
1309        ),
1310    }
1311
1312    @formatted
1313    const_cannot_be_optional {
1314        args: (),
1315        msg: format!(
1316            "Constants cannot have an optional type or a type that contains an optional",
1317        ),
1318        help: None,
1319    }
1320
1321    @formatted
1322    function_cannot_take_option_as_input {
1323        args: (name: impl Display, ty: impl Display),
1324        msg: format!(
1325            "The input `{name}` has type `{ty}`, which is or contains an optional type and is not allowed as an input to an entry point fn.",
1326        ),
1327        help: Some(
1328            "Inputs to entry point fn definitions cannot be optional or contain optionals. Consider moving the optionality outside the call site.".to_string()
1329        ),
1330    }
1331
1332    @formatted
1333    function_cannot_return_option_as_output {
1334        args: (ty: impl Display),
1335        msg: format!(
1336            "This function has an output of type `{ty}`, which is or contains an optional type and is not allowed as an output of an entry point fn.",
1337        ),
1338        help: Some(
1339            "Outputs of entry point fns cannot be optional or contain optionals. Consider moving the optionality outside the function call.".to_string()
1340        ),
1341    }
1342
1343    @formatted
1344    invalid_storage_type {
1345        args: (type_: impl Display),
1346        msg: format!("{type_} is an invalid storage type"),
1347        help: None,
1348    }
1349
1350    @formatted
1351    storage_vectors_cannot_be_moved_or_assigned {
1352        args: (),
1353        msg: format!(
1354            "Storage vectors cannot be moved or assigned. You can only access or modify them using methods like `get`, `push`, or `pop`."
1355        ),
1356        help: None,
1357    }
1358
1359    @formatted
1360    function_has_too_many_inputs {
1361        args: (variant: impl Display, name: impl Display, limit: usize, actual: usize),
1362        msg: format!(
1363            "The {variant} `{name}` has {actual} input parameters, which exceeds the allowed limit of {limit}.",
1364        ),
1365        help: Some(
1366            "Consider reducing the number of input parameters. You might combine some parameters into a struct or refactor the {variant} to simplify its signature.".to_string()
1367        ),
1368    }
1369
1370    @formatted
1371    function_has_too_many_outputs {
1372        args: (variant: impl Display, name: impl Display, limit: usize, actual: usize),
1373        msg: format!(
1374            "The {variant} `{name}` has {actual} output parameters, which exceeds the allowed limit of {limit}.",
1375        ),
1376        help: Some(
1377            "Consider reducing the number of output parameters. You might combine some parameters into a struct or refactor the {variant} to simplify its signature.".to_string()
1378        ),
1379    }
1380
1381    @formatted
1382    empty_function_args {
1383        args: (),
1384        msg: format!("Cannot define a function with only empty parameters."),
1385        help: None,
1386    }
1387
1388    @formatted
1389    zero_size_struct {
1390        args: (),
1391        msg: "A struct must have at least one member of non-zero size.".to_string(),
1392        help: None,
1393    }
1394
1395    /// For when an invalid intrinsic is used.
1396    @formatted
1397    invalid_intrinsic {
1398        args: (intr: impl Display),
1399        msg: format!(
1400            "{intr} is not a valid intrinsic.",
1401        ),
1402        help: None,
1403    }
1404
1405    @formatted
1406    cannot_instantiate_external_record  {
1407        args: (loc: impl Display),
1408        msg: format!(
1409            "Cannot create external record `{loc}`. Records can only be created in the program that they are defined in",
1410        ),
1411        help: None,
1412    }
1413
1414    @formatted
1415    cannot_modify_external_storage_variable {
1416        args: (),
1417        msg: format!("Assignment to storage variables of another program is not allowed. You can only modify storage declared in the current program."),
1418        help: None,
1419    }
1420
1421    @formatted
1422    no_inline_not_allowed_on_final_fn {
1423        args: (),
1424        msg: format!("`@no_inline` is not allowed on `final fn` functions because they must always be inlined."),
1425        help: None,
1426    }
1427
1428    @formatted
1429    record_captured_by_final_block {
1430        args: (var_name: impl Display),
1431        msg: format!("A `final` block cannot capture the record variable `{var_name}`. Records cannot be used in on-chain code."),
1432        help: Some(format!("Extract the needed fields before the `final` block. For example: `let val = {var_name}.field_name;`")),
1433    }
1434
1435    @formatted
1436    dynamic_call_not_allowed_here {
1437        args: (context: impl Display),
1438        msg: format!("Dynamic calls can only be made from an entry point, but found one in {context}."),
1439        help: None,
1440    }
1441
1442    @formatted
1443    dyn_record_field_requires_type {
1444        args: (field: impl Display),
1445        msg: format!("Accessing field `{field}` on a `dyn record` requires a type annotation."),
1446        help: Some(format!("Use `let x: <type> = r.{field};` or `r.{field} as <type>`.")),
1447    }
1448
1449    @formatted
1450    cannot_cast_to_dyn_record {
1451        args: (type_: impl Display),
1452        msg: format!("Cannot cast `{type_}` to `dyn record`: only concrete record types can be cast to `dyn record`."),
1453        help: None,
1454    }
1455
1456    @formatted
1457    dynamic_call_min_args {
1458        args: (found: impl Display),
1459        msg: format!("`_dynamic_call` requires at least 3 arguments (program, network, function), but found {found}."),
1460        help: None,
1461    }
1462
1463    @formatted
1464    dynamic_intrinsic_wrong_arg_count {
1465        args: (name: impl Display, expected: impl Display, found: impl Display),
1466        msg: format!("`{name}` requires {expected} arguments, but found {found}."),
1467        help: None,
1468    }
1469
1470    @formatted
1471    dynamic_intrinsic_missing_type_param {
1472        args: (name: impl Display),
1473        msg: format!("`{name}` requires exactly one type parameter, e.g. `{name}::[u64](...)`"),
1474        help: None,
1475    }
1476
1477    @formatted
1478    dynamic_call_input_type_count_mismatch {
1479        args: (annotated: impl Display, actual: impl Display),
1480        msg: format!("`_dynamic_call` has {annotated} input type annotation(s) but {actual} call argument(s) were provided (excluding the 3 target arguments)."),
1481        help: Some("The number of type annotations before the return type must match the number of call arguments after program/network/function.".to_string()),
1482    }
1483
1484    @formatted
1485    dynamic_call_in_conditional {
1486        args: (),
1487        msg: "Dynamic calls cannot be used inside a conditional branch.".to_string(),
1488        help: Some("Move the dynamic call outside the `if`/`else` block.".to_string()),
1489    }
1490
1491    @formatted
1492    dynamic_call_constant_not_allowed {
1493        args: (),
1494        msg: "`constant` visibility is not allowed in `_dynamic_call` type annotations.".to_string(),
1495        help: Some("Use `public` or `private` instead.".to_string()),
1496    }
1497
1498    /// For when an interface definition appears inside a library module.
1499    @formatted
1500    interfaces_not_allowed_in_library_modules {
1501        args: (),
1502        msg: "Interface definitions are not allowed inside library modules.".to_string(),
1503        help: None,
1504    }
1505
1506    @formatted
1507    dynamic_call_record_arg_requires_dyn_record {
1508        args: (record_type: impl Display),
1509        msg: format!("Dynamic call argument has record type `{record_type}`, but dynamic calls require `dyn record`."),
1510        help: Some("Cast your record value with `my_arg as dyn record`.".to_string()),
1511    }
1512
1513    @formatted
1514    dynamic_call_record_return_is_dyn_record {
1515        args: (record_type: impl Display),
1516        msg: format!("Dynamic call returns record type `{record_type}`, but dynamic calls return `dyn record`."),
1517        help: Some("Dynamic calls cannot return concrete record types. Access fields on the returned `dyn record` with type annotations: `let x: u64 = result.field;`".to_string()),
1518    }
1519);