mirror of
https://github.com/AleoHQ/leo.git
synced 2024-09-11 15:05:33 +03:00
Merge pull request #28316 from ProvableHQ/fix/tuple-future
[Fix] Futures in Tuples
This commit is contained in:
commit
4a7b062175
@ -113,9 +113,11 @@ impl Type {
|
||||
///
|
||||
/// Returns `true` if the self `Type` is equal to the other `Type` in all aspects besides composite program of origin.
|
||||
///
|
||||
/// In the case of futures, it also makes sure that if both are not explicit, they are equal.
|
||||
///
|
||||
/// Flattens array syntax: `[[u8; 1]; 2] == [u8; (2, 1)] == true`
|
||||
///
|
||||
pub fn eq_flat_relax_composite(&self, other: &Self) -> bool {
|
||||
pub fn eq_flat_relaxed(&self, other: &Self) -> bool {
|
||||
match (self, other) {
|
||||
(Type::Address, Type::Address)
|
||||
| (Type::Boolean, Type::Boolean)
|
||||
@ -126,18 +128,18 @@ impl Type {
|
||||
| (Type::String, Type::String)
|
||||
| (Type::Unit, Type::Unit) => true,
|
||||
(Type::Array(left), Type::Array(right)) => {
|
||||
left.element_type().eq_flat_relax_composite(right.element_type()) && left.length() == right.length()
|
||||
left.element_type().eq_flat_relaxed(right.element_type()) && left.length() == right.length()
|
||||
}
|
||||
(Type::Identifier(left), Type::Identifier(right)) => left.matches(right),
|
||||
(Type::Integer(left), Type::Integer(right)) => left.eq(right),
|
||||
(Type::Mapping(left), Type::Mapping(right)) => {
|
||||
left.key.eq_flat_relax_composite(&right.key) && left.value.eq_flat(&right.value)
|
||||
left.key.eq_flat_relaxed(&right.key) && left.value.eq_flat_relaxed(&right.value)
|
||||
}
|
||||
(Type::Tuple(left), Type::Tuple(right)) if left.length() == right.length() => left
|
||||
.elements()
|
||||
.iter()
|
||||
.zip_eq(right.elements().iter())
|
||||
.all(|(left_type, right_type)| left_type.eq_flat_relax_composite(right_type)),
|
||||
.all(|(left_type, right_type)| left_type.eq_flat_relaxed(right_type)),
|
||||
(Type::Composite(left), Type::Composite(right)) => left.id.name == right.id.name,
|
||||
// Don't type check when type hasn't been explicitly defined.
|
||||
(Type::Future(left), Type::Future(right)) if !left.is_explicit || !right.is_explicit => true,
|
||||
@ -145,7 +147,7 @@ impl Type {
|
||||
.inputs()
|
||||
.iter()
|
||||
.zip_eq(right.inputs().iter())
|
||||
.all(|(left_type, right_type)| left_type.eq_flat_relax_composite(right_type)),
|
||||
.all(|(left_type, right_type)| left_type.eq_flat_relaxed(right_type)),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ impl SymbolTable {
|
||||
return false;
|
||||
}
|
||||
for (member1, member2) in new.members.iter().zip(old.members.iter()) {
|
||||
if member1.name() != member2.name() || !member1.type_.eq_flat_relax_composite(&member2.type_) {
|
||||
if member1.name() != member2.name() || !member1.type_.eq_flat_relaxed(&member2.type_) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ impl ExpressionReconstructor for Flattener<'_> {
|
||||
};
|
||||
|
||||
// Note that type checking guarantees that both expressions have the same same type. This is a sanity check.
|
||||
assert!(first_type.eq_flat_relax_composite(&second_type));
|
||||
assert!(first_type.eq_flat_relaxed(&second_type));
|
||||
|
||||
match &first_type {
|
||||
Type::Array(first_type) => self.ternary_array(first_type, &input.condition, &first, &second),
|
||||
|
@ -148,15 +148,9 @@ impl<'a, N: Network> ExpressionVisitor<'a> for TypeChecker<'a, N> {
|
||||
} else {
|
||||
// Lookup type of tuple index.
|
||||
let actual = tuple.elements().get(index).expect("failed to get tuple index").clone();
|
||||
// Emit error for mismatched types.
|
||||
if let Some(expected) = expected {
|
||||
// Emit error for mismatched types.
|
||||
if !actual.eq_flat(expected) {
|
||||
self.emit_err(TypeCheckerError::type_should_be(
|
||||
&actual,
|
||||
expected,
|
||||
access.span(),
|
||||
))
|
||||
}
|
||||
self.check_eq_types(&Some(actual.clone()), &Some(expected.clone()), access.span());
|
||||
}
|
||||
|
||||
// Return type of tuple index.
|
||||
|
@ -143,7 +143,7 @@ impl<'a, N: Network> ProgramVisitor<'a> for TypeChecker<'a, N> {
|
||||
|need, expected_ty: Type| match input.members.iter().find_map(|Member { identifier, type_, .. }| {
|
||||
(identifier.name == need).then_some((identifier, type_))
|
||||
}) {
|
||||
Some((_, actual_ty)) if expected_ty.eq_flat(actual_ty) => {} // All good, found + right type!
|
||||
Some((_, actual_ty)) if expected_ty.eq_flat_relaxed(actual_ty) => {} // All good, found + right type!
|
||||
Some((field, _)) => {
|
||||
self.emit_err(TypeCheckerError::record_var_wrong_type(field, expected_ty, input.span()));
|
||||
}
|
||||
|
@ -174,7 +174,7 @@ impl<'a, N: Network> TypeChecker<'a, N> {
|
||||
/// Emits an error if the two given types are not equal.
|
||||
pub(crate) fn check_eq_types(&self, t1: &Option<Type>, t2: &Option<Type>, span: Span) {
|
||||
match (t1, t2) {
|
||||
(Some(t1), Some(t2)) if !Type::eq_flat_relax_composite(t1, t2) => {
|
||||
(Some(t1), Some(t2)) if !Type::eq_flat_relaxed(t1, t2) => {
|
||||
// If both types are futures, print them out.
|
||||
if let (Type::Future(f1), Type::Future(f2)) = (t1, t2) {
|
||||
println!("Future 1: {:?}", f1);
|
||||
|
31
tests/expectations/compiler/futures/future_in_tuple.out
Normal file
31
tests/expectations/compiler/futures/future_in_tuple.out
Normal file
@ -0,0 +1,31 @@
|
||||
---
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- - compile:
|
||||
- initial_symbol_table: e19a77f482bf38e20c7ecd69838dadb5e778a6a95c1de2eb56bddc42121b8940
|
||||
type_checked_symbol_table: 33b1b5c2459bfa8d5c5b4b740965f4d59e09990037934364b94f1cb2e6316c2f
|
||||
unrolled_symbol_table: 33b1b5c2459bfa8d5c5b4b740965f4d59e09990037934364b94f1cb2e6316c2f
|
||||
initial_ast: 65074d34d89168f67b8db62c7b091b8c02e93aeda11f79c218c3761e270f8c09
|
||||
unrolled_ast: 65074d34d89168f67b8db62c7b091b8c02e93aeda11f79c218c3761e270f8c09
|
||||
ssa_ast: 3b05d816fbca67dce63e2f851a77f8ffa65930e3eb094c01647f05d251305632
|
||||
flattened_ast: 6fa4c0335842d7ba9412438bbf35dcd75843107f14a25ebeb16b8a150bee11b7
|
||||
destructured_ast: f21d1fc10d1ebd9a86273f17a20bd1cd1247c1ce1456f9ad252cb7c4f5bb10bb
|
||||
inlined_ast: 3cb6765aec323b35119157dd2e3264aead6820169d79b182c256f499af1ff5a8
|
||||
dce_ast: 3cb6765aec323b35119157dd2e3264aead6820169d79b182c256f499af1ff5a8
|
||||
bytecode: 5650e018cca64d11f7a2eb88b57ed2f9fcc81a2b56856f983f660d34421dd82e
|
||||
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: a3cec0fb931bb7be4c60ea116dec933b1587fc50f37efdd9a0816628889a2f68
|
||||
errors: ""
|
||||
warnings: ""
|
34
tests/tests/compiler/futures/future_in_tuple.leo
Normal file
34
tests/tests/compiler/futures/future_in_tuple.leo
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
*/
|
||||
program credits.aleo {
|
||||
record credits {
|
||||
owner: address,
|
||||
amount: u64,
|
||||
}
|
||||
|
||||
async transition transfer_private_to_public(input: credits, addr: address, amount:u64) -> (credits, Future) {
|
||||
let f: Future = finalize();
|
||||
return (input, f);
|
||||
}
|
||||
|
||||
async function finalize() {
|
||||
assert_eq(1u8, 1u8);
|
||||
}
|
||||
}
|
||||
|
||||
// --- Next Program --- //
|
||||
|
||||
import credits.aleo;
|
||||
|
||||
program test_credits.aleo {
|
||||
async transition send_credits(input: credits.aleo/credits, amount: u64) -> (credits.aleo/credits, Future) {
|
||||
let result: (credits.aleo/credits, Future) = credits.aleo/transfer_private_to_public(input, self.address, amount);
|
||||
return (result.0, finish(result.1));
|
||||
}
|
||||
|
||||
async function finish(f: Future) {
|
||||
f.await();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user