Merge pull request #1054 from AleoHQ/bugs/1040-1041-input-bugs

input bugs fixes
This commit is contained in:
Alessandro Coglio 2021-06-22 15:07:28 -07:00 committed by GitHub
commit 214c5b21c9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 221 additions and 20 deletions

View File

@ -26,6 +26,7 @@ use leo_input::{
CharValue as InputCharValue,
FieldValue,
GroupValue as InputGroupValue,
IntegerValue,
NumberValue,
Value,
},
@ -102,6 +103,32 @@ impl InputValue {
(DataType::Boolean(_), Value::Boolean(boolean)) => InputValue::from_boolean(boolean),
(DataType::Char(_), Value::Char(character)) => InputValue::from_char(character),
(DataType::Integer(integer_type), Value::Integer(integer)) => {
match integer.clone() {
IntegerValue::Signed(signed) => {
if let IntegerType::Signed(inner) = integer_type.clone() {
let singed_type = signed.clone().type_;
if std::mem::discriminant(&inner) != std::mem::discriminant(&singed_type) {
return Err(InputParserError::integer_type_mismatch(
integer_type,
IntegerType::Signed(singed_type),
integer.span(),
));
}
}
}
IntegerValue::Unsigned(unsigned) => {
if let IntegerType::Unsigned(inner) = integer_type.clone() {
let unsinged_type = unsigned.clone().type_;
if std::mem::discriminant(&inner) != std::mem::discriminant(&unsinged_type) {
return Err(InputParserError::integer_type_mismatch(
integer_type,
IntegerType::Unsigned(unsinged_type),
integer.span(),
));
}
}
}
}
Ok(InputValue::from_number(integer_type, integer.to_string()))
}
(DataType::Group(_), Value::Group(group)) => Ok(InputValue::from_group(group)),

View File

@ -14,7 +14,7 @@
// 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 leo_ast::{FormattedError, LeoError, Span};
use leo_ast::{FormattedError, IntegerType, LeoError, Span};
use snarkvm_gadgets::errors::{SignedIntegerError, UnsignedIntegerError};
use snarkvm_r1cs::SynthesisError;
@ -68,6 +68,12 @@ impl IntegerError {
Self::new_from_span(message, span)
}
pub fn integer_type_mismatch(expected: &IntegerType, received: IntegerType, span: &Span) -> Self {
let message = format!("expected data type `{}`, found `{}`", expected, received);
Self::new_from_span(message, span)
}
pub fn invalid_integer(actual: String, span: &Span) -> Self {
let message = format!("failed to parse `{}` as expected integer type", actual);

View File

@ -67,7 +67,7 @@ impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
(_, Some(_), Some(_)) => {
return Err(FunctionError::double_input_declaration(
name.to_string(),
&function.span.clone().unwrap_or_default(),
&input_variable.name.span,
));
}
// If input option is found in [main] section and input is not const.
@ -76,7 +76,7 @@ impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
&input_variable.type_.clone(),
&name,
input_option,
&function.span.clone().unwrap_or_default(),
&input_variable.name.span,
)?,
// If input option is found in [constants] section and function argument is const.
(true, _, Some(input_option)) => self.constant_main_function_input(
@ -84,27 +84,27 @@ impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
&input_variable.type_.clone(),
&name,
input_option,
&function.span.clone().unwrap_or_default(),
&input_variable.name.span,
)?,
// Function argument is const, input is not.
(true, Some(_), None) => {
return Err(FunctionError::expected_const_input(
name.to_string(),
&function.span.clone().unwrap_or_default(),
&input_variable.name.span,
));
}
// Input is const, function argument is not.
(false, None, Some(_)) => {
return Err(FunctionError::expected_non_const_input(
name.to_string(),
&function.span.clone().unwrap_or_default(),
&input_variable.name.span,
));
}
// When not found - Error out.
(_, _, _) => {
return Err(FunctionError::input_not_found(
name.to_string(),
&function.span.clone().unwrap_or_default(),
&input_variable.name.span,
));
}
};

View File

@ -157,7 +157,11 @@ impl Integer {
// Check that the input value is the correct type
let option = match integer_value {
Some(input) => {
if let InputValue::Integer(_type_, number) = input {
if let InputValue::Integer(type_, number) = input {
let asg_type = IntegerType::from(type_);
if std::mem::discriminant(&asg_type) != std::mem::discriminant(integer_type) {
return Err(IntegerError::integer_type_mismatch(integer_type, asg_type, span));
}
Some(number)
} else {
return Err(IntegerError::invalid_integer(input.to_string(), span));

View File

@ -128,11 +128,12 @@ macro_rules! match_integers_span {
macro_rules! allocate_type {
($rust_ty:ty, $gadget_ty:ty, $leo_ty:path, $cs:expr, $name:expr, $option:expr, $span:expr) => {{
let option = $option.map(|s| {
s.parse::<$rust_ty>()
.map_err(|_| IntegerError::invalid_integer(s, $span))
.unwrap()
});
let option = $option
.map(|s| {
s.parse::<$rust_ty>()
.map_err(|_| IntegerError::invalid_integer(s, $span))
})
.transpose()?;
let result = <$gadget_ty>::alloc(
$cs.ns(|| {

View File

@ -20,7 +20,7 @@ use crate::{
expressions::{ArrayInlineExpression, Expression},
sections::Header,
tables::Table,
types::{DataType, Type},
types::{DataType, IntegerType, Type},
values::{NumberValue, Value},
};
@ -83,6 +83,12 @@ impl InputParserError {
Self::new_from_span(message, span)
}
pub fn integer_type_mismatch(expected: IntegerType, received: IntegerType, span: &Span) -> Self {
let message = format!("expected data type `{}`, found `{}`", expected, received);
Self::new_from_span(message, span)
}
pub fn invalid_char(character: String, span: &Span) -> Self {
let message = format!("Expected valid character found `{}`", character);

View File

@ -0,0 +1,11 @@
/*
namespace: Compile
expectation: Fail
input_file: input/different_types_signed_fail.in
input_file: input/different_types_const_signed_fail.in
input_file: input/main_fail_type.in
*/
function main(const a: i32) {
let b = a * 2;
}

View File

@ -0,0 +1,11 @@
/*
namespace: Compile
expectation: Fail
input_file: input/different_types_const_unsigned_fail.in
input_file: input/different_types_unsigned_fail.in
input_file: input/main_fail_type.in
*/
function main(const a: u32) {
let b = a * 2;
}

View File

@ -0,0 +1,11 @@
/*
namespace: Compile
expectation: Fail
input_file: input/different_types_signed_fail.in
input_file: input/different_types_const_signed_fail.in
input_file: input/var_in_both_sections_fail.in
*/
function main(a: i32) {
let b = a * 2;
}

View File

@ -0,0 +1,11 @@
/*
namespace: Compile
expectation: Fail
input_file: input/different_types_const_unsigned_fail.in
input_file: input/different_types_unsigned_fail.in
input_file: input/var_in_both_sections_fail.in
*/
function main(a: u32) {
let b = a * 2;
}

View File

@ -0,0 +1,2 @@
[constants]
a: i32 = 2i8;

View File

@ -0,0 +1,2 @@
[main]
a: i32 = 2i8;

View File

@ -0,0 +1,2 @@
[constants]
a: u32 = 2u8;

View File

@ -0,0 +1,2 @@
[main]
a: u32 = 2u8;

View File

@ -0,0 +1,5 @@
[main]
a: u32 = 2u32;
[constants]
a: u32 = 2u32;

View File

@ -1,5 +1,5 @@
[main]
a: [[u8; 4]; 2] = [[0u64, 0u64, 0u64, 0u64], [0u64, 0u64, 0u64, 0u64]];
a: [[u8; 4]; 2] = [[0u8, 0u8, 0u8, 0u8], [0u8, 0u8, 0u8, 0u8]];
[registers]
r2: [[u8; 4]; 2] = [[0u64, 0u64, 0u64, 0u64], [0u64, 0u64, 0u64, 0u64]];
r2: [[u8; 4]; 2] = [[0u8, 0u8, 0u8, 0u8], [0u8, 0u8, 0u8, 0u8]];

View File

@ -0,0 +1,10 @@
/*
namespace: Compile
expectation: Fail
inputs:
- u128.in: |
[main]
a: u128 = -2;
*/
function main(a: u128) {}

View File

@ -0,0 +1,10 @@
/*
namespace: Compile
expectation: Fail
inputs:
- u16.in: |
[main]
a: u16 = -2;
*/
function main(a: u16) {}

View File

@ -0,0 +1,10 @@
/*
namespace: Compile
expectation: Fail
inputs:
- u32.in: |
[main]
a: u32 = -2;
*/
function main(a: u32) {}

View File

@ -0,0 +1,10 @@
/*
namespace: Compile
expectation: Fail
inputs:
- u64.in: |
[main]
a: u64 = -2;
*/
function main(a: u64) {}

View File

@ -0,0 +1,10 @@
/*
namespace: Compile
expectation: Fail
inputs:
- u8.in: |
[main]
a: u8 = -2;
*/
function main(a: u8) {}

View File

@ -0,0 +1,5 @@
---
namespace: Compile
expectation: Fail
outputs:
- " --> compiler-test:3:21\n |\n 3 | function main(const a: i32) {\n | ^\n |\n = Expected input variable `a` to be constant. Move input variable `a` to [constants] section of input file"

View File

@ -0,0 +1,5 @@
---
namespace: Compile
expectation: Fail
outputs:
- " --> compiler-test:3:21\n |\n 3 | function main(const a: u32) {\n | ^\n |\n = Expected input variable `a` to be constant. Move input variable `a` to [constants] section of input file"

View File

@ -0,0 +1,5 @@
---
namespace: Compile
expectation: Fail
outputs:
- " --> compiler-test:3:15\n |\n 3 | function main(a: u32) {\n | ^\n |\n = expected data type `u32`, found `u8`"

View File

@ -0,0 +1,5 @@
---
namespace: Compile
expectation: Fail
outputs:
- " --> compiler-test:3:15\n |\n 3 | function main(a: i32) {\n | ^\n |\n = Input variable a declared twice"

View File

@ -0,0 +1,5 @@
---
namespace: Compile
expectation: Fail
outputs:
- " --> compiler-test:3:15\n |\n 3 | function main(a: u32) {\n | ^\n |\n = Input variable a declared twice"

View File

@ -2,4 +2,4 @@
namespace: Compile
expectation: Fail
outputs:
- " --> compiler-test:3:1\n |\n 3 | function main(x: [i16; 2]) {\n 4 | ...\n 5 | }\n | ^\n |\n = Input array dimensions mismatch expected 1, found array dimensions 2"
- " --> compiler-test:3:15\n |\n 3 | function main(x: [i16; 2]) {\n | ^\n |\n = Input array dimensions mismatch expected 1, found array dimensions 2"

View File

@ -2,4 +2,4 @@
namespace: Compile
expectation: Fail
outputs:
- " --> compiler-test:3:1\n |\n 3 | function main(x: (u8, bool, u8)) {\n 4 | ...\n 5 | }\n | ^\n |\n = Input tuple size mismatch expected 3, found tuple with length 2"
- " --> compiler-test:3:15\n |\n 3 | function main(x: (u8, bool, u8)) {\n | ^\n |\n = Input tuple size mismatch expected 3, found tuple with length 2"

View File

@ -2,4 +2,4 @@
namespace: Compile
expectation: Fail
outputs:
- " --> compiler-test:3:1\n |\n 3 | function main(const x: [i16; 2]) {\n 4 | ...\n 5 | }\n | ^\n |\n = Input array dimensions mismatch expected 2, found array dimensions 1"
- " --> compiler-test:3:21\n |\n 3 | function main(const x: [i16; 2]) {\n | ^\n |\n = Input array dimensions mismatch expected 2, found array dimensions 1"

View File

@ -2,4 +2,4 @@
namespace: Compile
expectation: Fail
outputs:
- " --> compiler-test:3:1\n |\n 3 | function main(const x: (u8, bool, u8)) {\n 4 | ...\n 5 | }\n | ^\n |\n = Input tuple size mismatch expected 3, found tuple with length 2"
- " --> compiler-test:3:21\n |\n 3 | function main(const x: (u8, bool, u8)) {\n | ^\n |\n = Input tuple size mismatch expected 3, found tuple with length 2"

View File

@ -0,0 +1,5 @@
---
namespace: Compile
expectation: Fail
outputs:
- " --> compiler-test:3:15\n |\n 3 | function main(a: u128) {}\n | ^\n |\n = failed to parse `-2` as expected integer type"

View File

@ -0,0 +1,5 @@
---
namespace: Compile
expectation: Fail
outputs:
- " --> compiler-test:3:15\n |\n 3 | function main(a: u16) {}\n | ^\n |\n = failed to parse `-2` as expected integer type"

View File

@ -0,0 +1,5 @@
---
namespace: Compile
expectation: Fail
outputs:
- " --> compiler-test:3:15\n |\n 3 | function main(a: u32) {}\n | ^\n |\n = failed to parse `-2` as expected integer type"

View File

@ -0,0 +1,5 @@
---
namespace: Compile
expectation: Fail
outputs:
- " --> compiler-test:3:15\n |\n 3 | function main(a: u64) {}\n | ^\n |\n = failed to parse `-2` as expected integer type"

View File

@ -0,0 +1,5 @@
---
namespace: Compile
expectation: Fail
outputs:
- " --> compiler-test:3:15\n |\n 3 | function main(a: u8) {}\n | ^\n |\n = failed to parse `-2` as expected integer type"