mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-11-22 05:00:59 +03:00
Merge pull request #28443 from ProvableHQ/feat/analyzers
[Fix] Introduce `StaticAnalysis` pass and add checks on usage of async code for safety.
This commit is contained in:
commit
bcdb1f57d2
@ -20,6 +20,28 @@
|
||||
|
||||
use crate::*;
|
||||
|
||||
// TODO: The Visitor and Reconstructor patterns need a redesign so that the default implementation can easily be invoked though its implemented in an overriding trait.
|
||||
// Here is a pattern that seems to work
|
||||
// trait ProgramVisitor {
|
||||
// // The trait method that can be overridden
|
||||
// fn visit_program_scope(&mut self);
|
||||
//
|
||||
// // Private helper function containing the default implementation
|
||||
// fn default_visit_program_scope(&mut self) {
|
||||
// println!("Do default stuff");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// struct YourStruct;
|
||||
//
|
||||
// impl ProgramVisitor for YourStruct {
|
||||
// fn visit_program_scope(&mut self) {
|
||||
// println!("Do custom stuff.");
|
||||
// // Call the default implementation
|
||||
// self.default_visit_program_scope();
|
||||
// }
|
||||
// }
|
||||
|
||||
/// A Visitor trait for expressions in the AST.
|
||||
pub trait ExpressionVisitor<'a> {
|
||||
type AdditionalInput: Default;
|
||||
|
@ -155,18 +155,24 @@ impl<'a, N: Network> Compiler<'a, N> {
|
||||
|
||||
/// Runs the type checker pass.
|
||||
pub fn type_checker_pass(&'a self, symbol_table: SymbolTable) -> Result<(SymbolTable, StructGraph, CallGraph)> {
|
||||
let (symbol_table, struct_graph, call_graph) = TypeChecker::<N>::do_pass((
|
||||
let (symbol_table, struct_graph, call_graph) =
|
||||
TypeChecker::<N>::do_pass((&self.ast, self.handler, symbol_table, &self.type_table))?;
|
||||
if self.compiler_options.output.type_checked_symbol_table {
|
||||
self.write_symbol_table_to_json("type_checked_symbol_table.json", &symbol_table)?;
|
||||
}
|
||||
Ok((symbol_table, struct_graph, call_graph))
|
||||
}
|
||||
|
||||
/// Runs the static analysis pass.
|
||||
pub fn static_analysis_pass(&mut self, symbol_table: &SymbolTable) -> Result<()> {
|
||||
StaticAnalyzer::<N>::do_pass((
|
||||
&self.ast,
|
||||
self.handler,
|
||||
symbol_table,
|
||||
&self.type_table,
|
||||
self.compiler_options.build.conditional_block_max_depth,
|
||||
self.compiler_options.build.disable_conditional_branch_type_checking,
|
||||
))?;
|
||||
if self.compiler_options.output.type_checked_symbol_table {
|
||||
self.write_symbol_table_to_json("type_checked_symbol_table.json", &symbol_table)?;
|
||||
}
|
||||
Ok((symbol_table, struct_graph, call_graph))
|
||||
))
|
||||
}
|
||||
|
||||
/// Runs the loop unrolling pass.
|
||||
@ -285,8 +291,11 @@ impl<'a, N: Network> Compiler<'a, N> {
|
||||
/// Runs the compiler stages.
|
||||
pub fn compiler_stages(&mut self) -> Result<(SymbolTable, StructGraph, CallGraph)> {
|
||||
let st = self.symbol_table_pass()?;
|
||||
|
||||
let (st, struct_graph, call_graph) = self.type_checker_pass(st)?;
|
||||
|
||||
self.static_analysis_pass(&st)?;
|
||||
|
||||
// TODO: Make this pass optional.
|
||||
let st = self.loop_unrolling_pass(st)?;
|
||||
|
||||
|
@ -265,6 +265,8 @@ pub fn compile_and_process<'a>(parsed: &'a mut Compiler<'a, CurrentNetwork>) ->
|
||||
|
||||
let (st, struct_graph, call_graph) = parsed.type_checker_pass(st)?;
|
||||
|
||||
parsed.static_analysis_pass(&st)?;
|
||||
|
||||
CheckUniqueNodeIds::new().visit_program(&parsed.ast.ast);
|
||||
|
||||
let st = parsed.loop_unrolling_pass(st)?;
|
||||
|
@ -50,9 +50,20 @@ impl<N: Node> TreeNode<N> {
|
||||
}
|
||||
|
||||
/// Removes an element from the current node.
|
||||
pub fn remove_element(&mut self, element: &N) {
|
||||
/// If the element does not exist, increment an internal counter which later used to generate an error that the user attempted to await a future twice.
|
||||
/// Returns `true` if the element was removed but not the first one in the node.
|
||||
pub fn remove_element(&mut self, element: &N) -> bool {
|
||||
// Check if the element is the first one in the node.
|
||||
let is_not_first = match self.elements.first() {
|
||||
Some(first) => first != element,
|
||||
None => false,
|
||||
};
|
||||
// Remove the element from the node.
|
||||
if !self.elements.shift_remove(element) {
|
||||
self.counter += 1;
|
||||
false
|
||||
} else {
|
||||
is_not_first
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,9 @@
|
||||
#![forbid(unsafe_code)]
|
||||
#![doc = include_str!("../README.md")]
|
||||
|
||||
pub mod static_analysis;
|
||||
pub use static_analysis::*;
|
||||
|
||||
pub mod code_generation;
|
||||
pub use code_generation::*;
|
||||
|
||||
|
@ -99,6 +99,7 @@ impl<'a> Unroller<'a> {
|
||||
.swap(previous_constant_propagation_table.borrow().lookup_scope_by_index(index).unwrap());
|
||||
self.constant_propagation_table.borrow_mut().parent =
|
||||
Some(Box::new(previous_constant_propagation_table.into_inner()));
|
||||
|
||||
core::mem::replace(&mut self.scope_index, 0)
|
||||
}
|
||||
|
||||
|
67
compiler/passes/src/static_analysis/analyze_expression.rs
Normal file
67
compiler/passes/src/static_analysis/analyze_expression.rs
Normal file
@ -0,0 +1,67 @@
|
||||
// Copyright (C) 2019-2024 Aleo Systems Inc.
|
||||
// This file is part of the Leo library.
|
||||
|
||||
// The Leo library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// The Leo library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::StaticAnalyzer;
|
||||
|
||||
use leo_ast::*;
|
||||
|
||||
use snarkvm::console::network::Network;
|
||||
|
||||
impl<'a, N: Network> ExpressionVisitor<'a> for StaticAnalyzer<'a, N> {
|
||||
type AdditionalInput = ();
|
||||
type Output = ();
|
||||
|
||||
fn visit_access(&mut self, input: &'a AccessExpression, _: &Self::AdditionalInput) -> Self::Output {
|
||||
if let AccessExpression::AssociatedFunction(access) = input {
|
||||
// Get the core function.
|
||||
let core_function = match CoreFunction::from_symbols(access.variant.name, access.name.name) {
|
||||
Some(core_function) => core_function,
|
||||
None => unreachable!("Typechecking guarantees that this function exists."),
|
||||
};
|
||||
|
||||
// Check that the future was awaited correctly.
|
||||
if core_function == CoreFunction::FutureAwait {
|
||||
self.assert_future_await(&access.arguments.first(), input.span());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_call(&mut self, input: &'a CallExpression, _: &Self::AdditionalInput) -> Self::Output {
|
||||
match &*input.function {
|
||||
// Note that the parser guarantees that `input.function` is always an identifier.
|
||||
Expression::Identifier(ident) => {
|
||||
// If the function call is an external async transition, then for all async calls that follow a non-async call,
|
||||
// we must check that the async call is not an async function that takes a future as an argument.
|
||||
if self.non_async_external_call_seen
|
||||
&& self.variant == Some(Variant::AsyncTransition)
|
||||
&& input.program.is_some()
|
||||
{
|
||||
// Note that this unwrap is safe since we check that `input.program` is `Some` above.
|
||||
self.assert_simple_async_transition_call(input.program.unwrap(), ident.name, input.span());
|
||||
}
|
||||
// Otherwise look up the function and check if it is a non-async call.
|
||||
if let Some(function_symbol) =
|
||||
self.symbol_table.lookup_fn_symbol(Location::new(input.program, ident.name))
|
||||
{
|
||||
if function_symbol.variant == Variant::Transition {
|
||||
self.non_async_external_call_seen = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => unreachable!("Parsing guarantees that a function name is always an identifier."),
|
||||
}
|
||||
}
|
||||
}
|
111
compiler/passes/src/static_analysis/analyze_program.rs
Normal file
111
compiler/passes/src/static_analysis/analyze_program.rs
Normal file
@ -0,0 +1,111 @@
|
||||
// Copyright (C) 2019-2024 Aleo Systems Inc.
|
||||
// This file is part of the Leo library.
|
||||
|
||||
// The Leo library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// The Leo library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::StaticAnalyzer;
|
||||
|
||||
use leo_ast::{Type, *};
|
||||
use leo_errors::{StaticAnalyzerError, StaticAnalyzerWarning};
|
||||
|
||||
use snarkvm::console::network::Network;
|
||||
|
||||
impl<'a, N: Network> ProgramVisitor<'a> for StaticAnalyzer<'a, N> {
|
||||
fn visit_program_scope(&mut self, input: &'a ProgramScope) {
|
||||
// Set the current program name.
|
||||
self.current_program = Some(input.program_id.name.name);
|
||||
// Do the default implementation for visiting the program scope.
|
||||
input.structs.iter().for_each(|(_, c)| (self.visit_struct(c)));
|
||||
input.mappings.iter().for_each(|(_, c)| (self.visit_mapping(c)));
|
||||
input.functions.iter().for_each(|(_, c)| (self.visit_function(c)));
|
||||
input.consts.iter().for_each(|(_, c)| (self.visit_const(c)));
|
||||
}
|
||||
|
||||
fn visit_function(&mut self, function: &'a Function) {
|
||||
// Set the function name and variant.
|
||||
self.variant = Some(function.variant);
|
||||
|
||||
// Set `non_async_external_call_seen` to false.
|
||||
self.non_async_external_call_seen = false;
|
||||
|
||||
// If the function is an async function, initialize the await checker.
|
||||
if self.variant == Some(Variant::AsyncFunction) {
|
||||
// Initialize the list of input futures. Each one must be awaited before the end of the function.
|
||||
self.await_checker.set_futures(
|
||||
function
|
||||
.input
|
||||
.iter()
|
||||
.filter_map(|input| {
|
||||
if let Type::Future(_) = input.type_.clone() { Some(input.identifier.name) } else { None }
|
||||
})
|
||||
.collect(),
|
||||
);
|
||||
}
|
||||
|
||||
self.visit_block(&function.block);
|
||||
|
||||
// Check that all futures were awaited exactly once.
|
||||
if self.variant == Some(Variant::AsyncFunction) {
|
||||
// Throw error if not all futures awaits even appear once.
|
||||
if !self.await_checker.static_to_await.is_empty() {
|
||||
self.emit_err(StaticAnalyzerError::future_awaits_missing(
|
||||
self.await_checker
|
||||
.static_to_await
|
||||
.clone()
|
||||
.iter()
|
||||
.map(|f| f.to_string())
|
||||
.collect::<Vec<String>>()
|
||||
.join(", "),
|
||||
function.span(),
|
||||
));
|
||||
} else if self.await_checker.enabled && !self.await_checker.to_await.is_empty() {
|
||||
// Tally up number of paths that are unawaited and number of paths that are awaited more than once.
|
||||
let (num_paths_unawaited, num_paths_duplicate_awaited, num_perfect) =
|
||||
self.await_checker.to_await.iter().fold((0, 0, 0), |(unawaited, duplicate, perfect), path| {
|
||||
(
|
||||
unawaited + if !path.elements.is_empty() { 1 } else { 0 },
|
||||
duplicate + if path.counter > 0 { 1 } else { 0 },
|
||||
perfect + if path.counter > 0 || !path.elements.is_empty() { 0 } else { 1 },
|
||||
)
|
||||
});
|
||||
|
||||
// Throw error if there does not exist a path in which all futures are awaited exactly once.
|
||||
if num_perfect == 0 {
|
||||
self.emit_err(StaticAnalyzerError::no_path_awaits_all_futures_exactly_once(
|
||||
self.await_checker.to_await.len(),
|
||||
function.span(),
|
||||
));
|
||||
}
|
||||
|
||||
// Throw warning if not all futures are awaited in some paths.
|
||||
if num_paths_unawaited > 0 {
|
||||
self.emit_warning(StaticAnalyzerWarning::some_paths_do_not_await_all_futures(
|
||||
self.await_checker.to_await.len(),
|
||||
num_paths_unawaited,
|
||||
function.span(),
|
||||
));
|
||||
}
|
||||
|
||||
// Throw warning if some futures are awaited more than once in some paths.
|
||||
if num_paths_duplicate_awaited > 0 {
|
||||
self.emit_warning(StaticAnalyzerWarning::some_paths_contain_duplicate_future_awaits(
|
||||
self.await_checker.to_await.len(),
|
||||
num_paths_duplicate_awaited,
|
||||
function.span(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
54
compiler/passes/src/static_analysis/analyze_statement.rs
Normal file
54
compiler/passes/src/static_analysis/analyze_statement.rs
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright (C) 2019-2024 Aleo Systems Inc.
|
||||
// This file is part of the Leo library.
|
||||
|
||||
// The Leo library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// The Leo library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use super::*;
|
||||
use crate::ConditionalTreeNode;
|
||||
|
||||
use leo_ast::*;
|
||||
|
||||
impl<'a, N: Network> StatementVisitor<'a> for StaticAnalyzer<'a, N> {
|
||||
fn visit_conditional(&mut self, input: &'a ConditionalStatement) {
|
||||
self.visit_expression(&input.condition, &Default::default());
|
||||
|
||||
// Create scope for checking awaits in `then` branch of conditional.
|
||||
let current_bst_nodes: Vec<ConditionalTreeNode> =
|
||||
match self.await_checker.create_then_scope(self.variant == Some(Variant::AsyncFunction), input.span) {
|
||||
Ok(nodes) => nodes,
|
||||
Err(warn) => return self.emit_warning(warn),
|
||||
};
|
||||
|
||||
// Visit block.
|
||||
self.visit_block(&input.then);
|
||||
|
||||
// Exit scope for checking awaits in `then` branch of conditional.
|
||||
let saved_paths =
|
||||
self.await_checker.exit_then_scope(self.variant == Some(Variant::AsyncFunction), current_bst_nodes);
|
||||
|
||||
if let Some(otherwise) = &input.otherwise {
|
||||
match &**otherwise {
|
||||
Statement::Block(stmt) => {
|
||||
// Visit the otherwise-block.
|
||||
self.visit_block(stmt);
|
||||
}
|
||||
Statement::Conditional(stmt) => self.visit_conditional(stmt),
|
||||
_ => unreachable!("Else-case can only be a block or conditional statement."),
|
||||
}
|
||||
}
|
||||
|
||||
// Update the set of all possible BST paths.
|
||||
self.await_checker.exit_statement_scope(self.variant == Some(Variant::AsyncFunction), saved_paths);
|
||||
}
|
||||
}
|
143
compiler/passes/src/static_analysis/analyzer.rs
Normal file
143
compiler/passes/src/static_analysis/analyzer.rs
Normal file
@ -0,0 +1,143 @@
|
||||
// Copyright (C) 2019-2024 Aleo Systems Inc.
|
||||
// This file is part of the Leo library.
|
||||
|
||||
// The Leo library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// The Leo library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{SymbolTable, TypeTable, static_analysis::await_checker::AwaitChecker};
|
||||
|
||||
use leo_ast::*;
|
||||
use leo_errors::{StaticAnalyzerError, StaticAnalyzerWarning, emitter::Handler};
|
||||
use leo_span::{Span, Symbol};
|
||||
|
||||
use snarkvm::console::network::Network;
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
pub struct StaticAnalyzer<'a, N: Network> {
|
||||
/// The symbol table for the program.
|
||||
pub(crate) symbol_table: &'a SymbolTable,
|
||||
/// The type table for the program.
|
||||
// Note that this pass does not use the type table in a meaningful way.
|
||||
// However, this may be useful in future static analysis passes.
|
||||
pub(crate) type_table: &'a TypeTable,
|
||||
/// The error handler.
|
||||
pub(crate) handler: &'a Handler,
|
||||
/// Struct to store the state relevant to checking all futures are awaited.
|
||||
pub(crate) await_checker: AwaitChecker,
|
||||
/// The current program name.
|
||||
pub(crate) current_program: Option<Symbol>,
|
||||
/// The variant of the function that we are currently traversing.
|
||||
pub(crate) variant: Option<Variant>,
|
||||
/// Whether or not a non-async external call has been seen in this function.
|
||||
pub(crate) non_async_external_call_seen: bool,
|
||||
// Allows the type checker to be generic over the network.
|
||||
phantom: PhantomData<N>,
|
||||
}
|
||||
|
||||
impl<'a, N: Network> StaticAnalyzer<'a, N> {
|
||||
/// Returns a new static analyzer given a symbol table and error handler.
|
||||
pub fn new(
|
||||
symbol_table: &'a SymbolTable,
|
||||
_type_table: &'a TypeTable,
|
||||
handler: &'a Handler,
|
||||
max_depth: usize,
|
||||
disabled: bool,
|
||||
) -> Self {
|
||||
Self {
|
||||
symbol_table,
|
||||
type_table: _type_table,
|
||||
handler,
|
||||
await_checker: AwaitChecker::new(max_depth, !disabled),
|
||||
current_program: None,
|
||||
variant: None,
|
||||
non_async_external_call_seen: false,
|
||||
phantom: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Emits a type checker error.
|
||||
pub(crate) fn emit_err(&self, err: StaticAnalyzerError) {
|
||||
self.handler.emit_err(err);
|
||||
}
|
||||
|
||||
/// Emits a type checker warning
|
||||
pub fn emit_warning(&self, warning: StaticAnalyzerWarning) {
|
||||
self.handler.emit_warning(warning.into());
|
||||
}
|
||||
|
||||
/// Type checks the awaiting of a future.
|
||||
pub(crate) fn assert_future_await(&mut self, future: &Option<&Expression>, span: Span) {
|
||||
// Make sure that it is an identifier expression.
|
||||
let future_variable = match future {
|
||||
Some(Expression::Identifier(name)) => name,
|
||||
_ => {
|
||||
return self.emit_err(StaticAnalyzerError::invalid_await_call(span));
|
||||
}
|
||||
};
|
||||
|
||||
// Make sure that the future is defined.
|
||||
match self.type_table.get(&future_variable.id) {
|
||||
Some(type_) => {
|
||||
if !matches!(type_, Type::Future(_)) {
|
||||
self.emit_err(StaticAnalyzerError::expected_future(future_variable.name, future_variable.span()));
|
||||
}
|
||||
// Mark the future as consumed.
|
||||
// If the call returns true, it means that a future was not awaited in the order of the input list, emit a warning.
|
||||
if self.await_checker.remove(future_variable) {
|
||||
self.emit_warning(StaticAnalyzerWarning::future_not_awaited_in_order(
|
||||
future_variable.name,
|
||||
future_variable.span(),
|
||||
));
|
||||
}
|
||||
}
|
||||
None => {
|
||||
self.emit_err(StaticAnalyzerError::expected_future(future_variable.name, future_variable.span()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Assert that an async call is a "simple" one.
|
||||
/// Simple is defined as an async transition function which does not return a `Future` that itself takes a `Future` as an argument.
|
||||
pub(crate) fn assert_simple_async_transition_call(&self, program: Symbol, function_name: Symbol, span: Span) {
|
||||
// Look up the function.
|
||||
let function = match self.symbol_table.lookup_fn_symbol(Location::new(Some(program), function_name)) {
|
||||
Some(function) => function,
|
||||
None => {
|
||||
unreachable!("Type checking guarantees that this function exists.");
|
||||
}
|
||||
};
|
||||
// If it is not an async transition, return.
|
||||
if function.variant != Variant::AsyncTransition {
|
||||
return;
|
||||
}
|
||||
// Otherwise, get the location of the finalize block.
|
||||
let location = match &function.finalize {
|
||||
Some(location) => location.clone(),
|
||||
None => {
|
||||
unreachable!("Typechecking guarantees that all async transitions have an associated `finalize` field.");
|
||||
}
|
||||
};
|
||||
// Look up the async function.
|
||||
let async_function = match self.symbol_table.lookup_fn_symbol(location) {
|
||||
Some(function) => function,
|
||||
None => {
|
||||
unreachable!("Type checking guarantees that this function exists.");
|
||||
}
|
||||
};
|
||||
// If the async function takes a future as an argument, emit an error.
|
||||
if !async_function.future_inputs.is_empty() {
|
||||
self.emit_err(StaticAnalyzerError::async_transition_call_with_future_argument(function_name, span));
|
||||
}
|
||||
}
|
||||
}
|
@ -17,7 +17,7 @@
|
||||
use crate::ConditionalTreeNode;
|
||||
use indexmap::IndexSet;
|
||||
use leo_ast::Identifier;
|
||||
use leo_errors::TypeCheckerWarning;
|
||||
use leo_errors::StaticAnalyzerWarning;
|
||||
use leo_span::{Span, Symbol};
|
||||
|
||||
// TODO: Could optimize by removing duplicate paths (if set of futures is the same).
|
||||
@ -39,15 +39,20 @@ impl AwaitChecker {
|
||||
}
|
||||
|
||||
/// Remove from list.
|
||||
pub fn remove(&mut self, id: &Identifier) {
|
||||
/// Returns `true` if there was a path where the future was not awaited in the order of the input list.
|
||||
pub fn remove(&mut self, id: &Identifier) -> bool {
|
||||
// Can assume in finalize block.
|
||||
if self.enabled {
|
||||
let is_not_first = if self.enabled {
|
||||
// Remove from dynamic list.
|
||||
self.to_await.iter_mut().for_each(|node| node.remove_element(&id.name));
|
||||
}
|
||||
self.to_await.iter_mut().any(|node| node.remove_element(&id.name))
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
// Remove from static list.
|
||||
self.static_to_await.shift_remove(&id.name);
|
||||
|
||||
is_not_first
|
||||
}
|
||||
|
||||
/// Initialize futures.
|
||||
@ -65,14 +70,14 @@ impl AwaitChecker {
|
||||
&mut self,
|
||||
is_finalize: bool,
|
||||
input: Span,
|
||||
) -> Result<Vec<ConditionalTreeNode>, TypeCheckerWarning> {
|
||||
) -> Result<Vec<ConditionalTreeNode>, StaticAnalyzerWarning> {
|
||||
if is_finalize && self.enabled {
|
||||
let mut current_nodes = Vec::new();
|
||||
// Extend all paths by one node to represent the upcoming `then` branch.
|
||||
for node in self.to_await.iter() {
|
||||
// Error if exceed maximum depth.
|
||||
if node.depth > self.max_depth {
|
||||
return Err(TypeCheckerWarning::max_conditional_block_depth_exceeded(self.max_depth, input));
|
||||
return Err(StaticAnalyzerWarning::max_conditional_block_depth_exceeded(self.max_depth, input));
|
||||
}
|
||||
// Extend current path.
|
||||
current_nodes.push(node.clone().create_child());
|
44
compiler/passes/src/static_analysis/mod.rs
Normal file
44
compiler/passes/src/static_analysis/mod.rs
Normal file
@ -0,0 +1,44 @@
|
||||
// Copyright (C) 2019-2024 Aleo Systems Inc.
|
||||
// This file is part of the Leo library.
|
||||
|
||||
// The Leo library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// The Leo library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
mod await_checker;
|
||||
|
||||
pub mod analyze_expression;
|
||||
|
||||
pub mod analyze_program;
|
||||
|
||||
pub mod analyze_statement;
|
||||
|
||||
pub mod analyzer;
|
||||
pub use analyzer::*;
|
||||
|
||||
use crate::{Pass, SymbolTable, TypeTable};
|
||||
|
||||
use leo_ast::{Ast, ProgramVisitor};
|
||||
use leo_errors::{Result, emitter::Handler};
|
||||
|
||||
use snarkvm::prelude::Network;
|
||||
|
||||
impl<'a, N: Network> Pass for StaticAnalyzer<'a, N> {
|
||||
type Input = (&'a Ast, &'a Handler, &'a SymbolTable, &'a TypeTable, usize, bool);
|
||||
type Output = Result<()>;
|
||||
|
||||
fn do_pass((ast, handler, st, tt, max_depth, await_checking): Self::Input) -> Self::Output {
|
||||
let mut visitor = StaticAnalyzer::<N>::new(st, tt, handler, max_depth, await_checking);
|
||||
visitor.visit_program(ast.as_repr());
|
||||
handler.last_err().map_err(|e| *e)
|
||||
}
|
||||
}
|
@ -114,11 +114,36 @@ impl<'a> ProgramVisitor<'a> for SymbolTableCreator<'a> {
|
||||
}
|
||||
|
||||
fn visit_function_stub(&mut self, input: &'a FunctionStub) {
|
||||
if let Err(err) =
|
||||
self.symbol_table.insert_fn(Location::new(self.program_name, input.name()), &Function::from(input.clone()))
|
||||
{
|
||||
// Construct the location for the function.
|
||||
let location = Location::new(self.program_name, input.name());
|
||||
// Initalize the function symbol.
|
||||
if let Err(err) = self.symbol_table.insert_fn(location.clone(), &Function::from(input.clone())) {
|
||||
self.handler.emit_err(err);
|
||||
}
|
||||
// If the `FunctionStub` is an async transition, attach the finalize logic to the function.
|
||||
if matches!(input.variant, Variant::AsyncTransition) {
|
||||
// This matches the logic in the disassembler.
|
||||
let name = Symbol::intern(&format!("finalize/{}", input.name()));
|
||||
if let Err(err) = self.symbol_table.attach_finalize(location, Location::new(self.program_name, name)) {
|
||||
self.handler.emit_err(err);
|
||||
}
|
||||
}
|
||||
// Otherwise is the `FunctionStub` is an async function, attach the future inputs.
|
||||
else if matches!(input.variant, Variant::AsyncFunction) {
|
||||
let future_inputs = input
|
||||
.input
|
||||
.iter()
|
||||
.filter_map(|input| match &input.type_ {
|
||||
Type::Future(future_type) => future_type.location.clone(),
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
// Note that this unwrap is safe, because `self.program_name` is set before traversing the AST.
|
||||
if let Err(err) = self.symbol_table.insert_futures(self.program_name.unwrap(), input.name(), future_inputs)
|
||||
{
|
||||
self.handler.emit_err(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_struct_stub(&mut self, input: &'a Composite) {
|
||||
|
@ -119,14 +119,10 @@ impl<'a, N: Network> ExpressionVisitor<'a> for TypeChecker<'a, N> {
|
||||
}
|
||||
|
||||
// Await futures here so that can use the argument variable names to lookup.
|
||||
if core_instruction == CoreFunction::FutureAwait {
|
||||
if access.arguments.len() != 1 {
|
||||
self.emit_err(TypeCheckerError::can_only_await_one_future_at_a_time(access.span));
|
||||
return Some(Type::Unit);
|
||||
}
|
||||
self.assert_future_await(&access.arguments.first(), input.span());
|
||||
if core_instruction == CoreFunction::FutureAwait && access.arguments.len() != 1 {
|
||||
self.emit_err(TypeCheckerError::can_only_await_one_future_at_a_time(access.span));
|
||||
return Some(Type::Unit);
|
||||
}
|
||||
|
||||
return return_type;
|
||||
} else {
|
||||
self.emit_err(TypeCheckerError::invalid_core_function_call(access, access.span()));
|
||||
|
@ -17,7 +17,7 @@
|
||||
use crate::{DiGraphError, TypeChecker};
|
||||
|
||||
use leo_ast::{Type, *};
|
||||
use leo_errors::{TypeCheckerError, TypeCheckerWarning};
|
||||
use leo_errors::TypeCheckerError;
|
||||
use leo_span::sym;
|
||||
|
||||
use snarkvm::console::network::Network;
|
||||
@ -262,19 +262,6 @@ impl<'a, N: Network> ProgramVisitor<'a> for TypeChecker<'a, N> {
|
||||
// Query helper function to type check function parameters and outputs.
|
||||
self.check_function_signature(function);
|
||||
|
||||
if self.scope_state.variant == Some(Variant::AsyncFunction) {
|
||||
// Initialize the list of input futures. Each one must be awaited before the end of the function.
|
||||
self.await_checker.set_futures(
|
||||
function
|
||||
.input
|
||||
.iter()
|
||||
.filter_map(|input| {
|
||||
if let Type::Future(_) = input.type_.clone() { Some(input.identifier.name) } else { None }
|
||||
})
|
||||
.collect(),
|
||||
);
|
||||
}
|
||||
|
||||
if function.variant == Variant::Function && function.input.is_empty() {
|
||||
self.emit_err(TypeCheckerError::empty_function_arglist(function.span));
|
||||
}
|
||||
@ -296,59 +283,6 @@ impl<'a, N: Network> ProgramVisitor<'a> for TypeChecker<'a, N> {
|
||||
if self.scope_state.variant == Some(Variant::AsyncTransition) && !self.scope_state.has_called_finalize {
|
||||
self.emit_err(TypeCheckerError::async_transition_must_call_async_function(function.span));
|
||||
}
|
||||
|
||||
// Check that all futures were awaited exactly once.
|
||||
if self.scope_state.variant == Some(Variant::AsyncFunction) {
|
||||
// Throw error if not all futures awaits even appear once.
|
||||
if !self.await_checker.static_to_await.is_empty() {
|
||||
self.emit_err(TypeCheckerError::future_awaits_missing(
|
||||
self.await_checker
|
||||
.static_to_await
|
||||
.clone()
|
||||
.iter()
|
||||
.map(|f| f.to_string())
|
||||
.collect::<Vec<String>>()
|
||||
.join(", "),
|
||||
function.span(),
|
||||
));
|
||||
} else if self.await_checker.enabled && !self.await_checker.to_await.is_empty() {
|
||||
// Tally up number of paths that are unawaited and number of paths that are awaited more than once.
|
||||
let (num_paths_unawaited, num_paths_duplicate_awaited, num_perfect) =
|
||||
self.await_checker.to_await.iter().fold((0, 0, 0), |(unawaited, duplicate, perfect), path| {
|
||||
(
|
||||
unawaited + if !path.elements.is_empty() { 1 } else { 0 },
|
||||
duplicate + if path.counter > 0 { 1 } else { 0 },
|
||||
perfect + if path.counter > 0 || !path.elements.is_empty() { 0 } else { 1 },
|
||||
)
|
||||
});
|
||||
|
||||
// Throw error if there does not exist a path in which all futures are awaited exactly once.
|
||||
if num_perfect == 0 {
|
||||
self.emit_err(TypeCheckerError::no_path_awaits_all_futures_exactly_once(
|
||||
self.await_checker.to_await.len(),
|
||||
function.span(),
|
||||
));
|
||||
}
|
||||
|
||||
// Throw warning if some futures are awaited more than once in some paths.
|
||||
if num_paths_unawaited > 0 {
|
||||
self.emit_warning(TypeCheckerWarning::some_paths_do_not_await_all_futures(
|
||||
self.await_checker.to_await.len(),
|
||||
num_paths_unawaited,
|
||||
function.span(),
|
||||
));
|
||||
}
|
||||
|
||||
// Throw warning if not all futures are awaited in some paths.
|
||||
if num_paths_duplicate_awaited > 0 {
|
||||
self.emit_warning(TypeCheckerWarning::some_paths_contain_duplicate_future_awaits(
|
||||
self.await_checker.to_await.len(),
|
||||
num_paths_duplicate_awaited,
|
||||
function.span(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_function_stub(&mut self, input: &'a FunctionStub) {
|
||||
|
@ -15,7 +15,7 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use super::*;
|
||||
use crate::{ConditionalTreeNode, TypeChecker, VariableSymbol, VariableType};
|
||||
use crate::{TypeChecker, VariableSymbol, VariableType};
|
||||
|
||||
use leo_ast::{
|
||||
Type::{Future, Tuple},
|
||||
@ -133,26 +133,12 @@ impl<'a, N: Network> StatementVisitor<'a> for TypeChecker<'a, N> {
|
||||
// Set the `is_conditional` flag.
|
||||
let previous_is_conditional = core::mem::replace(&mut self.scope_state.is_conditional, true);
|
||||
|
||||
// Create scope for checking awaits in `then` branch of conditional.
|
||||
let current_bst_nodes: Vec<ConditionalTreeNode> = match self
|
||||
.await_checker
|
||||
.create_then_scope(self.scope_state.variant == Some(Variant::AsyncFunction), input.span)
|
||||
{
|
||||
Ok(nodes) => nodes,
|
||||
Err(warn) => return self.emit_warning(warn),
|
||||
};
|
||||
|
||||
// Visit block.
|
||||
self.visit_block(&input.then);
|
||||
|
||||
// Store the `has_return` flag for the then-block.
|
||||
then_block_has_return = self.scope_state.has_return;
|
||||
|
||||
// Exit scope for checking awaits in `then` branch of conditional.
|
||||
let saved_paths = self
|
||||
.await_checker
|
||||
.exit_then_scope(self.scope_state.variant == Some(Variant::AsyncFunction), current_bst_nodes);
|
||||
|
||||
if let Some(otherwise) = &input.otherwise {
|
||||
// Set the `has_return` flag for the otherwise-block.
|
||||
self.scope_state.has_return = otherwise_block_has_return;
|
||||
@ -170,9 +156,6 @@ impl<'a, N: Network> StatementVisitor<'a> for TypeChecker<'a, N> {
|
||||
otherwise_block_has_return = self.scope_state.has_return;
|
||||
}
|
||||
|
||||
// Update the set of all possible BST paths.
|
||||
self.await_checker.exit_statement_scope(self.scope_state.variant == Some(Variant::AsyncFunction), saved_paths);
|
||||
|
||||
// Restore the previous `has_return` flag.
|
||||
self.scope_state.has_return = previous_has_return || (then_block_has_return && otherwise_block_has_return);
|
||||
// Restore the previous `is_conditional` flag.
|
||||
|
@ -21,7 +21,7 @@ use crate::{
|
||||
TypeTable,
|
||||
VariableSymbol,
|
||||
VariableType,
|
||||
type_checking::{await_checker::AwaitChecker, scope_state::ScopeState},
|
||||
type_checking::scope_state::ScopeState,
|
||||
};
|
||||
|
||||
use leo_ast::*;
|
||||
@ -47,8 +47,6 @@ pub struct TypeChecker<'a, N: Network> {
|
||||
pub(crate) handler: &'a Handler,
|
||||
/// The state of the current scope being traversed.
|
||||
pub(crate) scope_state: ScopeState,
|
||||
/// Struct to store the state relevant to checking all futures are awaited.
|
||||
pub(crate) await_checker: AwaitChecker,
|
||||
/// Mapping from async function name to the inferred input types.
|
||||
pub(crate) async_function_input_types: IndexMap<Location, Vec<Type>>,
|
||||
/// The set of used composites.
|
||||
@ -103,13 +101,7 @@ const MAGNITUDE_TYPES: [Type; 3] =
|
||||
|
||||
impl<'a, N: Network> TypeChecker<'a, N> {
|
||||
/// Returns a new type checker given a symbol table and error handler.
|
||||
pub fn new(
|
||||
symbol_table: SymbolTable,
|
||||
type_table: &'a TypeTable,
|
||||
handler: &'a Handler,
|
||||
max_depth: usize,
|
||||
disabled: bool,
|
||||
) -> Self {
|
||||
pub fn new(symbol_table: SymbolTable, type_table: &'a TypeTable, handler: &'a Handler) -> Self {
|
||||
let struct_names = symbol_table.structs.keys().map(|loc| loc.name).collect();
|
||||
let function_names = symbol_table.functions.keys().map(|loc| loc.name).collect();
|
||||
|
||||
@ -121,7 +113,6 @@ impl<'a, N: Network> TypeChecker<'a, N> {
|
||||
call_graph: CallGraph::new(function_names),
|
||||
handler,
|
||||
scope_state: ScopeState::new(),
|
||||
await_checker: AwaitChecker::new(max_depth, !disabled),
|
||||
async_function_input_types: IndexMap::new(),
|
||||
used_structs: IndexSet::new(),
|
||||
phantom: Default::default(),
|
||||
@ -1308,31 +1299,6 @@ impl<'a, N: Network> TypeChecker<'a, N> {
|
||||
struct_
|
||||
}
|
||||
|
||||
/// Type checks the awaiting of a future.
|
||||
pub(crate) fn assert_future_await(&mut self, future: &Option<&Expression>, span: Span) {
|
||||
// Make sure that it is an identifier expression.
|
||||
let future_variable = match future {
|
||||
Some(Expression::Identifier(name)) => name,
|
||||
_ => {
|
||||
return self.emit_err(TypeCheckerError::invalid_await_call(span));
|
||||
}
|
||||
};
|
||||
|
||||
// Make sure that the future is defined.
|
||||
match self.symbol_table.borrow().lookup_variable(Location::new(None, future_variable.name)) {
|
||||
Some(var) => {
|
||||
if !matches!(&var.type_, &Type::Future(_)) {
|
||||
self.emit_err(TypeCheckerError::expected_future(future_variable.name, future_variable.span()));
|
||||
}
|
||||
// Mark the future as consumed.
|
||||
self.await_checker.remove(future_variable);
|
||||
}
|
||||
None => {
|
||||
self.emit_err(TypeCheckerError::expected_future(future_variable.name, future_variable.span()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Inserts variable to symbol table.
|
||||
pub(crate) fn insert_variable(
|
||||
&mut self,
|
||||
|
@ -14,8 +14,6 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
mod await_checker;
|
||||
|
||||
pub mod check_expressions;
|
||||
|
||||
pub mod check_program;
|
||||
@ -36,11 +34,11 @@ use leo_errors::{Result, emitter::Handler};
|
||||
use snarkvm::prelude::Network;
|
||||
|
||||
impl<'a, N: Network> Pass for TypeChecker<'a, N> {
|
||||
type Input = (&'a Ast, &'a Handler, SymbolTable, &'a TypeTable, usize, bool);
|
||||
type Input = (&'a Ast, &'a Handler, SymbolTable, &'a TypeTable);
|
||||
type Output = Result<(SymbolTable, StructGraph, CallGraph)>;
|
||||
|
||||
fn do_pass((ast, handler, st, tt, max_depth, await_checking): Self::Input) -> Self::Output {
|
||||
let mut visitor = TypeChecker::<N>::new(st, tt, handler, max_depth, await_checking);
|
||||
fn do_pass((ast, handler, st, tt): Self::Input) -> Self::Output {
|
||||
let mut visitor = TypeChecker::<N>::new(st, tt, handler);
|
||||
visitor.visit_program(ast.as_repr());
|
||||
handler.last_err().map_err(|e| *e)?;
|
||||
|
||||
|
@ -1,29 +0,0 @@
|
||||
// Copyright (C) 2019-2024 Aleo Systems Inc.
|
||||
// This file is part of the Leo library.
|
||||
|
||||
// The Leo library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// The Leo library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::create_errors;
|
||||
|
||||
use std::{
|
||||
error::Error as ErrorArg,
|
||||
fmt::{Debug, Display},
|
||||
};
|
||||
|
||||
create_errors!(
|
||||
/// ImportError enum that represents all the errors for the `leo-import` crate.
|
||||
ImportError,
|
||||
exit_code_mask: 4000i32,
|
||||
error_code_prefix: "IMP",
|
||||
);
|
@ -45,6 +45,10 @@ pub use self::package::*;
|
||||
pub mod parser;
|
||||
pub use self::parser::*;
|
||||
|
||||
/// Contains the Static Analyzer error definitions.
|
||||
pub mod static_analyzer;
|
||||
pub use self::static_analyzer::*;
|
||||
|
||||
/// Contains the Type Checker error definitions.
|
||||
pub mod type_checker;
|
||||
pub use self::type_checker::*;
|
||||
@ -72,6 +76,9 @@ pub enum LeoError {
|
||||
/// Represents a Parser Error in a Leo Error.
|
||||
#[error(transparent)]
|
||||
ParserError(#[from] ParserError),
|
||||
/// Represents a Static Analyzer Error in a Leo Error.
|
||||
#[error(transparent)]
|
||||
StaticAnalyzerError(#[from] StaticAnalyzerError),
|
||||
/// Represents a Type Checker Error in a Leo Error.
|
||||
#[error(transparent)]
|
||||
TypeCheckerError(#[from] TypeCheckerError),
|
||||
@ -104,6 +111,7 @@ impl LeoError {
|
||||
CliError(error) => error.error_code(),
|
||||
ParserError(error) => error.error_code(),
|
||||
PackageError(error) => error.error_code(),
|
||||
StaticAnalyzerError(error) => error.error_code(),
|
||||
TypeCheckerError(error) => error.error_code(),
|
||||
LoopUnrollerError(error) => error.error_code(),
|
||||
FlattenError(error) => error.error_code(),
|
||||
@ -123,6 +131,7 @@ impl LeoError {
|
||||
CliError(error) => error.exit_code(),
|
||||
ParserError(error) => error.exit_code(),
|
||||
PackageError(error) => error.exit_code(),
|
||||
StaticAnalyzerError(error) => error.exit_code(),
|
||||
TypeCheckerError(error) => error.exit_code(),
|
||||
LoopUnrollerError(error) => error.exit_code(),
|
||||
FlattenError(error) => error.exit_code(),
|
||||
@ -140,6 +149,9 @@ pub enum LeoWarning {
|
||||
/// Represents an Parser Warning in a Leo Warning.
|
||||
#[error(transparent)]
|
||||
ParserWarning(#[from] ParserWarning),
|
||||
/// Represents a Static Analyzer Warning in a Leo Warning.
|
||||
#[error(transparent)]
|
||||
StaticAnalyzerWarning(#[from] StaticAnalyzerWarning),
|
||||
/// Represents a Type Checker Warning in a Leo Warning.
|
||||
#[error(transparent)]
|
||||
TypeCheckerWarning(#[from] TypeCheckerWarning),
|
||||
@ -153,6 +165,7 @@ impl LeoWarning {
|
||||
match self {
|
||||
ParserWarning(warning) => warning.warning_code(),
|
||||
TypeCheckerWarning(warning) => warning.warning_code(),
|
||||
StaticAnalyzerWarning(warning) => warning.warning_code(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,9 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
/// This module contains the Import error definitions.
|
||||
pub mod import_errors;
|
||||
pub use self::import_errors::*;
|
||||
/// This module contains the static analysis error definitions.
|
||||
pub mod static_analyzer_error;
|
||||
pub use self::static_analyzer_error::*;
|
||||
|
||||
pub mod static_analyzer_warning;
|
||||
pub use self::static_analyzer_warning::*;
|
62
errors/src/errors/static_analyzer/static_analyzer_error.rs
Normal file
62
errors/src/errors/static_analyzer/static_analyzer_error.rs
Normal file
@ -0,0 +1,62 @@
|
||||
// Copyright (C) 2019-2024 Aleo Systems Inc.
|
||||
// This file is part of the Leo library.
|
||||
|
||||
// The Leo library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// The Leo library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::create_messages;
|
||||
use std::fmt::{Debug, Display};
|
||||
|
||||
// TODO: Consolidate errors.
|
||||
|
||||
create_messages!(
|
||||
/// StaticAnalyzer enum that represents all the errors for static analysis.
|
||||
StaticAnalyzerError,
|
||||
code_mask: 4000i32,
|
||||
code_prefix: "SAZ",
|
||||
|
||||
@formatted
|
||||
no_path_awaits_all_futures_exactly_once {
|
||||
args: (num_total_paths: impl Display),
|
||||
msg: format!("Futures must be awaited exactly once. Out of `{num_total_paths}`, there does not exist a single path in which all futures are awaited exactly once."),
|
||||
help: Some("Ex: for `f: Future` call `f.await()` to await a future. Remove duplicate future await redundancies, and add future awaits for un-awaited futures.".to_string()),
|
||||
}
|
||||
|
||||
@formatted
|
||||
future_awaits_missing {
|
||||
args: (unawaited: impl Display),
|
||||
msg: format!("The following futures were never awaited: {unawaited}"),
|
||||
help: Some("Ex: for `f: Future` call `f.await()` to await a future.".to_string()),
|
||||
}
|
||||
|
||||
@formatted
|
||||
invalid_await_call {
|
||||
args: (),
|
||||
msg: "Not a valid await call.".to_string(),
|
||||
help: Some("Ex: for `f: Future` call `f.await()` or `Future::await(f)` to await a future.".to_string()),
|
||||
}
|
||||
|
||||
@formatted
|
||||
expected_future {
|
||||
args: (type_: impl Display),
|
||||
msg: format!("Expected a future, but found `{type_}`"),
|
||||
help: Some("Only futures can be awaited.".to_string()),
|
||||
}
|
||||
|
||||
@formatted
|
||||
async_transition_call_with_future_argument {
|
||||
args: (function_name: impl Display),
|
||||
msg: format!("The call to {function_name} will result in failed executions on-chain."),
|
||||
help: Some("There is a subtle error that occurs if an async transition call follows a non-async transition call, and the async call returns a `Future` that itself takes a `Future` as an input. See See `https://github.com/AleoNet/snarkVM/issues/2570` for more context.".to_string()),
|
||||
}
|
||||
);
|
54
errors/src/errors/static_analyzer/static_analyzer_warning.rs
Normal file
54
errors/src/errors/static_analyzer/static_analyzer_warning.rs
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright (C) 2019-2024 Aleo Systems Inc.
|
||||
// This file is part of the Leo library.
|
||||
|
||||
// The Leo library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// The Leo library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::create_messages;
|
||||
|
||||
use std::fmt::Display;
|
||||
|
||||
create_messages!(
|
||||
/// ParserWarning enum that represents all the warnings for static analysis
|
||||
StaticAnalyzerWarning,
|
||||
code_mask: 4000i32,
|
||||
code_prefix: "SAZ",
|
||||
|
||||
@formatted
|
||||
some_paths_do_not_await_all_futures {
|
||||
args: (num_total_paths: impl Display, num_unawaited_paths: impl Display),
|
||||
msg: format!("Not all paths through the function await all futures. {num_unawaited_paths}/{num_total_paths} paths contain at least one future that is never awaited."),
|
||||
help: Some("Ex: `f.await()` to await a future. Remove this warning by including the `--disable-conditional-branch-type-checking` flag.".to_string()),
|
||||
}
|
||||
|
||||
@formatted
|
||||
some_paths_contain_duplicate_future_awaits {
|
||||
args: (num_total_paths: impl Display, num_duplicate_await_paths: impl Display),
|
||||
msg: format!("Some paths through the function contain duplicate future awaits. {num_duplicate_await_paths}/{num_total_paths} paths contain at least one future that is awaited more than once."),
|
||||
help: Some("Look at the times `.await()` is called, and try to reduce redundancies. Remove this warning by including the `--disable-conditional-branch-type-checking` flag.".to_string()),
|
||||
}
|
||||
|
||||
@formatted
|
||||
max_conditional_block_depth_exceeded {
|
||||
args: (max: impl Display),
|
||||
msg: format!("The type checker has exceeded the max depth of nested conditional blocks: {max}."),
|
||||
help: Some("Re-run with a larger maximum depth using the `--conditional_block_max_depth` build option. Ex: `leo run main --conditional_block_max_depth 25`.".to_string()),
|
||||
}
|
||||
|
||||
@formatted
|
||||
future_not_awaited_in_order {
|
||||
args: (future_name: impl Display),
|
||||
msg: format!("The future `{}` is not awaited in the order in which they were passed in to the `async` function.", future_name),
|
||||
help: Some("While it is not required for futures to be awaited in order, there is some specific behavior that arises, which may affect the semantics of your program. See `https://github.com/AleoNet/snarkVM/issues/2570` for more context.".to_string()),
|
||||
}
|
||||
);
|
@ -742,6 +742,7 @@ create_messages!(
|
||||
help: Some(" Future arguments must be addressed by their index. Ex: `f.1.3`.".to_string()),
|
||||
}
|
||||
|
||||
// TODO: This error is deprecated. Remove.
|
||||
@formatted
|
||||
no_path_awaits_all_futures_exactly_once {
|
||||
args: (num_total_paths: impl Display),
|
||||
@ -749,6 +750,7 @@ create_messages!(
|
||||
help: Some("Ex: for `f: Future` call `f.await()` to await a future. Remove duplicate future await redundancies, and add future awaits for un-awaited futures.".to_string()),
|
||||
}
|
||||
|
||||
// TODO: This error is deprecated. Remove.
|
||||
@formatted
|
||||
future_awaits_missing {
|
||||
args: (unawaited: impl Display),
|
||||
@ -763,6 +765,7 @@ create_messages!(
|
||||
help: Some("Futures can only be defined as the result of async calls.".to_string()),
|
||||
}
|
||||
|
||||
// TODO: This error is deprecated. Remove.
|
||||
@formatted
|
||||
invalid_await_call {
|
||||
args: (),
|
||||
@ -777,6 +780,7 @@ create_messages!(
|
||||
help: Some("Ex: for `f: Future` call `f.await()` or `Future::await(f)` to await a future.".to_string()),
|
||||
}
|
||||
|
||||
// TODO: This error is deprecated. Remove.
|
||||
@formatted
|
||||
expected_future {
|
||||
args: (type_: impl Display),
|
||||
|
@ -38,6 +38,7 @@ create_messages!(
|
||||
help: Some("Look at the times `.await()` is called, and try to reduce redundancies. Remove this warning by including the `--disable-conditional-branch-type-checking` flag.".to_string()),
|
||||
}
|
||||
|
||||
// TODO: This warning is deprecated, remove it in the future.
|
||||
@formatted
|
||||
async_function_is_never_called_by_transition_function {
|
||||
args: (name: impl Display),
|
||||
|
47
tests/expectations/compiler/futures/await_out_of_order.out
Normal file
47
tests/expectations/compiler/futures/await_out_of_order.out
Normal file
@ -0,0 +1,47 @@
|
||||
namespace = "Compile"
|
||||
expectation = "Pass"
|
||||
outputs = [[{ compile = [
|
||||
{ initial_symbol_table = "c05e8ce7b527a0192d65e50963afd67a1fe92c837da97a5299c22af29f0275dd", type_checked_symbol_table = "8b2f1b5c22979924b6e08419e57fb515c05d3ce6932a9d1c1533ed4a2927aec2", unrolled_symbol_table = "8b2f1b5c22979924b6e08419e57fb515c05d3ce6932a9d1c1533ed4a2927aec2", initial_ast = "713c85bcb7d5fef43e4626a09e4fe3858f76de6025fcae475cb0398c26b5d123", unrolled_ast = "713c85bcb7d5fef43e4626a09e4fe3858f76de6025fcae475cb0398c26b5d123", ssa_ast = "5e2a213bd10e28dad299e0e48ac3336484fd2ffd894eeb63d15d67e6af65195e", flattened_ast = "11828763a38326b604155e1074699e6ca85205fbc83167d554624d0fe5d8bb2b", destructured_ast = "83c9eaa9aef53de6143980c9e001e59da64c291a7b2aa0693139b868339e589c", inlined_ast = "dda1aade2a50a9f25571004c8a68e3ff90efadd6a567ce25b1edbbd2e82b59d7", dce_ast = "dda1aade2a50a9f25571004c8a68e3ff90efadd6a567ce25b1edbbd2e82b59d7", bytecode = """
|
||||
program test.aleo;
|
||||
|
||||
mapping foo:
|
||||
key as u32.public;
|
||||
value as u32.public;
|
||||
|
||||
function main_inner:
|
||||
input r0 as u32.public;
|
||||
input r1 as u32.public;
|
||||
async main_inner r0 r1 into r2;
|
||||
output r2 as test.aleo/main_inner.future;
|
||||
|
||||
finalize main_inner:
|
||||
input r0 as u32.public;
|
||||
input r1 as u32.public;
|
||||
set r1 into foo[r0];
|
||||
""", errors = "", warnings = "" },
|
||||
{ initial_symbol_table = "748f1d6d760d63c1eb80d518379d99323e13132bf77520f8442534c79c64895b", type_checked_symbol_table = "3c5970cf8251ed27741614785eb8871b1df48e9437da1cc425c9c85448f63ed3", unrolled_symbol_table = "3c5970cf8251ed27741614785eb8871b1df48e9437da1cc425c9c85448f63ed3", initial_ast = "c1dddbcc56c1c3e89c4633a45eac54ca710cbb206f002e3cc8a4312342d5e43e", unrolled_ast = "1717122f03eb439466cb78560d07bb79e508a7549ce60de07bb76b1c0ccefdad", ssa_ast = "c53df47cb4b84b067fea09e1b1dbadeb7751b57c6624961d5df4317f609eddd1", flattened_ast = "ba297f2543a11739a669f85af00f9bae6b9149c6860d895216f1e5bd96617642", destructured_ast = "8531973ac60ebf3c0d7884bd0aa36794242a6575c379113053c01ca8f11a805f", inlined_ast = "48b3da6f8d8a056bb2e18f2b1b3d83d8a00ed4d259d65ad86321b824390141e9", dce_ast = "48b3da6f8d8a056bb2e18f2b1b3d83d8a00ed4d259d65ad86321b824390141e9", bytecode = """
|
||||
import test.aleo;
|
||||
program basic.aleo;
|
||||
|
||||
function main:
|
||||
input r0 as u32.public;
|
||||
input r1 as u32.private;
|
||||
call test.aleo/main_inner 0u32 0u32 into r2;
|
||||
call test.aleo/main_inner 1u32 1u32 into r3;
|
||||
async main r2 r3 into r4;
|
||||
output r4 as basic.aleo/main.future;
|
||||
|
||||
finalize main:
|
||||
input r0 as test.aleo/main_inner.future;
|
||||
input r1 as test.aleo/main_inner.future;
|
||||
await r1;
|
||||
await r0;
|
||||
""", errors = "", warnings = """
|
||||
Warning [WSAZ0374003]: The future `f2` is not awaited in the order in which they were passed in to the `async` function.
|
||||
--> compiler-test:13:9
|
||||
|
|
||||
13 | f2.await();
|
||||
| ^^
|
||||
|
|
||||
= While it is not required for futures to be awaited in order, there is some specific behavior that arises, which may affect the semantics of your program. See `https://github.com/AleoNet/snarkVM/issues/2570` for more context.""" },
|
||||
] }]]
|
@ -20,7 +20,7 @@ finalize main_inner:
|
||||
input r0 as u32.public;
|
||||
set 1u32 into foo[r0];
|
||||
""", errors = "", warnings = "" },
|
||||
{ initial_symbol_table = "ad49aec92f87f1e65648a7ae10d5bfb563f50bb397a933a9852c979b4ed5e3f3", type_checked_symbol_table = "7a05bbb86250bee3f69eee0c1f46f9d506dcb57c74358c26d158bde771b29bd7", unrolled_symbol_table = "7a05bbb86250bee3f69eee0c1f46f9d506dcb57c74358c26d158bde771b29bd7", initial_ast = "f4b27c45b21e659b2b730a167dbbf8a309b19e71beded7108cb7267b06177417", unrolled_ast = "bdd7c6800831eebcb6a09cb05acd5be0ad83730e1d210eb4d9b4d6b968d0b326", ssa_ast = "e4441d4a0d42e1061d4481bce0113ebd8a6f258dc9e877adc5e52029d3f04991", flattened_ast = "82cca8f1537803acde719f029a4ac265e0c1c53fa6e8cd4e4e2800a4d840c871", destructured_ast = "aee30ce903740d4f39c7f88aae66ed0bca4affce5b51988699cc9167ff946494", inlined_ast = "f4292c099047c4d8e3c0fbdaf7f32a1273a3eb68c4a11b0eccff59bd7c804247", dce_ast = "406a8d3de9427c696512e49e8f7ab27d48616754516e535152dc13c15a3e1ee0", bytecode = """
|
||||
{ initial_symbol_table = "4dd8afce563dd05c782ba0046cf84da0e161b0db932b993995bc119a0828174c", type_checked_symbol_table = "01e4b42297bfc584587cb7a0ebab2790e0fd87d7c645cdc55a8d6dcc6f48360f", unrolled_symbol_table = "01e4b42297bfc584587cb7a0ebab2790e0fd87d7c645cdc55a8d6dcc6f48360f", initial_ast = "f4b27c45b21e659b2b730a167dbbf8a309b19e71beded7108cb7267b06177417", unrolled_ast = "bdd7c6800831eebcb6a09cb05acd5be0ad83730e1d210eb4d9b4d6b968d0b326", ssa_ast = "e4441d4a0d42e1061d4481bce0113ebd8a6f258dc9e877adc5e52029d3f04991", flattened_ast = "82cca8f1537803acde719f029a4ac265e0c1c53fa6e8cd4e4e2800a4d840c871", destructured_ast = "aee30ce903740d4f39c7f88aae66ed0bca4affce5b51988699cc9167ff946494", inlined_ast = "f4292c099047c4d8e3c0fbdaf7f32a1273a3eb68c4a11b0eccff59bd7c804247", dce_ast = "406a8d3de9427c696512e49e8f7ab27d48616754516e535152dc13c15a3e1ee0", bytecode = """
|
||||
import test.aleo;
|
||||
program basic.aleo;
|
||||
|
||||
|
@ -19,7 +19,7 @@ function transfer_private_to_public:
|
||||
finalize transfer_private_to_public:
|
||||
assert.eq 1u8 1u8;
|
||||
""", errors = "", warnings = "" },
|
||||
{ initial_symbol_table = "fd67d75af194fb6d6fee5a2b15b4b51ae5511e5d0546c6c6f83063611a168123", type_checked_symbol_table = "031e9fc89b17624e259bb154ca42385665d2cf4349bf1579347a2d2487305a1b", unrolled_symbol_table = "031e9fc89b17624e259bb154ca42385665d2cf4349bf1579347a2d2487305a1b", initial_ast = "fc9f1985c1e0441e9423e67cfd4cb8252178ccc236dfabae17187c5a5cc98ebe", unrolled_ast = "c6fdd37447ee674a058e7fe314096c0df8cf0c02f307ff499e0f08b76cdc6709", ssa_ast = "d26ea69b3993a2a3c4b2660a27706c51383f9b01357d27adf6275a5dfffe6e9d", flattened_ast = "5741efe1907a4da96fbad021b725a22e8c3365fa61b2413b06743c3ed01cda35", destructured_ast = "496bea9fd498c2d4ac9d93dd143beb403e13fdf59fc2ff842d8ff932883feda1", inlined_ast = "7c87cc964f8225fd91c634c8683ee0b09aaa301cb29ab85cadc4e4aea65253ba", dce_ast = "7c87cc964f8225fd91c634c8683ee0b09aaa301cb29ab85cadc4e4aea65253ba", bytecode = """
|
||||
{ initial_symbol_table = "baa9875274a09ad91eb08326f18797401a6e98c32388e75b3b406a539acab343", type_checked_symbol_table = "610cf3eeddc2789f19854347864fbaae2dc10ecc0aae8034fe3eaaa2394ba89f", unrolled_symbol_table = "610cf3eeddc2789f19854347864fbaae2dc10ecc0aae8034fe3eaaa2394ba89f", initial_ast = "fc9f1985c1e0441e9423e67cfd4cb8252178ccc236dfabae17187c5a5cc98ebe", unrolled_ast = "c6fdd37447ee674a058e7fe314096c0df8cf0c02f307ff499e0f08b76cdc6709", ssa_ast = "d26ea69b3993a2a3c4b2660a27706c51383f9b01357d27adf6275a5dfffe6e9d", flattened_ast = "5741efe1907a4da96fbad021b725a22e8c3365fa61b2413b06743c3ed01cda35", destructured_ast = "496bea9fd498c2d4ac9d93dd143beb403e13fdf59fc2ff842d8ff932883feda1", inlined_ast = "7c87cc964f8225fd91c634c8683ee0b09aaa301cb29ab85cadc4e4aea65253ba", dce_ast = "7c87cc964f8225fd91c634c8683ee0b09aaa301cb29ab85cadc4e4aea65253ba", bytecode = """
|
||||
import credits.aleo;
|
||||
program test_credits.aleo;
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
namespace = "Compile"
|
||||
expectation = "Fail"
|
||||
outputs = ["""
|
||||
Error [ETYC0372093]: The following futures were never awaited: f4
|
||||
Error [ESAZ0374001]: The following futures were never awaited: f4
|
||||
--> compiler-test:12:5
|
||||
|
|
||||
12 | async function finalize_foo(f0: Future, f1: Future, f2: Future, f3: Future, f4: Future, f5: Future) {
|
||||
@ -14,4 +14,31 @@ Error [ETYC0372093]: The following futures were never awaited: f4
|
||||
| ^
|
||||
|
|
||||
= Ex: for `f: Future` call `f.await()` to await a future.
|
||||
"""]
|
||||
Warning [WSAZ0374003]: The future `f1` is not awaited in the order in which they were passed in to the `async` function.
|
||||
--> compiler-test:13:9
|
||||
|
|
||||
13 | f1.await();
|
||||
| ^^
|
||||
|
|
||||
= While it is not required for futures to be awaited in order, there is some specific behavior that arises, which may affect the semantics of your program. See `https://github.com/AleoNet/snarkVM/issues/2570` for more context.
|
||||
Warning [WSAZ0374003]: The future `f2` is not awaited in the order in which they were passed in to the `async` function.
|
||||
--> compiler-test:14:9
|
||||
|
|
||||
14 | f2.await();
|
||||
| ^^
|
||||
|
|
||||
= While it is not required for futures to be awaited in order, there is some specific behavior that arises, which may affect the semantics of your program. See `https://github.com/AleoNet/snarkVM/issues/2570` for more context.
|
||||
Warning [WSAZ0374003]: The future `f3` is not awaited in the order in which they were passed in to the `async` function.
|
||||
--> compiler-test:15:9
|
||||
|
|
||||
15 | f3.await();
|
||||
| ^^
|
||||
|
|
||||
= While it is not required for futures to be awaited in order, there is some specific behavior that arises, which may affect the semantics of your program. See `https://github.com/AleoNet/snarkVM/issues/2570` for more context.
|
||||
Warning [WSAZ0374003]: The future `f5` is not awaited in the order in which they were passed in to the `async` function.
|
||||
--> compiler-test:17:9
|
||||
|
|
||||
17 | f5.await();
|
||||
| ^^
|
||||
|
|
||||
= While it is not required for futures to be awaited in order, there is some specific behavior that arises, which may affect the semantics of your program. See `https://github.com/AleoNet/snarkVM/issues/2570` for more context."""]
|
||||
|
@ -24,7 +24,7 @@ finalize main_dep:
|
||||
input r1 as u32.public;
|
||||
set r1 into Yo[r0];
|
||||
""", errors = "", warnings = "" },
|
||||
{ initial_symbol_table = "837e6e9f7a93af9d92cb90208d54a4e55693939bccddf588c94102805a600ec2", type_checked_symbol_table = "c33e10eabb14d2d0dc8a7ffd7370dcda4d0467b46dc00d9a526c0cf7fc373906", unrolled_symbol_table = "c33e10eabb14d2d0dc8a7ffd7370dcda4d0467b46dc00d9a526c0cf7fc373906", initial_ast = "64089bd9ecc0ab9ce224328c7ba9b2ece577f585b2417b48eb0883ec8cec304c", unrolled_ast = "450bb73f7249477591a716a45cbd0fbb332d98a8765b2804ca919488cbc7e1bf", ssa_ast = "d445e67098ada41b7ada11f69a07acf107d1b8e6ab052e7bb3e8d1b6530c4371", flattened_ast = "b3e5d4d940f433b770b6acdd85c2a5f1de7327617f71783b75108c2a515c12a1", destructured_ast = "36361778b1d97dcde52548c1e082ad7382dbe6e6be4fd6be1fdc73bb213d0016", inlined_ast = "b358e9fa7f234ae1154b48cbd83c3e2029c1a83c5298470035729f78537e03a6", dce_ast = "4d6d5c792f8d7a9d83e0c1bee6efcf24470e92fd4746aa7a9d0afabc93ec8a19", bytecode = """
|
||||
{ initial_symbol_table = "354ff959a0573f0946a92f8626af3fd47b9ee3165f9b3971d60040e00d1e078f", type_checked_symbol_table = "f532890dcb4613a7f23287cebd8594b9f053e1d80ceba9ca9566c40925df460b", unrolled_symbol_table = "f532890dcb4613a7f23287cebd8594b9f053e1d80ceba9ca9566c40925df460b", initial_ast = "64089bd9ecc0ab9ce224328c7ba9b2ece577f585b2417b48eb0883ec8cec304c", unrolled_ast = "450bb73f7249477591a716a45cbd0fbb332d98a8765b2804ca919488cbc7e1bf", ssa_ast = "d445e67098ada41b7ada11f69a07acf107d1b8e6ab052e7bb3e8d1b6530c4371", flattened_ast = "b3e5d4d940f433b770b6acdd85c2a5f1de7327617f71783b75108c2a515c12a1", destructured_ast = "36361778b1d97dcde52548c1e082ad7382dbe6e6be4fd6be1fdc73bb213d0016", inlined_ast = "b358e9fa7f234ae1154b48cbd83c3e2029c1a83c5298470035729f78537e03a6", dce_ast = "4d6d5c792f8d7a9d83e0c1bee6efcf24470e92fd4746aa7a9d0afabc93ec8a19", bytecode = """
|
||||
import test_dep.aleo;
|
||||
program test.aleo;
|
||||
|
||||
@ -65,7 +65,7 @@ finalize main:
|
||||
add r0[0u32] r1[0u32] into r5;
|
||||
set r5 into ayo[1u32];
|
||||
""", errors = "", warnings = """
|
||||
Warning [WTYC0372000]: Not all paths through the function await all futures. 2/4 paths contain at least one future that is never awaited.
|
||||
Warning [WSAZ0374000]: Not all paths through the function await all futures. 2/4 paths contain at least one future that is never awaited.
|
||||
--> compiler-test:17:5
|
||||
|
|
||||
17 | async function finalize_main(f: Future, f2: Future, a: u32) {
|
||||
@ -86,7 +86,7 @@ Warning [WTYC0372000]: Not all paths through the function await all futures. 2/4
|
||||
| ^
|
||||
|
|
||||
= Ex: `f.await()` to await a future. Remove this warning by including the `--disable-conditional-branch-type-checking` flag.""" },
|
||||
{ initial_symbol_table = "11d73259b527776fa2019508fa961ca24850cc2bd0fbbcebfb7310c565289560", type_checked_symbol_table = "fb91e05612819b16dc6a1fb37cd80f776918dc1f502feca4d9428f42dc21754d", unrolled_symbol_table = "fb91e05612819b16dc6a1fb37cd80f776918dc1f502feca4d9428f42dc21754d", initial_ast = "05de2b0dcfd85ec6446f4507492e26b2093e771f44c497f92a24d6fff5e8c864", unrolled_ast = "4f09dae0678393afc3cbc5592159df83ca22b947084d3c8e779281724d07a2ca", ssa_ast = "0cb5c531ad471909089716ef6c7382fb3fcbb82dafb6edef541e4f7cff4fb8ba", flattened_ast = "46d54d4d9fe36538d34ac306780262ee1f54a6141aa2281ef7ae74ffcf4dddcf", destructured_ast = "88653b95656b6f56872d7ea452491322e4c122909879b72856b891c474aa8342", inlined_ast = "0f81029815dec13a526530eeea0e92e6eb61313421ce5a7b46ed3739d62beaf6", dce_ast = "6b852bcf601b323678eea14e096f49c72f8800d18ec811b00c31817daf630d63", bytecode = """
|
||||
{ initial_symbol_table = "539fd89c0dea3feb2b2b3844532aacc032658f2546cd011dd1aa257eb18dc0af", type_checked_symbol_table = "b3785d02f513f6e1671e4c42f2674c7ecb8da3f2c8bd20d36024d7d2e1322217", unrolled_symbol_table = "b3785d02f513f6e1671e4c42f2674c7ecb8da3f2c8bd20d36024d7d2e1322217", initial_ast = "05de2b0dcfd85ec6446f4507492e26b2093e771f44c497f92a24d6fff5e8c864", unrolled_ast = "4f09dae0678393afc3cbc5592159df83ca22b947084d3c8e779281724d07a2ca", ssa_ast = "0cb5c531ad471909089716ef6c7382fb3fcbb82dafb6edef541e4f7cff4fb8ba", flattened_ast = "46d54d4d9fe36538d34ac306780262ee1f54a6141aa2281ef7ae74ffcf4dddcf", destructured_ast = "88653b95656b6f56872d7ea452491322e4c122909879b72856b891c474aa8342", inlined_ast = "0f81029815dec13a526530eeea0e92e6eb61313421ce5a7b46ed3739d62beaf6", dce_ast = "6b852bcf601b323678eea14e096f49c72f8800d18ec811b00c31817daf630d63", bytecode = """
|
||||
import test_dep.aleo;
|
||||
import test.aleo;
|
||||
program wrapper.aleo;
|
||||
@ -109,7 +109,7 @@ finalize main:
|
||||
await r1;
|
||||
await r2;
|
||||
""", errors = "", warnings = "" },
|
||||
{ initial_symbol_table = "04a3a0ccbf4ed061d19da4e624725caff0e64ac838498cbd09df865f4f9044f2", type_checked_symbol_table = "69550e476553614e01dd39df0b3a8f682556cdf76982503af0e6a77d4916e027", unrolled_symbol_table = "69550e476553614e01dd39df0b3a8f682556cdf76982503af0e6a77d4916e027", initial_ast = "bf4f5dac2e3cac6f6c8b117a93b7bc9a4b9d31f66b3b0d946866da23003e6a69", unrolled_ast = "a1786c230d46f3b207f118aaaaea373cd1d9935aa7e63b99e403a8faf36df2fe", ssa_ast = "82581ca24afcd79d3e3c1346009981d4a9d3d227afc0540707b6c315ecdce107", flattened_ast = "2ff2d69c6199a5c70a8ffb96d8dc0529f6f1fbf631a1f690169d2d9162e91689", destructured_ast = "8da4c7c91fabf5edb6768e616f223e574b3415c848321f66ad9e587b76259210", inlined_ast = "a740025e070d37bd22f264e37dfd6802eb9e1b10c12c928a08acd14fbe9043d6", dce_ast = "e127a5223a49f123398009b927e96ebb44f266df7271feb7b1ff5f7f748e6ff5", bytecode = """
|
||||
{ initial_symbol_table = "07bdfd403caa73ec17903694bb68a93e108011dc9d77e555fd2815e4da90a1de", type_checked_symbol_table = "9e2a9214686265f8ebc82b39d1102894360f03fd7e0f1cf3f8f8dc1cf463f0c6", unrolled_symbol_table = "9e2a9214686265f8ebc82b39d1102894360f03fd7e0f1cf3f8f8dc1cf463f0c6", initial_ast = "bf4f5dac2e3cac6f6c8b117a93b7bc9a4b9d31f66b3b0d946866da23003e6a69", unrolled_ast = "a1786c230d46f3b207f118aaaaea373cd1d9935aa7e63b99e403a8faf36df2fe", ssa_ast = "82581ca24afcd79d3e3c1346009981d4a9d3d227afc0540707b6c315ecdce107", flattened_ast = "2ff2d69c6199a5c70a8ffb96d8dc0529f6f1fbf631a1f690169d2d9162e91689", destructured_ast = "8da4c7c91fabf5edb6768e616f223e574b3415c848321f66ad9e587b76259210", inlined_ast = "a740025e070d37bd22f264e37dfd6802eb9e1b10c12c928a08acd14fbe9043d6", dce_ast = "e127a5223a49f123398009b927e96ebb44f266df7271feb7b1ff5f7f748e6ff5", bytecode = """
|
||||
import test_dep.aleo;
|
||||
import test.aleo;
|
||||
import wrapper.aleo;
|
||||
|
@ -0,0 +1,58 @@
|
||||
namespace = "Compile"
|
||||
expectation = "Pass"
|
||||
outputs = [[{ compile = [
|
||||
{ initial_symbol_table = "6cd6500abf0e8651ba271e6aa7703e19da9c183c54cc5304ecbc59bf9336fce8", type_checked_symbol_table = "75075f8b61db1c78b075b1b7b042f351d4b406457277b05e2f4f531e19eed0d0", unrolled_symbol_table = "75075f8b61db1c78b075b1b7b042f351d4b406457277b05e2f4f531e19eed0d0", initial_ast = "242372b2feb8f6e98c77aa4bb4a891130a5ceb5c07ec724cce9c4dde4fd49208", unrolled_ast = "242372b2feb8f6e98c77aa4bb4a891130a5ceb5c07ec724cce9c4dde4fd49208", ssa_ast = "2787cc66971dcd0423755380ff9f4adc0a4ec03825407ff9fda2f2c731179c75", flattened_ast = "cf44ace46cbe7e60114c27ac8c6fbbdd2097f599134bdfe37822f3d4093b9f8a", destructured_ast = "72f55596cce2dab4e8fd8f2a8eff12931cd159f6eb5585dc13334ff20ad36f87", inlined_ast = "fc67b7df09f254e6c1fd19bc3005be38ce306eea369efa384ecba6b38639a638", dce_ast = "fc67b7df09f254e6c1fd19bc3005be38ce306eea369efa384ecba6b38639a638", bytecode = """
|
||||
program inner.aleo;
|
||||
|
||||
mapping foo:
|
||||
key as u32.public;
|
||||
value as u32.public;
|
||||
|
||||
function inner:
|
||||
input r0 as u32.private;
|
||||
async inner r0 into r1;
|
||||
output r1 as inner.aleo/inner.future;
|
||||
|
||||
finalize inner:
|
||||
input r0 as u32.public;
|
||||
set r0 into foo[0u32];
|
||||
""", errors = "", warnings = "" },
|
||||
{ initial_symbol_table = "386cb81f5601365a2c421d1a78a1bcfaa78fd6c3172666c6a9d1c49b02233d6e", type_checked_symbol_table = "7ad49c58b4cdb6eadc16c5c55f66dbc6dacde2fb624e91b374e60ce5ad8b2425", unrolled_symbol_table = "7ad49c58b4cdb6eadc16c5c55f66dbc6dacde2fb624e91b374e60ce5ad8b2425", initial_ast = "f25d550819ceefd793a9711f96460c97c78ca1aeb7da21d3105dbcb06020ea8f", unrolled_ast = "b04609dab316adc708b481faf5241c5a67cb9fd3cbfa21531788b6bc01c9c8e6", ssa_ast = "e3f3822d24d05d2b393d2311ad1a115c69b816050fbd5c5b095f2713573d2030", flattened_ast = "ee6255715b49f761e5f12a23d7e25b968eb29821f9c2c6ee91a040ab7b7a0a0c", destructured_ast = "3d349126a6c352d726734cfcdd72affbe58584734f65c77e819ee1b171a135d3", inlined_ast = "cd9854c1633542668ffe6bf0e1f00de68f99ed21fddae01d161f2887e2e18180", dce_ast = "cd9854c1633542668ffe6bf0e1f00de68f99ed21fddae01d161f2887e2e18180", bytecode = """
|
||||
import inner.aleo;
|
||||
program mid.aleo;
|
||||
|
||||
function mid:
|
||||
input r0 as u32.private;
|
||||
call inner.aleo/inner 0u32 into r1;
|
||||
call inner.aleo/inner 1u32 into r2;
|
||||
async mid r2 r1 into r3;
|
||||
output r3 as mid.aleo/mid.future;
|
||||
|
||||
finalize mid:
|
||||
input r0 as inner.aleo/inner.future;
|
||||
input r1 as inner.aleo/inner.future;
|
||||
await r0;
|
||||
await r1;
|
||||
|
||||
function dummy:
|
||||
""", errors = "", warnings = "" },
|
||||
{ initial_symbol_table = "f662e7a456e22a2d1b4b42fa3221de16e5671edc25c1d0b20610dfd0ab55c579", type_checked_symbol_table = "bc09a36414412397442b9bf24d95ddbb21d0bf2d1b70f7084df400bdd836e37a", unrolled_symbol_table = "bc09a36414412397442b9bf24d95ddbb21d0bf2d1b70f7084df400bdd836e37a", initial_ast = "5df535c99668c958f5649f0e5d24ae951023b165941ded5e9df3665a1c4bdd7d", unrolled_ast = "57200953ba2c83408d2dbc51c10e7c01143b6ed3f3dcf96616e7072ac99e2152", ssa_ast = "223b30eb9d800a33aab6105dea3b4dde8bc3435673b1be29ab4268e944406384", flattened_ast = "2ed49413ee703e36ee432a5f271fecb3327be45039477ee9bc2bc6ef77e25f41", destructured_ast = "26b81f6ad2dab39e3a9a5e1d73ebff1f5a165f794897fd770ed0f7927a34bf95", inlined_ast = "5dc7a113088ff1f7682c9b5618e381baa011609a7f2e1a876272c1fd79b6dfd3", dce_ast = "5dc7a113088ff1f7682c9b5618e381baa011609a7f2e1a876272c1fd79b6dfd3", bytecode = """
|
||||
import inner.aleo;
|
||||
import mid.aleo;
|
||||
program outer.aleo;
|
||||
|
||||
function outer:
|
||||
input r0 as u32.private;
|
||||
call mid.aleo/mid 0u32 into r1;
|
||||
call mid.aleo/mid 1u32 into r2;
|
||||
call mid.aleo/dummy;
|
||||
async outer r1 r2 into r3;
|
||||
output r3 as outer.aleo/outer.future;
|
||||
|
||||
finalize outer:
|
||||
input r0 as mid.aleo/mid.future;
|
||||
input r1 as mid.aleo/mid.future;
|
||||
await r0;
|
||||
await r1;
|
||||
""", errors = "", warnings = "" },
|
||||
] }]]
|
@ -0,0 +1,52 @@
|
||||
namespace = "Compile"
|
||||
expectation = "Pass"
|
||||
outputs = [[{ compile = [
|
||||
{ initial_symbol_table = "16e119df6ee0ccf0c2a2eaa55c81867664630b3468627f778098d1ff0c8cd5fa", type_checked_symbol_table = "f4fb482aeb7abb52f5ca3aae4f42a53b98f7403ec1d2c488996efb1ff11f213b", unrolled_symbol_table = "f4fb482aeb7abb52f5ca3aae4f42a53b98f7403ec1d2c488996efb1ff11f213b", initial_ast = "5a07ca97b09d15a8549692408a74444dc346fbd3c8d08b1e3fa4dc60d2a0a05c", unrolled_ast = "5a07ca97b09d15a8549692408a74444dc346fbd3c8d08b1e3fa4dc60d2a0a05c", ssa_ast = "50c140777b792e917824e9021e722774b3e037f2d97c9d0c59a14b2c5088c98b", flattened_ast = "f6f59f2f6e0f8b8c933ecdb0d2360cd9c53a2ba10486c2935f72140b48b68927", destructured_ast = "f5851f2b9ebf08030bf8a9778e0c52c85f61b0a32f3eed802897da99c48a29bd", inlined_ast = "8051736585fdd624f74052e44368eef86e1a7e9533152406503a5737939c4e1e", dce_ast = "8051736585fdd624f74052e44368eef86e1a7e9533152406503a5737939c4e1e", bytecode = """
|
||||
program test.aleo;
|
||||
|
||||
mapping foo:
|
||||
key as u32.public;
|
||||
value as u32.public;
|
||||
|
||||
function main_inner:
|
||||
input r0 as u32.public;
|
||||
input r1 as u32.public;
|
||||
async main_inner r0 r1 into r2;
|
||||
output r2 as test.aleo/main_inner.future;
|
||||
|
||||
finalize main_inner:
|
||||
input r0 as u32.public;
|
||||
input r1 as u32.public;
|
||||
set r1 into foo[r0];
|
||||
|
||||
function baz:
|
||||
input r0 as u32.private;
|
||||
input r1 as u32.private;
|
||||
add r0 r1 into r2;
|
||||
output r2 as u32.private;
|
||||
""", errors = "", warnings = "" },
|
||||
{ initial_symbol_table = "42d242bf08b1ff58a2640d65713dcb4783a7b59c9fe35af1863b819c33e6b9f2", type_checked_symbol_table = "f28e9e26827f070928d22fcd6ab9e070dec65d97d4e6b3333959e75ca91a9953", unrolled_symbol_table = "f28e9e26827f070928d22fcd6ab9e070dec65d97d4e6b3333959e75ca91a9953", initial_ast = "959ef8008a2cb837e0f067c6954356034892bed1a8dcda72224f08e360a1c791", unrolled_ast = "f5a2e49f992ab80a104ceae85eb1c0a34c094ee9012a7ca9d5d6406f050515c4", ssa_ast = "a70cc7f42605c3f72904723c4c8237e3eada556f617588f9bde00e07d58c2cd2", flattened_ast = "02f4563ed934754a6db1939c5b3017356e63e4deaeafb66091c46500a534d8ab", destructured_ast = "56153136bc984183c654e6a4fcc8bd607c801b0a92a502d4c008360e6b816c54", inlined_ast = "573187f8b898181cc4f1c59ca1dc960b4767fa818591ccd3189eee82fc698155", dce_ast = "573187f8b898181cc4f1c59ca1dc960b4767fa818591ccd3189eee82fc698155", bytecode = """
|
||||
import test.aleo;
|
||||
program basic.aleo;
|
||||
|
||||
function main:
|
||||
input r0 as u32.public;
|
||||
input r1 as u32.private;
|
||||
call test.aleo/baz r0 r1 into r2;
|
||||
assert.eq r2 1u32;
|
||||
call test.aleo/main_inner 0u32 0u32 into r3;
|
||||
call test.aleo/baz r0 r1 into r4;
|
||||
assert.eq r4 1u32;
|
||||
call test.aleo/main_inner 1u32 1u32 into r5;
|
||||
call test.aleo/baz r0 r1 into r6;
|
||||
assert.eq r6 1u32;
|
||||
async main r3 r5 into r7;
|
||||
output r7 as basic.aleo/main.future;
|
||||
|
||||
finalize main:
|
||||
input r0 as test.aleo/main_inner.future;
|
||||
input r1 as test.aleo/main_inner.future;
|
||||
await r0;
|
||||
await r1;
|
||||
""", errors = "", warnings = "" },
|
||||
] }]]
|
@ -0,0 +1,25 @@
|
||||
namespace = "Compile"
|
||||
expectation = "Fail"
|
||||
outputs = ["""
|
||||
Error [ESAZ0374004]: The call to mid will result in failed executions on-chain.
|
||||
--> compiler-test:8:26
|
||||
|
|
||||
8 | let f1: Future = mid.aleo/mid(0u32);
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= There is a subtle error that occurs if an async transition call follows a non-async transition call, and the async call returns a `Future` that itself takes a `Future` as an input. See See `https://github.com/AleoNet/snarkVM/issues/2570` for more context.
|
||||
Error [ESAZ0374004]: The call to mid will result in failed executions on-chain.
|
||||
--> compiler-test:9:26
|
||||
|
|
||||
9 | let f2: Future = mid.aleo/mid(1u32);
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= There is a subtle error that occurs if an async transition call follows a non-async transition call, and the async call returns a `Future` that itself takes a `Future` as an input. See See `https://github.com/AleoNet/snarkVM/issues/2570` for more context.
|
||||
Error [ESAZ0374004]: The call to mid will result in failed executions on-chain.
|
||||
--> compiler-test:17:26
|
||||
|
|
||||
17 | let f2: Future = mid.aleo/mid(1u32);
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= There is a subtle error that occurs if an async transition call follows a non-async transition call, and the async call returns a `Future` that itself takes a `Future` as an input. See See `https://github.com/AleoNet/snarkVM/issues/2570` for more context.
|
||||
"""]
|
@ -34,7 +34,7 @@ function main_dep_2:
|
||||
finalize main_dep_2:
|
||||
set 1u32 into Yo[1u32];
|
||||
""", errors = "", warnings = "" },
|
||||
{ initial_symbol_table = "1a537ce4873945cd8969e08fd2440d3d9dbf4175306e7a60a18f59305958366e", type_checked_symbol_table = "3c670b67da9da6028e642d487a1382f3de1b554c8c0d51fc531b71e36b5cdef5", unrolled_symbol_table = "3c670b67da9da6028e642d487a1382f3de1b554c8c0d51fc531b71e36b5cdef5", initial_ast = "bcfa98eafaf355e7313773fa4340b88d2530e3d2b279252fc1117327de42d77a", unrolled_ast = "01a9f5e11f5749b408619a513bf7f9eececfd83f9f87c883fcd8db53440babab", ssa_ast = "b6da9c41019a2af6cd137e29fe7b5041cc13a45d574b920101a69f7093c58980", flattened_ast = "7bddc7f16b5ef5baef1fc50ac2f45767844d05fc0de797d267c77306bc586dc5", destructured_ast = "df2c950dd52d4094ef1f2d364aa6dd57020f7ca431ead915353c2c33482ee05d", inlined_ast = "7dd0bb6eee84d038c01e43a8c7fdfd38ec3cbb269bf4990078a49e5202fe177e", dce_ast = "4378a2b09abc850959d98704efb7ec28bd6ad7962cc4ec761e26e57400cec8a0", bytecode = """
|
||||
{ initial_symbol_table = "1efe1fca5533564cb10347a951f503433d841d861e7eae035d3a86912ac5e475", type_checked_symbol_table = "5c2b623a5f1f09b4bd46ab77d25c40a1966d596f6cc41f7c4d93f883094ad185", unrolled_symbol_table = "5c2b623a5f1f09b4bd46ab77d25c40a1966d596f6cc41f7c4d93f883094ad185", initial_ast = "bcfa98eafaf355e7313773fa4340b88d2530e3d2b279252fc1117327de42d77a", unrolled_ast = "01a9f5e11f5749b408619a513bf7f9eececfd83f9f87c883fcd8db53440babab", ssa_ast = "b6da9c41019a2af6cd137e29fe7b5041cc13a45d574b920101a69f7093c58980", flattened_ast = "7bddc7f16b5ef5baef1fc50ac2f45767844d05fc0de797d267c77306bc586dc5", destructured_ast = "df2c950dd52d4094ef1f2d364aa6dd57020f7ca431ead915353c2c33482ee05d", inlined_ast = "7dd0bb6eee84d038c01e43a8c7fdfd38ec3cbb269bf4990078a49e5202fe177e", dce_ast = "4378a2b09abc850959d98704efb7ec28bd6ad7962cc4ec761e26e57400cec8a0", bytecode = """
|
||||
import test_dep.aleo;
|
||||
program test.aleo;
|
||||
|
||||
@ -75,7 +75,7 @@ finalize main:
|
||||
add r0[0u32] r1[0u32] into r5;
|
||||
set r5 into ayo[1u32];
|
||||
""", errors = "", warnings = """
|
||||
Warning [WTYC0372000]: Not all paths through the function await all futures. 2/4 paths contain at least one future that is never awaited.
|
||||
Warning [WSAZ0374000]: Not all paths through the function await all futures. 2/4 paths contain at least one future that is never awaited.
|
||||
--> compiler-test:17:5
|
||||
|
|
||||
17 | async function finalize_main(f: Future, f2: Future, a: u32) {
|
||||
@ -96,7 +96,7 @@ Warning [WTYC0372000]: Not all paths through the function await all futures. 2/4
|
||||
| ^
|
||||
|
|
||||
= Ex: `f.await()` to await a future. Remove this warning by including the `--disable-conditional-branch-type-checking` flag.""" },
|
||||
{ initial_symbol_table = "04f7d3a44d791763aec79b596224c653e682ab928bc0cba71a1cd6282198e885", type_checked_symbol_table = "d9d3363d1049a924bbae356d0f90ac3c9bfca7f6ae5ba51ad915d66e9d0b9a1e", unrolled_symbol_table = "d9d3363d1049a924bbae356d0f90ac3c9bfca7f6ae5ba51ad915d66e9d0b9a1e", initial_ast = "856e56d95eaf14f6e9241001763546b7d982402ac87521e2ec3b7ea476764692", unrolled_ast = "75b69748ca1e534c95cf084164773d471f51537b50b2d517dc4be26dddb06e1b", ssa_ast = "6d38bf225e9cf5af37b9d6c595c2973ec31a32d227ca65cb590d27400d442780", flattened_ast = "65fb4138701cad86a5fcd7e024645e833aeb6e88b3ea2a3a6b69269fd1d77620", destructured_ast = "85a81c23da7e97b057ddf4ef71f375781e1dfcb90d656d694a5aa0f0c176b497", inlined_ast = "a1b2367575e170a79ace2ac7ff071bc3c770476b37ee149310c3b2cfe67b1c7f", dce_ast = "f46fa7963b327b9c75c9f7a7569e350d7f62c21964cb5df140cd2186c2043697", bytecode = """
|
||||
{ initial_symbol_table = "cd14d130e4f9b9b92f731cb8caee6237ae4477573ea636af8775e5e02966390e", type_checked_symbol_table = "387eabcc94db2a5021555b90e0dddcb7373aa3344fe7bbc86087f32f0893fa35", unrolled_symbol_table = "387eabcc94db2a5021555b90e0dddcb7373aa3344fe7bbc86087f32f0893fa35", initial_ast = "856e56d95eaf14f6e9241001763546b7d982402ac87521e2ec3b7ea476764692", unrolled_ast = "75b69748ca1e534c95cf084164773d471f51537b50b2d517dc4be26dddb06e1b", ssa_ast = "6d38bf225e9cf5af37b9d6c595c2973ec31a32d227ca65cb590d27400d442780", flattened_ast = "65fb4138701cad86a5fcd7e024645e833aeb6e88b3ea2a3a6b69269fd1d77620", destructured_ast = "85a81c23da7e97b057ddf4ef71f375781e1dfcb90d656d694a5aa0f0c176b497", inlined_ast = "a1b2367575e170a79ace2ac7ff071bc3c770476b37ee149310c3b2cfe67b1c7f", dce_ast = "f46fa7963b327b9c75c9f7a7569e350d7f62c21964cb5df140cd2186c2043697", bytecode = """
|
||||
import test_dep.aleo;
|
||||
import test.aleo;
|
||||
program wrapper.aleo;
|
||||
@ -119,7 +119,7 @@ finalize main:
|
||||
await r1;
|
||||
await r2;
|
||||
""", errors = "", warnings = "" },
|
||||
{ initial_symbol_table = "11c1000ce2f1774ad382af12ba51e8b55d5a98ee0da67cb8620e686c1fcaebb1", type_checked_symbol_table = "9f27eb3f177ceb81d9b14cc85c07b7198eb67d0ee806c04cbbff1cfb18b997ab", unrolled_symbol_table = "9f27eb3f177ceb81d9b14cc85c07b7198eb67d0ee806c04cbbff1cfb18b997ab", initial_ast = "575e251f07e552c917ab36bc9877b13dd1638651c4023ade20701dd2a5fe27ff", unrolled_ast = "2a4969ad315e900b5a3f1eecd4e6508dc6946fb5f6c3861ee793961ce6bcc203", ssa_ast = "4a00e3d36cdd4ff4be1fc6a389aaf17cfb02b6c54fa84276fb5be66b8a78b124", flattened_ast = "885c5f8145aa1a82e5fe41abbabae12cbd15eb014b333b246c6c5401b5b6bfea", destructured_ast = "f3b5b961a498f9befec85b69b3012145a6e97774d37a8c8e354ec4e5eeb64f84", inlined_ast = "2bf37fc499b3eca18c8227e61f69f730d36e755d7879dde13bb9161936bafbfc", dce_ast = "390391c2098cf6a910eeec98fc92fdea31303a84a1d6fd6673c8dbd9d20180de", bytecode = """
|
||||
{ initial_symbol_table = "29aefa9acac4488265303e8b3bd52a434ae4824211df7919f6b63cfe6e1ec51f", type_checked_symbol_table = "1d1a8312d73125086e436d6463fd554fbc3aa622a2e28efc8622ddf0adfb473f", unrolled_symbol_table = "1d1a8312d73125086e436d6463fd554fbc3aa622a2e28efc8622ddf0adfb473f", initial_ast = "575e251f07e552c917ab36bc9877b13dd1638651c4023ade20701dd2a5fe27ff", unrolled_ast = "2a4969ad315e900b5a3f1eecd4e6508dc6946fb5f6c3861ee793961ce6bcc203", ssa_ast = "4a00e3d36cdd4ff4be1fc6a389aaf17cfb02b6c54fa84276fb5be66b8a78b124", flattened_ast = "885c5f8145aa1a82e5fe41abbabae12cbd15eb014b333b246c6c5401b5b6bfea", destructured_ast = "f3b5b961a498f9befec85b69b3012145a6e97774d37a8c8e354ec4e5eeb64f84", inlined_ast = "2bf37fc499b3eca18c8227e61f69f730d36e755d7879dde13bb9161936bafbfc", dce_ast = "390391c2098cf6a910eeec98fc92fdea31303a84a1d6fd6673c8dbd9d20180de", bytecode = """
|
||||
import test_dep.aleo;
|
||||
import test.aleo;
|
||||
import wrapper.aleo;
|
||||
|
40
tests/expectations/compiler/futures/pass_in_out_of_order.out
Normal file
40
tests/expectations/compiler/futures/pass_in_out_of_order.out
Normal file
@ -0,0 +1,40 @@
|
||||
namespace = "Compile"
|
||||
expectation = "Pass"
|
||||
outputs = [[{ compile = [
|
||||
{ initial_symbol_table = "c05e8ce7b527a0192d65e50963afd67a1fe92c837da97a5299c22af29f0275dd", type_checked_symbol_table = "8b2f1b5c22979924b6e08419e57fb515c05d3ce6932a9d1c1533ed4a2927aec2", unrolled_symbol_table = "8b2f1b5c22979924b6e08419e57fb515c05d3ce6932a9d1c1533ed4a2927aec2", initial_ast = "713c85bcb7d5fef43e4626a09e4fe3858f76de6025fcae475cb0398c26b5d123", unrolled_ast = "713c85bcb7d5fef43e4626a09e4fe3858f76de6025fcae475cb0398c26b5d123", ssa_ast = "5e2a213bd10e28dad299e0e48ac3336484fd2ffd894eeb63d15d67e6af65195e", flattened_ast = "11828763a38326b604155e1074699e6ca85205fbc83167d554624d0fe5d8bb2b", destructured_ast = "83c9eaa9aef53de6143980c9e001e59da64c291a7b2aa0693139b868339e589c", inlined_ast = "dda1aade2a50a9f25571004c8a68e3ff90efadd6a567ce25b1edbbd2e82b59d7", dce_ast = "dda1aade2a50a9f25571004c8a68e3ff90efadd6a567ce25b1edbbd2e82b59d7", bytecode = """
|
||||
program test.aleo;
|
||||
|
||||
mapping foo:
|
||||
key as u32.public;
|
||||
value as u32.public;
|
||||
|
||||
function main_inner:
|
||||
input r0 as u32.public;
|
||||
input r1 as u32.public;
|
||||
async main_inner r0 r1 into r2;
|
||||
output r2 as test.aleo/main_inner.future;
|
||||
|
||||
finalize main_inner:
|
||||
input r0 as u32.public;
|
||||
input r1 as u32.public;
|
||||
set r1 into foo[r0];
|
||||
""", errors = "", warnings = "" },
|
||||
{ initial_symbol_table = "748f1d6d760d63c1eb80d518379d99323e13132bf77520f8442534c79c64895b", type_checked_symbol_table = "3c5970cf8251ed27741614785eb8871b1df48e9437da1cc425c9c85448f63ed3", unrolled_symbol_table = "3c5970cf8251ed27741614785eb8871b1df48e9437da1cc425c9c85448f63ed3", initial_ast = "0614c4d1a71ead028505adbca60be45e21f8dfff3cac5c2d5825fdccb742599a", unrolled_ast = "3937cfdaeaeb310aed147b646aa466e86c2be135f08c34caba4c442d9287cc00", ssa_ast = "085e51180733890a2fa69926ff9aff285cbe30fbfb212363b7cde717f8fdb726", flattened_ast = "f8c1203193c1ede409ac0f76bdd99dcc3030182b0e04fcde92b21588e2130806", destructured_ast = "c2f3abb79321f123b41bf581e21b8abe73f799f1e3d4431fa68849d7ee4f2053", inlined_ast = "501b7b97d2873c583d12763895fa3d01a7fac7a7554d91b71850d9f8060413c8", dce_ast = "501b7b97d2873c583d12763895fa3d01a7fac7a7554d91b71850d9f8060413c8", bytecode = """
|
||||
import test.aleo;
|
||||
program basic.aleo;
|
||||
|
||||
function main:
|
||||
input r0 as u32.public;
|
||||
input r1 as u32.private;
|
||||
call test.aleo/main_inner 0u32 0u32 into r2;
|
||||
call test.aleo/main_inner 1u32 1u32 into r3;
|
||||
async main r3 r2 into r4;
|
||||
output r4 as basic.aleo/main.future;
|
||||
|
||||
finalize main:
|
||||
input r0 as test.aleo/main_inner.future;
|
||||
input r1 as test.aleo/main_inner.future;
|
||||
await r0;
|
||||
await r1;
|
||||
""", errors = "", warnings = "" },
|
||||
] }]]
|
@ -19,7 +19,7 @@ function main_inner:
|
||||
finalize main_inner:
|
||||
set 1u32 into foo[1u32];
|
||||
""", errors = "", warnings = "" },
|
||||
{ initial_symbol_table = "e68fd2fbfc3ff3832375c1c2df1e6a67787480498938fc77e766ca07ae751992", type_checked_symbol_table = "a3dbe89fee3c01d1a1798775bd34ee5e9a160d9a31bc223cf8d949ad08310b43", unrolled_symbol_table = "a3dbe89fee3c01d1a1798775bd34ee5e9a160d9a31bc223cf8d949ad08310b43", initial_ast = "90315edede362afca47bb3f8c861ab8bbbdb049ea56db7ebbbf8f20ce60aeb4a", unrolled_ast = "6541d8c338b4eeb027aedd7c9151f3eac30d61ab2986d22a008ef5bd4a67ffc7", ssa_ast = "80086e21c3779f9da4b57c755eedf9132709a1edc63644ef4ec574ce047b076f", flattened_ast = "a9988b6cbd9cb03bc49e6850084531888e0cc04e456496fe7eff390812d39611", destructured_ast = "a94ba575cc25982052a729a8a1b8fa3560a0043b305cf4dede91d17a71202fcb", inlined_ast = "7a6d98c84ce9a50bd944f11bca3d98f8262ab57b55fcc7f15537650b3d4bc6ef", dce_ast = "ef3d06f7a3ed3bba09c3fda4378aaa2f700384fc28e5d8c3751633bbc03f9f4e", bytecode = """
|
||||
{ initial_symbol_table = "6c555c940588a42fbc942c59adb0a7d43f9423b5e08eea2ab43581fb8d979a41", type_checked_symbol_table = "bda27ed9363abf086753d5bb203fa4c10c8fb4168e6759f58e1eef1c5ae48dbf", unrolled_symbol_table = "bda27ed9363abf086753d5bb203fa4c10c8fb4168e6759f58e1eef1c5ae48dbf", initial_ast = "90315edede362afca47bb3f8c861ab8bbbdb049ea56db7ebbbf8f20ce60aeb4a", unrolled_ast = "6541d8c338b4eeb027aedd7c9151f3eac30d61ab2986d22a008ef5bd4a67ffc7", ssa_ast = "80086e21c3779f9da4b57c755eedf9132709a1edc63644ef4ec574ce047b076f", flattened_ast = "a9988b6cbd9cb03bc49e6850084531888e0cc04e456496fe7eff390812d39611", destructured_ast = "a94ba575cc25982052a729a8a1b8fa3560a0043b305cf4dede91d17a71202fcb", inlined_ast = "7a6d98c84ce9a50bd944f11bca3d98f8262ab57b55fcc7f15537650b3d4bc6ef", dce_ast = "ef3d06f7a3ed3bba09c3fda4378aaa2f700384fc28e5d8c3751633bbc03f9f4e", bytecode = """
|
||||
import test.aleo;
|
||||
program basic.aleo;
|
||||
|
||||
|
@ -24,7 +24,7 @@ finalize unregister:
|
||||
input r0 as address.public;
|
||||
set false into users[r0];
|
||||
""", errors = "", warnings = "" },
|
||||
{ initial_symbol_table = "23d4f67793776c110bfd4cc47d98dedde4495edb453c82f6b06718a8cdbc7f6d", type_checked_symbol_table = "f8c6d89c3ff7316d9a2e391c1a0d6c7f3f4ab2f45109b0dbd58b6ff424d854dd", unrolled_symbol_table = "f8c6d89c3ff7316d9a2e391c1a0d6c7f3f4ab2f45109b0dbd58b6ff424d854dd", initial_ast = "9cc519cc416b2f54ecf753c541196b337f359d42616e4f38b8d9a5a86746de41", unrolled_ast = "4f5beff4969ba9db8b429435d2a6a6133eed2e8718564073fefa76ed4db76381", ssa_ast = "012d0c07475a7e03d3898338aa2a91b56d77032978437b17c9337a5001ae5249", flattened_ast = "e391d1d2c6731ec8961afe91d8fa94fb9edb091b892ddecfa48ce3f5a6febe8e", destructured_ast = "26f202a3d6a24f0af49542d0f2c29c635314073b2d52ede163d3ab5e5bcc86fa", inlined_ast = "72e4121a823f91aeeb5b8433f03f07943d174353d55f58a3aae111bc1bab0798", dce_ast = "72e4121a823f91aeeb5b8433f03f07943d174353d55f58a3aae111bc1bab0798", bytecode = """
|
||||
{ initial_symbol_table = "ad44035dc7b8fd88c75dae7732786222905037adcba313f1fa11964e3b6a3a18", type_checked_symbol_table = "2ae36cf87aea22ac6069d3d750ea3ed2b2ac03c0f9ee75f957edf106095aa036", unrolled_symbol_table = "2ae36cf87aea22ac6069d3d750ea3ed2b2ac03c0f9ee75f957edf106095aa036", initial_ast = "9cc519cc416b2f54ecf753c541196b337f359d42616e4f38b8d9a5a86746de41", unrolled_ast = "4f5beff4969ba9db8b429435d2a6a6133eed2e8718564073fefa76ed4db76381", ssa_ast = "012d0c07475a7e03d3898338aa2a91b56d77032978437b17c9337a5001ae5249", flattened_ast = "e391d1d2c6731ec8961afe91d8fa94fb9edb091b892ddecfa48ce3f5a6febe8e", destructured_ast = "26f202a3d6a24f0af49542d0f2c29c635314073b2d52ede163d3ab5e5bcc86fa", inlined_ast = "72e4121a823f91aeeb5b8433f03f07943d174353d55f58a3aae111bc1bab0798", dce_ast = "72e4121a823f91aeeb5b8433f03f07943d174353d55f58a3aae111bc1bab0798", bytecode = """
|
||||
import registry.aleo;
|
||||
program relay.aleo;
|
||||
|
||||
|
@ -17,7 +17,7 @@ finalize init:
|
||||
input r0 as TestStruct.public;
|
||||
assert.eq 0u32 0u32;
|
||||
""", errors = "", warnings = "" },
|
||||
{ initial_symbol_table = "c9f26fb8c18222d0819c01087efc4aae88ea8944dec03710d94c38c24e0d077a", type_checked_symbol_table = "ed3db1e139955da3a7df17d8abdf36ddcabf05e2cb0cc6af012cce4a4fc67fae", unrolled_symbol_table = "ed3db1e139955da3a7df17d8abdf36ddcabf05e2cb0cc6af012cce4a4fc67fae", initial_ast = "b1348090a951e00cbf76c62d734fa808bfceea5b4169aa6da15a08ff185cbc50", unrolled_ast = "f1c461c8b0f677d0954ff6d29ab29abb648b57c7c141ddaf116a28d837e2b546", ssa_ast = "39e50a1b965cf6d4c19750d75edd4b1a8f8c02c04bbcb361f4fa70cebdc39574", flattened_ast = "a5a1c8def04670f3c5177946811bd27dcae5b045fce181e5e3307d9964686341", destructured_ast = "97153aa38aad12f2695c1e457270bd678add4d96f01f78660a9be0ab8cd409bf", inlined_ast = "97153aa38aad12f2695c1e457270bd678add4d96f01f78660a9be0ab8cd409bf", dce_ast = "97153aa38aad12f2695c1e457270bd678add4d96f01f78660a9be0ab8cd409bf", bytecode = """
|
||||
{ initial_symbol_table = "df5db326efa87ea83dbafd0e06782435113131775dc2aa80754176a6433e34c3", type_checked_symbol_table = "4c659204bbe76e0bc59df1829ce5ae48f3bc830ae96ce5cf1b29cb69dfe0943b", unrolled_symbol_table = "4c659204bbe76e0bc59df1829ce5ae48f3bc830ae96ce5cf1b29cb69dfe0943b", initial_ast = "b1348090a951e00cbf76c62d734fa808bfceea5b4169aa6da15a08ff185cbc50", unrolled_ast = "f1c461c8b0f677d0954ff6d29ab29abb648b57c7c141ddaf116a28d837e2b546", ssa_ast = "39e50a1b965cf6d4c19750d75edd4b1a8f8c02c04bbcb361f4fa70cebdc39574", flattened_ast = "a5a1c8def04670f3c5177946811bd27dcae5b045fce181e5e3307d9964686341", destructured_ast = "97153aa38aad12f2695c1e457270bd678add4d96f01f78660a9be0ab8cd409bf", inlined_ast = "97153aa38aad12f2695c1e457270bd678add4d96f01f78660a9be0ab8cd409bf", dce_ast = "97153aa38aad12f2695c1e457270bd678add4d96f01f78660a9be0ab8cd409bf", bytecode = """
|
||||
import parent.aleo;
|
||||
program child.aleo;
|
||||
|
||||
|
@ -35,7 +35,7 @@ finalize d:
|
||||
add r1 1u64 into r2;
|
||||
set r2 into counts[r0];
|
||||
""", errors = "", warnings = "" },
|
||||
{ initial_symbol_table = "6223f92c3bd5bbad5da2f567698b6e984ece97d3134095b26cc0b1d11079f60c", type_checked_symbol_table = "e22aa51f2a565205fe03a6f3b00552bd2e3442e100315dab5f2805a7f8b4cb69", unrolled_symbol_table = "e22aa51f2a565205fe03a6f3b00552bd2e3442e100315dab5f2805a7f8b4cb69", initial_ast = "2c14e776b891d7131858e07a8dba4dbf727b3d01dbf4d2e22415711d688dc7c3", unrolled_ast = "31db5dfbc43b124cb4780c1d629ee28de4a249a5aba21727a0dcb9726d4322f6", ssa_ast = "1f4225e1f83eb88bb3368544c3b2a077da163281476eaeb688334dac41bc0a9d", flattened_ast = "eba4b124fd3df6170a5cbfaad89f0e6d398cb2cba50d61b3c18f00381a6b3be9", destructured_ast = "c1e81066ab08a49915eaaed5b82b323ab1b7227157be6916832ff22eb658b15c", inlined_ast = "22f3f544c5331fee78a3b81381f6695bdaa06f437c4a56142b36da1e852d9840", dce_ast = "22f3f544c5331fee78a3b81381f6695bdaa06f437c4a56142b36da1e852d9840", bytecode = """
|
||||
{ initial_symbol_table = "245c739fc70f8cdcd2b24f30d8aec16924fcab28c52d7c0043646622dbe75f57", type_checked_symbol_table = "8263d5899d205220dc81a56f9785ba66255b723f07d6203b6697708812831273", unrolled_symbol_table = "8263d5899d205220dc81a56f9785ba66255b723f07d6203b6697708812831273", initial_ast = "2c14e776b891d7131858e07a8dba4dbf727b3d01dbf4d2e22415711d688dc7c3", unrolled_ast = "31db5dfbc43b124cb4780c1d629ee28de4a249a5aba21727a0dcb9726d4322f6", ssa_ast = "1f4225e1f83eb88bb3368544c3b2a077da163281476eaeb688334dac41bc0a9d", flattened_ast = "eba4b124fd3df6170a5cbfaad89f0e6d398cb2cba50d61b3c18f00381a6b3be9", destructured_ast = "c1e81066ab08a49915eaaed5b82b323ab1b7227157be6916832ff22eb658b15c", inlined_ast = "22f3f544c5331fee78a3b81381f6695bdaa06f437c4a56142b36da1e852d9840", dce_ast = "22f3f544c5331fee78a3b81381f6695bdaa06f437c4a56142b36da1e852d9840", bytecode = """
|
||||
import zero_program.aleo;
|
||||
import one_program.aleo;
|
||||
program two_program.aleo;
|
||||
@ -60,7 +60,7 @@ finalize b:
|
||||
add r3 1u64 into r4;
|
||||
set r4 into counts[r2];
|
||||
""", errors = "", warnings = "" },
|
||||
{ initial_symbol_table = "7d0a0d54b673b8428f972bec8346ca6830248f69cb3fba4b42c32e1a72cc1b0f", type_checked_symbol_table = "ea10fb298006b83389a483e12f9b97b7e1f691dc0a1aee602e74e10d915e8b0c", unrolled_symbol_table = "ea10fb298006b83389a483e12f9b97b7e1f691dc0a1aee602e74e10d915e8b0c", initial_ast = "387aba043fde6ead4d99bf4eb5c817051491a7d16aecd6383411e3cbc6aaefd5", unrolled_ast = "f93e4fd19542c5af01a5e0aec60e9f6265491a0952cafabfb7cdcfac00bd81b9", ssa_ast = "0ad477f1c1bc42ebcd4098caf856428e5be9a0845972cbd2908dcf53c6ce45a0", flattened_ast = "3fa8070cfe4be62533fb8b3d899c490f940686a97ae01ee0c8f6f7743527d726", destructured_ast = "5407ddb3a931cde7e50dc466557108fde8f6ebfd8d446cdb44855542208f4056", inlined_ast = "8accc3977c89a2e948b39f6abc2c7f989e52313aac237bcb25469e4bc91fc4f1", dce_ast = "8accc3977c89a2e948b39f6abc2c7f989e52313aac237bcb25469e4bc91fc4f1", bytecode = """
|
||||
{ initial_symbol_table = "ee9c47b21aa811094b66a4cef0eef7af32effb924a2f514094b5280b4d611987", type_checked_symbol_table = "bf3047bd773d692e484ef3bddcaca86ffc8c897f658afe2f85cb592c4b856ca3", unrolled_symbol_table = "bf3047bd773d692e484ef3bddcaca86ffc8c897f658afe2f85cb592c4b856ca3", initial_ast = "387aba043fde6ead4d99bf4eb5c817051491a7d16aecd6383411e3cbc6aaefd5", unrolled_ast = "f93e4fd19542c5af01a5e0aec60e9f6265491a0952cafabfb7cdcfac00bd81b9", ssa_ast = "0ad477f1c1bc42ebcd4098caf856428e5be9a0845972cbd2908dcf53c6ce45a0", flattened_ast = "3fa8070cfe4be62533fb8b3d899c490f940686a97ae01ee0c8f6f7743527d726", destructured_ast = "5407ddb3a931cde7e50dc466557108fde8f6ebfd8d446cdb44855542208f4056", inlined_ast = "8accc3977c89a2e948b39f6abc2c7f989e52313aac237bcb25469e4bc91fc4f1", dce_ast = "8accc3977c89a2e948b39f6abc2c7f989e52313aac237bcb25469e4bc91fc4f1", bytecode = """
|
||||
import zero_program.aleo;
|
||||
import one_program.aleo;
|
||||
import two_program.aleo;
|
||||
@ -89,7 +89,7 @@ finalize e:
|
||||
add r4 1u64 into r5;
|
||||
set r5 into counts[r3];
|
||||
""", errors = "", warnings = "" },
|
||||
{ initial_symbol_table = "8272b3774900302d111cc659f82a49e7df702875ceb4e54787c068bcac901a85", type_checked_symbol_table = "3b9ce08a512a197af239b00944b50298885603f4f723debc4ee96b281d28bc4c", unrolled_symbol_table = "3b9ce08a512a197af239b00944b50298885603f4f723debc4ee96b281d28bc4c", initial_ast = "f731cdda879e0134eb5b1cf0d64d3cf5abbee2fd2ce758d3afac05ee07fb885f", unrolled_ast = "79017a53e402d0c7aad500a44936f4e06e418407b4a2b40f2bf69a185c4865c0", ssa_ast = "8a4f2ea8f8118515b8843aad5a201824dc2c6b06046f68698dde622f5ace3c4f", flattened_ast = "35f966d0d86e1e38c2c6650d83e62d701a9b9440766b78919ee0b509c3255cf7", destructured_ast = "5677314a7b55bf523441d3c40029daedf97666fb7821159b0c88654776ea2932", inlined_ast = "9c779149583480acdca132daad34c2577ec0d09e28c36b11ecf91beb556cc7b5", dce_ast = "9c779149583480acdca132daad34c2577ec0d09e28c36b11ecf91beb556cc7b5", bytecode = """
|
||||
{ initial_symbol_table = "044526dfe3dfe09fde9004db01d837c5fe566d508d6a6045b8b64c6921179e15", type_checked_symbol_table = "ad633121ad08786628d1ddd39eddae1004962f1f6dcb2370179c751fd460fcfe", unrolled_symbol_table = "ad633121ad08786628d1ddd39eddae1004962f1f6dcb2370179c751fd460fcfe", initial_ast = "f731cdda879e0134eb5b1cf0d64d3cf5abbee2fd2ce758d3afac05ee07fb885f", unrolled_ast = "79017a53e402d0c7aad500a44936f4e06e418407b4a2b40f2bf69a185c4865c0", ssa_ast = "8a4f2ea8f8118515b8843aad5a201824dc2c6b06046f68698dde622f5ace3c4f", flattened_ast = "35f966d0d86e1e38c2c6650d83e62d701a9b9440766b78919ee0b509c3255cf7", destructured_ast = "5677314a7b55bf523441d3c40029daedf97666fb7821159b0c88654776ea2932", inlined_ast = "9c779149583480acdca132daad34c2577ec0d09e28c36b11ecf91beb556cc7b5", dce_ast = "9c779149583480acdca132daad34c2577ec0d09e28c36b11ecf91beb556cc7b5", bytecode = """
|
||||
import zero_program.aleo;
|
||||
import one_program.aleo;
|
||||
import two_program.aleo;
|
||||
|
31
tests/tests/compiler/futures/await_out_of_order.leo
Normal file
31
tests/tests/compiler/futures/await_out_of_order.leo
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
namespace = "Compile"
|
||||
expectation = "Pass"
|
||||
*/
|
||||
program test.aleo {
|
||||
mapping foo: u32 => u32;
|
||||
async transition main_inner(public a: u32, public b: u32) -> Future {
|
||||
return finalize(a, b);
|
||||
}
|
||||
|
||||
async function finalize(a: u32, b: u32) {
|
||||
Mapping::set(foo, a, b);
|
||||
}
|
||||
}
|
||||
|
||||
// --- Next Program --- //
|
||||
|
||||
import test.aleo;
|
||||
program basic.aleo {
|
||||
async transition main(public a: u32, b: u32) -> Future {
|
||||
let f1: Future = test.aleo/main_inner(0u32, 0u32);
|
||||
let f2: Future = test.aleo/main_inner(1u32, 1u32);
|
||||
let f:Future = finalize(f1, f2);
|
||||
return f;
|
||||
}
|
||||
|
||||
async function finalize(f1: Future, f2: Future) {
|
||||
f2.await();
|
||||
f1.await();
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
namespace = "Compile"
|
||||
expectation = "Pass"
|
||||
*/
|
||||
program inner.aleo {
|
||||
mapping foo: u32 => u32;
|
||||
|
||||
async transition inner(a: u32) -> Future {
|
||||
return finalize(a);
|
||||
}
|
||||
|
||||
async function finalize(a: u32) {
|
||||
Mapping::set(foo, 0u32, a);
|
||||
}
|
||||
}
|
||||
|
||||
// --- Next Program --- //
|
||||
|
||||
import inner.aleo;
|
||||
program mid.aleo {
|
||||
async transition mid(a: u32) -> Future {
|
||||
let f1: Future = inner.aleo/inner(0u32);
|
||||
let f2: Future = inner.aleo/inner(1u32);
|
||||
let f:Future = finalize(f2, f1);
|
||||
return f;
|
||||
}
|
||||
|
||||
async function finalize(f1: Future, f2: Future) {
|
||||
f1.await();
|
||||
f2.await();
|
||||
}
|
||||
|
||||
transition dummy() {}
|
||||
}
|
||||
|
||||
// --- Next Program --- //
|
||||
|
||||
import inner.aleo;
|
||||
import mid.aleo;
|
||||
program outer.aleo {
|
||||
async transition outer(a: u32) -> Future {
|
||||
let f1: Future = mid.aleo/mid(0u32);
|
||||
let f2: Future = mid.aleo/mid(1u32);
|
||||
mid.aleo/dummy();
|
||||
let f:Future = finalize(f1, f2);
|
||||
return f;
|
||||
}
|
||||
|
||||
async function finalize(f1: Future, f2: Future) {
|
||||
f1.await();
|
||||
f2.await();
|
||||
}
|
||||
}
|
47
tests/tests/compiler/futures/non_async_before_async.leo
Normal file
47
tests/tests/compiler/futures/non_async_before_async.leo
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
namespace = "Compile"
|
||||
expectation = "Pass"
|
||||
*/
|
||||
program test.aleo {
|
||||
mapping foo: u32 => u32;
|
||||
|
||||
async transition main_inner(public a: u32, public b: u32) -> Future {
|
||||
return finalize(a, b);
|
||||
}
|
||||
|
||||
async function finalize(a: u32, b: u32) {
|
||||
Mapping::set(foo, a, b);
|
||||
}
|
||||
|
||||
transition baz(a: u32, b: u32) -> u32 {
|
||||
return a + b;
|
||||
}
|
||||
}
|
||||
|
||||
// --- Next Program --- //
|
||||
|
||||
import test.aleo;
|
||||
program basic.aleo {
|
||||
async transition main(public a: u32, b: u32) -> Future {
|
||||
let sum1: u32 = test.aleo/baz(a, b);
|
||||
assert_eq(sum1, 1u32);
|
||||
|
||||
let f1: Future = test.aleo/main_inner(0u32, 0u32);
|
||||
|
||||
let sum2: u32 = test.aleo/baz(a, b);
|
||||
assert_eq(sum2, 1u32);
|
||||
|
||||
let f2: Future = test.aleo/main_inner(1u32, 1u32);
|
||||
|
||||
let sum3: u32 = test.aleo/baz(a, b);
|
||||
assert_eq(sum3, 1u32);
|
||||
|
||||
let f:Future = finalize(f1, f2);
|
||||
return f;
|
||||
}
|
||||
|
||||
async function finalize(f1: Future, f2: Future) {
|
||||
f1.await();
|
||||
f2.await();
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
namespace = "Compile"
|
||||
expectation = "Fail"
|
||||
*/
|
||||
program inner.aleo {
|
||||
mapping foo: u32 => u32;
|
||||
|
||||
async transition inner(a: u32) -> Future {
|
||||
return finalize(a);
|
||||
}
|
||||
|
||||
async function finalize(a: u32) {
|
||||
Mapping::set(foo, 0u32, a);
|
||||
}
|
||||
}
|
||||
|
||||
// --- Next Program --- //
|
||||
|
||||
import inner.aleo;
|
||||
program mid.aleo {
|
||||
async transition mid(a: u32) -> Future {
|
||||
let f1: Future = inner.aleo/inner(0u32);
|
||||
let f2: Future = inner.aleo/inner(1u32);
|
||||
let f:Future = finalize(f2, f1);
|
||||
return f;
|
||||
}
|
||||
|
||||
async function finalize(f1: Future, f2: Future) {
|
||||
f1.await();
|
||||
f2.await();
|
||||
}
|
||||
|
||||
transition dummy() {}
|
||||
}
|
||||
|
||||
// --- Next Program --- //
|
||||
|
||||
import inner.aleo;
|
||||
import mid.aleo;
|
||||
program outer.aleo {
|
||||
async transition outer_1(a: u32) -> Future {
|
||||
mid.aleo/dummy();
|
||||
let f1: Future = mid.aleo/mid(0u32);
|
||||
let f2: Future = mid.aleo/mid(1u32);
|
||||
let f:Future = finalize(f1, f2);
|
||||
return f;
|
||||
}
|
||||
|
||||
async transition outer_2(a: u32) -> Future {
|
||||
let f1: Future = mid.aleo/mid(0u32);
|
||||
mid.aleo/dummy();
|
||||
let f2: Future = mid.aleo/mid(1u32);
|
||||
let f:Future = finalize(f1, f2);
|
||||
return f;
|
||||
}
|
||||
|
||||
async function finalize(f1: Future, f2: Future) {
|
||||
f1.await();
|
||||
f2.await();
|
||||
}
|
||||
}
|
31
tests/tests/compiler/futures/pass_in_out_of_order.leo
Normal file
31
tests/tests/compiler/futures/pass_in_out_of_order.leo
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
namespace = "Compile"
|
||||
expectation = "Pass"
|
||||
*/
|
||||
program test.aleo {
|
||||
mapping foo: u32 => u32;
|
||||
async transition main_inner(public a: u32, public b: u32) -> Future {
|
||||
return finalize(a, b);
|
||||
}
|
||||
|
||||
async function finalize(a: u32, b: u32) {
|
||||
Mapping::set(foo, a, b);
|
||||
}
|
||||
}
|
||||
|
||||
// --- Next Program --- //
|
||||
|
||||
import test.aleo;
|
||||
program basic.aleo {
|
||||
async transition main(public a: u32, b: u32) -> Future {
|
||||
let f1: Future = test.aleo/main_inner(0u32, 0u32);
|
||||
let f2: Future = test.aleo/main_inner(1u32, 1u32);
|
||||
let f:Future = finalize(f2, f1);
|
||||
return f;
|
||||
}
|
||||
|
||||
async function finalize(f1: Future, f2: Future) {
|
||||
f1.await();
|
||||
f2.await();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user