mirror of
https://github.com/AleoHQ/leo.git
synced 2024-12-24 10:01:40 +03:00
Merge pull request #1837 from AleoHQ/type-checking-bug-fixes
[Fix] Type checking bug fixes
This commit is contained in:
commit
d43605538d
@ -151,11 +151,11 @@ impl Emitter for BufferEmitter {
|
|||||||
self.0.borrow_mut().push(LeoOrString::Leo(err));
|
self.0.borrow_mut().push(LeoOrString::Leo(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn last_emited_err(&self) -> Option<LeoError> {
|
fn last_emitted_err_code(&self) -> Option<i32> {
|
||||||
let temp = &*self.0.borrow();
|
let temp = &*self.0.borrow();
|
||||||
temp.last_entry().map(|entry| match entry {
|
temp.last_entry().map(|entry| match entry {
|
||||||
LeoOrString::Leo(err) => err.clone(),
|
LeoOrString::Leo(err) => err.exit_code(),
|
||||||
_ => unimplemented!(),
|
_ => 0,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +58,6 @@ impl<'a> TypeChecker<'a> {
|
|||||||
match type_ {
|
match type_ {
|
||||||
IntegerType::I8 => {
|
IntegerType::I8 => {
|
||||||
let int = if self.negate {
|
let int = if self.negate {
|
||||||
self.negate = false;
|
|
||||||
format!("-{str_content}")
|
format!("-{str_content}")
|
||||||
} else {
|
} else {
|
||||||
str_content.clone()
|
str_content.clone()
|
||||||
@ -71,7 +70,6 @@ impl<'a> TypeChecker<'a> {
|
|||||||
}
|
}
|
||||||
IntegerType::I16 => {
|
IntegerType::I16 => {
|
||||||
let int = if self.negate {
|
let int = if self.negate {
|
||||||
self.negate = false;
|
|
||||||
format!("-{str_content}")
|
format!("-{str_content}")
|
||||||
} else {
|
} else {
|
||||||
str_content.clone()
|
str_content.clone()
|
||||||
@ -84,7 +82,6 @@ impl<'a> TypeChecker<'a> {
|
|||||||
}
|
}
|
||||||
IntegerType::I32 => {
|
IntegerType::I32 => {
|
||||||
let int = if self.negate {
|
let int = if self.negate {
|
||||||
self.negate = false;
|
|
||||||
format!("-{str_content}")
|
format!("-{str_content}")
|
||||||
} else {
|
} else {
|
||||||
str_content.clone()
|
str_content.clone()
|
||||||
@ -97,7 +94,6 @@ impl<'a> TypeChecker<'a> {
|
|||||||
}
|
}
|
||||||
IntegerType::I64 => {
|
IntegerType::I64 => {
|
||||||
let int = if self.negate {
|
let int = if self.negate {
|
||||||
self.negate = false;
|
|
||||||
format!("-{str_content}")
|
format!("-{str_content}")
|
||||||
} else {
|
} else {
|
||||||
str_content.clone()
|
str_content.clone()
|
||||||
@ -110,7 +106,6 @@ impl<'a> TypeChecker<'a> {
|
|||||||
}
|
}
|
||||||
IntegerType::I128 => {
|
IntegerType::I128 => {
|
||||||
let int = if self.negate {
|
let int = if self.negate {
|
||||||
self.negate = false;
|
|
||||||
format!("-{str_content}")
|
format!("-{str_content}")
|
||||||
} else {
|
} else {
|
||||||
str_content.clone()
|
str_content.clone()
|
||||||
@ -121,7 +116,6 @@ impl<'a> TypeChecker<'a> {
|
|||||||
.emit_err(TypeCheckerError::invalid_int_value(int, "i128", value.span()).into());
|
.emit_err(TypeCheckerError::invalid_int_value(int, "i128", value.span()).into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IntegerType::U8 if str_content.parse::<u8>().is_err() => self
|
IntegerType::U8 if str_content.parse::<u8>().is_err() => self
|
||||||
.handler
|
.handler
|
||||||
.emit_err(TypeCheckerError::invalid_int_value(str_content, "u8", value.span()).into()),
|
.emit_err(TypeCheckerError::invalid_int_value(str_content, "u8", value.span()).into()),
|
||||||
@ -175,11 +169,21 @@ impl<'a> TypeChecker<'a> {
|
|||||||
|
|
||||||
// Allow `group` * `scalar` multiplication.
|
// Allow `group` * `scalar` multiplication.
|
||||||
match (t1.as_ref(), t2.as_ref()) {
|
match (t1.as_ref(), t2.as_ref()) {
|
||||||
(Some(Type::Group), Some(other)) | (Some(other), Some(Type::Group)) => {
|
(Some(Type::Group), Some(other)) => {
|
||||||
|
self.assert_type(Type::Group, expected, binary.left.span());
|
||||||
self.assert_type(*other, Some(Type::Scalar), binary.span());
|
self.assert_type(*other, Some(Type::Scalar), binary.span());
|
||||||
Some(Type::Group)
|
Some(Type::Group)
|
||||||
}
|
}
|
||||||
_ => return_incorrect_type(t1, t2, expected),
|
(Some(other), Some(Type::Group)) => {
|
||||||
|
self.assert_type(Type::Group, expected, binary.right.span());
|
||||||
|
self.assert_type(*other, Some(Type::Scalar), binary.span());
|
||||||
|
Some(Type::Group)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
self.assert_type(t1.unwrap(), expected, binary.left.span());
|
||||||
|
self.assert_type(t2.unwrap(), expected, binary.right.span());
|
||||||
|
return_incorrect_type(t1, t2, expected)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BinaryOperation::Div => {
|
BinaryOperation::Div => {
|
||||||
@ -230,23 +234,23 @@ impl<'a> TypeChecker<'a> {
|
|||||||
t1
|
t1
|
||||||
}
|
}
|
||||||
BinaryOperation::Eq | BinaryOperation::Ne => {
|
BinaryOperation::Eq | BinaryOperation::Ne => {
|
||||||
self.assert_type(Type::Boolean, expected, binary.span());
|
|
||||||
|
|
||||||
let t1 = self.compare_expr_type(&binary.left, None, binary.left.span());
|
let t1 = self.compare_expr_type(&binary.left, None, binary.left.span());
|
||||||
let t2 = self.compare_expr_type(&binary.right, None, binary.right.span());
|
let t2 = self.compare_expr_type(&binary.right, None, binary.right.span());
|
||||||
|
|
||||||
return_incorrect_type(t1, t2, expected)
|
self.assert_eq_types(t1, t2, binary.span());
|
||||||
|
|
||||||
|
Some(Type::Boolean)
|
||||||
}
|
}
|
||||||
BinaryOperation::Lt | BinaryOperation::Gt | BinaryOperation::Le | BinaryOperation::Ge => {
|
BinaryOperation::Lt | BinaryOperation::Gt | BinaryOperation::Le | BinaryOperation::Ge => {
|
||||||
self.assert_type(Type::Boolean, expected, binary.span());
|
|
||||||
|
|
||||||
let t1 = self.compare_expr_type(&binary.left, None, binary.left.span());
|
let t1 = self.compare_expr_type(&binary.left, None, binary.left.span());
|
||||||
self.assert_field_scalar_int_type(t1, binary.left.span());
|
self.assert_field_scalar_int_type(t1, binary.left.span());
|
||||||
|
|
||||||
let t2 = self.compare_expr_type(&binary.right, None, binary.right.span());
|
let t2 = self.compare_expr_type(&binary.right, None, binary.right.span());
|
||||||
self.assert_field_scalar_int_type(t2, binary.right.span());
|
self.assert_field_scalar_int_type(t2, binary.right.span());
|
||||||
|
|
||||||
return_incorrect_type(t1, t2, expected)
|
self.assert_eq_types(t1, t2, binary.span());
|
||||||
|
|
||||||
|
Some(Type::Boolean)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Expression::Unary(unary) => match unary.op {
|
Expression::Unary(unary) => match unary.op {
|
||||||
@ -255,7 +259,11 @@ impl<'a> TypeChecker<'a> {
|
|||||||
self.compare_expr_type(&unary.inner, expected, unary.inner.span())
|
self.compare_expr_type(&unary.inner, expected, unary.inner.span())
|
||||||
}
|
}
|
||||||
UnaryOperation::Negate => {
|
UnaryOperation::Negate => {
|
||||||
match expected.as_ref() {
|
let prior_negate_state = self.negate;
|
||||||
|
self.negate = true;
|
||||||
|
let type_ = self.compare_expr_type(&unary.inner, expected, unary.inner.span());
|
||||||
|
self.negate = prior_negate_state;
|
||||||
|
match type_.as_ref() {
|
||||||
Some(
|
Some(
|
||||||
Type::IntegerType(
|
Type::IntegerType(
|
||||||
IntegerType::I8
|
IntegerType::I8
|
||||||
@ -266,13 +274,13 @@ impl<'a> TypeChecker<'a> {
|
|||||||
)
|
)
|
||||||
| Type::Field
|
| Type::Field
|
||||||
| Type::Group,
|
| Type::Group,
|
||||||
) => self.negate = !self.negate,
|
) => {}
|
||||||
Some(t) => self
|
Some(t) => self
|
||||||
.handler
|
.handler
|
||||||
.emit_err(TypeCheckerError::type_is_not_negatable(t, unary.inner.span()).into()),
|
.emit_err(TypeCheckerError::type_is_not_negatable(t, unary.inner.span()).into()),
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
self.compare_expr_type(&unary.inner, expected, unary.inner.span())
|
type_
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Expression::Ternary(ternary) => {
|
Expression::Ternary(ternary) => {
|
||||||
|
@ -77,6 +77,19 @@ impl<'a> TypeChecker<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Emits an error if the two given types are not equal.
|
||||||
|
pub(crate) fn assert_eq_types(&self, t1: Option<Type>, t2: Option<Type>, span: Span) {
|
||||||
|
match (t1, t2) {
|
||||||
|
(Some(t1), Some(t2)) if t1 != t2 => self
|
||||||
|
.handler
|
||||||
|
.emit_err(TypeCheckerError::type_should_be(t1, t2, span).into()),
|
||||||
|
(Some(type_), None) | (None, Some(type_)) => self
|
||||||
|
.handler
|
||||||
|
.emit_err(TypeCheckerError::type_should_be("no type", type_, span).into()),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the given type if it equals the expected type or the expected type is none.
|
/// Returns the given type if it equals the expected type or the expected type is none.
|
||||||
pub(crate) fn assert_type(&self, type_: Type, expected: Option<Type>, span: Span) -> Type {
|
pub(crate) fn assert_type(&self, type_: Type, expected: Option<Type>, span: Span) -> Type {
|
||||||
if let Some(expected) = expected {
|
if let Some(expected) = expected {
|
||||||
|
@ -38,8 +38,6 @@ impl<'a> Pass<'a> for TypeChecker<'a> {
|
|||||||
fn do_pass((ast, symbol_table, handler): Self::Input) -> Self::Output {
|
fn do_pass((ast, symbol_table, handler): Self::Input) -> Self::Output {
|
||||||
let mut visitor = VisitorDirector::new(TypeChecker::new(symbol_table, handler));
|
let mut visitor = VisitorDirector::new(TypeChecker::new(symbol_table, handler));
|
||||||
visitor.visit_program(ast.as_repr());
|
visitor.visit_program(ast.as_repr());
|
||||||
// todo @gluax: awkward cause last error double prints...
|
|
||||||
// but can't os exit or it causes tests to stop.
|
|
||||||
handler.last_err()?;
|
handler.last_err()?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
BIN
docs/grammar/README.md
Normal file
BIN
docs/grammar/README.md
Normal file
Binary file not shown.
@ -27,8 +27,8 @@ pub trait Emitter {
|
|||||||
/// Emit the error `err`.
|
/// Emit the error `err`.
|
||||||
fn emit_err(&mut self, err: LeoError);
|
fn emit_err(&mut self, err: LeoError);
|
||||||
|
|
||||||
/// Tracks last emmited error.
|
/// Tracks last emitted error.
|
||||||
fn last_emited_err(&self) -> Option<LeoError>;
|
fn last_emitted_err_code(&self) -> Option<i32>;
|
||||||
|
|
||||||
/// Emit the warning.
|
/// Emit the warning.
|
||||||
fn emit_warning(&mut self, warning: LeoWarning);
|
fn emit_warning(&mut self, warning: LeoWarning);
|
||||||
@ -36,18 +36,18 @@ pub trait Emitter {
|
|||||||
|
|
||||||
/// A trivial `Emitter` using the standard error.
|
/// A trivial `Emitter` using the standard error.
|
||||||
pub struct StderrEmitter {
|
pub struct StderrEmitter {
|
||||||
/// The last emitted error.
|
/// Exit code of the last emitted error.
|
||||||
last_error: Option<LeoError>,
|
last_error_code: Option<i32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Emitter for StderrEmitter {
|
impl Emitter for StderrEmitter {
|
||||||
fn emit_err(&mut self, err: LeoError) {
|
fn emit_err(&mut self, err: LeoError) {
|
||||||
self.last_error = Some(err.clone());
|
self.last_error_code = Some(err.exit_code());
|
||||||
eprintln!("{}", err);
|
eprintln!("{}", err);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn last_emited_err(&self) -> Option<LeoError> {
|
fn last_emitted_err_code(&self) -> Option<i32> {
|
||||||
self.last_error.clone()
|
self.last_error_code
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_warning(&mut self, warning: LeoWarning) {
|
fn emit_warning(&mut self, warning: LeoWarning) {
|
||||||
@ -126,9 +126,9 @@ impl Emitter for BufferEmitter {
|
|||||||
self.0.borrow_mut().push(err);
|
self.0.borrow_mut().push(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn last_emited_err(&self) -> Option<LeoError> {
|
fn last_emitted_err_code(&self) -> Option<i32> {
|
||||||
let temp = &*self.0.borrow();
|
let temp = &*self.0.borrow();
|
||||||
temp.last_entry().cloned()
|
temp.last_entry().map(|entry| entry.exit_code())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_warning(&mut self, warning: LeoWarning) {
|
fn emit_warning(&mut self, warning: LeoWarning) {
|
||||||
@ -155,8 +155,8 @@ impl HandlerInner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the last emitted error's exit code.
|
/// Gets the last emitted error's exit code.
|
||||||
fn last_emited_err(&self) -> Option<LeoError> {
|
fn last_emited_err_code(&self) -> Option<i32> {
|
||||||
self.emitter.last_emited_err()
|
self.emitter.last_emitted_err_code()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Emit the error `err`.
|
/// Emit the error `err`.
|
||||||
@ -175,7 +175,7 @@ pub struct Handler {
|
|||||||
|
|
||||||
impl Default for Handler {
|
impl Default for Handler {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::new(Box::new(StderrEmitter { last_error: None }))
|
Self::new(Box::new(StderrEmitter { last_error_code: None }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,8 +240,8 @@ impl Handler {
|
|||||||
/// Gets the last emitted error's exit code if it exists.
|
/// Gets the last emitted error's exit code if it exists.
|
||||||
/// Then exits the program with it if it did exist.
|
/// Then exits the program with it if it did exist.
|
||||||
pub fn last_err(&self) -> Result<(), LeoError> {
|
pub fn last_err(&self) -> Result<(), LeoError> {
|
||||||
if let Some(code) = self.inner.borrow().last_emited_err() {
|
if let Some(code) = self.inner.borrow().last_emited_err_code() {
|
||||||
Err(code)
|
Err(LeoError::LastErrorCode(code))
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -70,6 +70,10 @@ pub enum LeoError {
|
|||||||
/// Represents an Type Checker Error in a Leo Error.
|
/// Represents an Type Checker Error in a Leo Error.
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
TypeCheckerError(#[from] TypeCheckerError),
|
TypeCheckerError(#[from] TypeCheckerError),
|
||||||
|
/// Purely for just exiting with the correct status code and
|
||||||
|
/// not re-displaying an error.
|
||||||
|
#[error("")]
|
||||||
|
LastErrorCode(i32),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LeoError {
|
impl LeoError {
|
||||||
@ -85,6 +89,7 @@ impl LeoError {
|
|||||||
ParserError(error) => error.error_code(),
|
ParserError(error) => error.error_code(),
|
||||||
PackageError(error) => error.error_code(),
|
PackageError(error) => error.error_code(),
|
||||||
TypeCheckerError(error) => error.error_code(),
|
TypeCheckerError(error) => error.error_code(),
|
||||||
|
LastErrorCode(_) => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,6 +105,7 @@ impl LeoError {
|
|||||||
ParserError(error) => error.exit_code(),
|
ParserError(error) => error.exit_code(),
|
||||||
PackageError(error) => error.exit_code(),
|
PackageError(error) => error.exit_code(),
|
||||||
TypeCheckerError(error) => error.exit_code(),
|
TypeCheckerError(error) => error.exit_code(),
|
||||||
|
LastErrorCode(code) => *code,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,5 +6,7 @@ input_file: ../inputs/dummy.in
|
|||||||
|
|
||||||
function main(y: bool) -> bool {
|
function main(y: bool) -> bool {
|
||||||
const a: i8 = -128i8;
|
const a: i8 = -128i8;
|
||||||
return y == true;
|
let z: bool = a == -128i8;
|
||||||
|
|
||||||
|
return z == true;
|
||||||
}
|
}
|
||||||
|
16
tests/compiler/statements/compare_diff_types_fail.leo
Normal file
16
tests/compiler/statements/compare_diff_types_fail.leo
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
namespace: Compile
|
||||||
|
expectation: Fail
|
||||||
|
input_file: inputs/i8.in
|
||||||
|
*/
|
||||||
|
|
||||||
|
function main(a: i8) -> bool {
|
||||||
|
let b: bool = a == 1u8;
|
||||||
|
let c: bool = a != 1u8;
|
||||||
|
let d: bool = a > 1u8;
|
||||||
|
let e: bool = a < 1u8;
|
||||||
|
let f: bool = a >= 1u8;
|
||||||
|
let g: bool = a <= 1u8;
|
||||||
|
let h: u32 = a * 1u8;
|
||||||
|
return b;
|
||||||
|
}
|
16
tests/compiler/statements/compare_invalid_negates_fail.leo
Normal file
16
tests/compiler/statements/compare_invalid_negates_fail.leo
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
namespace: Compile
|
||||||
|
expectation: Fail
|
||||||
|
input_file: inputs/u8.in
|
||||||
|
*/
|
||||||
|
|
||||||
|
function main(a: u8) -> bool {
|
||||||
|
let b: bool = -a == -1u8;
|
||||||
|
let c: bool = -a > -1u8;
|
||||||
|
let d: bool = -a < -1u8;
|
||||||
|
let e: bool = -a >= -1u8;
|
||||||
|
let f: bool = -a <= -1u8;
|
||||||
|
let g: u8 = -a * -1u8;
|
||||||
|
let h: u8 = -a ** -1u8;
|
||||||
|
return b;
|
||||||
|
}
|
5
tests/compiler/statements/inputs/i8.in
Normal file
5
tests/compiler/statements/inputs/i8.in
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
[main]
|
||||||
|
a: i8 = 1i8;
|
||||||
|
|
||||||
|
[registers]
|
||||||
|
r0: bool = true;
|
5
tests/compiler/statements/inputs/u8.in
Normal file
5
tests/compiler/statements/inputs/u8.in
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
[main]
|
||||||
|
a: u8 = 1u8;
|
||||||
|
|
||||||
|
[registers]
|
||||||
|
r0: bool = true;
|
@ -2,4 +2,4 @@
|
|||||||
namespace: Compile
|
namespace: Compile
|
||||||
expectation: Fail
|
expectation: Fail
|
||||||
outputs:
|
outputs:
|
||||||
- "Error [EAST0372014]: function `main` shadowed\n --> compiler-test:3:1\n |\n 3 | function main(y: bool) -> bool {\n 4 | console.log(\"{}\", 1u8);\n 5 | return y;\n 6 | }\n | ^\nError [EAST0372014]: function `main` shadowed\n --> compiler-test:3:1\n |\n 3 | function main(y: bool) -> bool {\n 4 | console.log(\"{}\", 1u8);\n 5 | return y;\n 6 | }\n | ^"
|
- "Error [EAST0372014]: function `main` shadowed\n --> compiler-test:3:1\n |\n 3 | function main(y: bool) -> bool {\n 4 | console.log(\"{}\", 1u8);\n 5 | return y;\n 6 | }\n | ^\n"
|
||||||
|
@ -2,4 +2,4 @@
|
|||||||
namespace: Compile
|
namespace: Compile
|
||||||
expectation: Fail
|
expectation: Fail
|
||||||
outputs:
|
outputs:
|
||||||
- "Error [EAST0372015]: variable `a` shadowed\n --> compiler-test:3:15\n |\n 3 | function main(a: u32, a: u32) -> u32 {\n | ^\nError [EAST0372015]: variable `a` shadowed\n --> compiler-test:3:15\n |\n 3 | function main(a: u32, a: u32) -> u32 {\n | ^"
|
- "Error [EAST0372015]: variable `a` shadowed\n --> compiler-test:3:15\n |\n 3 | function main(a: u32, a: u32) -> u32 {\n | ^\n"
|
||||||
|
@ -2,4 +2,4 @@
|
|||||||
namespace: Compile
|
namespace: Compile
|
||||||
expectation: Fail
|
expectation: Fail
|
||||||
outputs:
|
outputs:
|
||||||
- "Error [EAST0372014]: function `hi` shadowed\n --> compiler-test:3:1\n |\n 3 | function hi() -> u8 {\n 4 | return 0u8;\n 5 | }\n | ^\nError [EAST0372014]: function `hi` shadowed\n --> compiler-test:3:1\n |\n 3 | function hi() -> u8 {\n 4 | return 0u8;\n 5 | }\n | ^"
|
- "Error [EAST0372014]: function `hi` shadowed\n --> compiler-test:3:1\n |\n 3 | function hi() -> u8 {\n 4 | return 0u8;\n 5 | }\n | ^\n"
|
||||||
|
@ -2,4 +2,4 @@
|
|||||||
namespace: Compile
|
namespace: Compile
|
||||||
expectation: Fail
|
expectation: Fail
|
||||||
outputs:
|
outputs:
|
||||||
- "Error [ETYC0372002]: Found type `group` but type `scalar` was expected\n --> compiler-test:4:12\n |\n 4 | return (_, _)group * a;\n | ^^^^^^^^^^^^^^^\nError [ETYC0372002]: Found type `group` but type `scalar` was expected\n --> compiler-test:4:12\n |\n 4 | return (_, _)group * a;\n | ^^^^^^^^^^^^^^^"
|
- "Error [ETYC0372002]: Found type `group` but type `scalar` was expected\n --> compiler-test:4:12\n |\n 4 | return (_, _)group * a;\n | ^^^^^^^^^^^^^^^\n"
|
||||||
|
@ -2,4 +2,4 @@
|
|||||||
namespace: Compile
|
namespace: Compile
|
||||||
expectation: Fail
|
expectation: Fail
|
||||||
outputs:
|
outputs:
|
||||||
- "Error [ETYC0372009]: The second operand must be a unsigned int but got type `i128`\n --> compiler-test:4:17\n |\n 4 | return a ** b == c;\n | ^\nError [ETYC0372009]: The second operand must be a unsigned int but got type `i128`\n --> compiler-test:4:17\n |\n 4 | return a ** b == c;\n | ^"
|
- "Error [ETYC0372009]: The second operand must be a unsigned int but got type `i128`\n --> compiler-test:4:17\n |\n 4 | return a ** b == c;\n | ^\n"
|
||||||
|
@ -2,4 +2,4 @@
|
|||||||
namespace: Compile
|
namespace: Compile
|
||||||
expectation: Fail
|
expectation: Fail
|
||||||
outputs:
|
outputs:
|
||||||
- "Error [ETYC0372009]: The second operand must be a unsigned int but got type `i16`\n --> compiler-test:4:17\n |\n 4 | return a ** b == c;\n | ^\nError [ETYC0372009]: The second operand must be a unsigned int but got type `i16`\n --> compiler-test:4:17\n |\n 4 | return a ** b == c;\n | ^"
|
- "Error [ETYC0372009]: The second operand must be a unsigned int but got type `i16`\n --> compiler-test:4:17\n |\n 4 | return a ** b == c;\n | ^\n"
|
||||||
|
@ -2,4 +2,4 @@
|
|||||||
namespace: Compile
|
namespace: Compile
|
||||||
expectation: Fail
|
expectation: Fail
|
||||||
outputs:
|
outputs:
|
||||||
- "Error [ETYC0372009]: The second operand must be a unsigned int but got type `i32`\n --> compiler-test:4:17\n |\n 4 | return a ** b == c;\n | ^\nError [ETYC0372009]: The second operand must be a unsigned int but got type `i32`\n --> compiler-test:4:17\n |\n 4 | return a ** b == c;\n | ^"
|
- "Error [ETYC0372009]: The second operand must be a unsigned int but got type `i32`\n --> compiler-test:4:17\n |\n 4 | return a ** b == c;\n | ^\n"
|
||||||
|
@ -2,4 +2,4 @@
|
|||||||
namespace: Compile
|
namespace: Compile
|
||||||
expectation: Fail
|
expectation: Fail
|
||||||
outputs:
|
outputs:
|
||||||
- "Error [ETYC0372009]: The second operand must be a unsigned int but got type `i64`\n --> compiler-test:4:17\n |\n 4 | return a ** b == c;\n | ^\nError [ETYC0372009]: The second operand must be a unsigned int but got type `i64`\n --> compiler-test:4:17\n |\n 4 | return a ** b == c;\n | ^"
|
- "Error [ETYC0372009]: The second operand must be a unsigned int but got type `i64`\n --> compiler-test:4:17\n |\n 4 | return a ** b == c;\n | ^\n"
|
||||||
|
@ -3,6 +3,6 @@ namespace: Compile
|
|||||||
expectation: Pass
|
expectation: Pass
|
||||||
outputs:
|
outputs:
|
||||||
- output:
|
- output:
|
||||||
- initial_input_ast: 43adaa31f572639c8ac2fc8547f0f3792c051b0c20e1806a11c549431afa749a
|
- initial_input_ast: a21868246c36e4325607d5efb14d1f8b85fac3cca07e97a27849863fe3c0ca1e
|
||||||
initial_ast: b2f87cded036964dbfdedee647b26b7e6e9f600da79e28d97e0bb37989d626dd
|
initial_ast: 6fba3601e8a6a4cb317fcc0e8eee97d31d2be8ac384e0ae6a3600a08b08650cd
|
||||||
symbol_table: 98cceb8df5e7a49587ca9cd0c728a7ae7d31f69b41541d3f2463315c75d825eb
|
symbol_table: 35d1e1f443565f02abe479bd9778bdf8a25ec934b5777b6419cf5d6557f0b2e3
|
||||||
|
@ -2,4 +2,4 @@
|
|||||||
namespace: Compile
|
namespace: Compile
|
||||||
expectation: Fail
|
expectation: Fail
|
||||||
outputs:
|
outputs:
|
||||||
- "Error [ETYC0372009]: The second operand must be a unsigned int but got type `i8`\n --> compiler-test:4:17\n |\n 4 | return a ** b == c;\n | ^\nError [ETYC0372009]: The second operand must be a unsigned int but got type `i8`\n --> compiler-test:4:17\n |\n 4 | return a ** b == c;\n | ^"
|
- "Error [ETYC0372009]: The second operand must be a unsigned int but got type `i8`\n --> compiler-test:4:17\n |\n 4 | return a ** b == c;\n | ^\n"
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
namespace: Compile
|
||||||
|
expectation: Fail
|
||||||
|
outputs:
|
||||||
|
- "Error [ETYC0372002]: Found type `i8` but type `u8` was expected\n --> compiler-test:4:19\n |\n 4 | let b: bool = a == 1u8;\n | ^^^^^^^^\nError [ETYC0372002]: Found type `i8` but type `u8` was expected\n --> compiler-test:5:19\n |\n 5 | let c: bool = a != 1u8;\n | ^^^^^^^^\nError [ETYC0372002]: Found type `i8` but type `u8` was expected\n --> compiler-test:6:19\n |\n 6 | let d: bool = a > 1u8;\n | ^^^^^^^\nError [ETYC0372002]: Found type `i8` but type `u8` was expected\n --> compiler-test:7:19\n |\n 7 | let e: bool = a < 1u8;\n | ^^^^^^^\nError [ETYC0372002]: Found type `i8` but type `u8` was expected\n --> compiler-test:8:19\n |\n 8 | let f: bool = a >= 1u8;\n | ^^^^^^^^\nError [ETYC0372002]: Found type `i8` but type `u8` was expected\n --> compiler-test:9:19\n |\n 9 | let g: bool = a <= 1u8;\n | ^^^^^^^^\nError [ETYC0372002]: Found type `i8` but type `u32` was expected\n --> compiler-test:10:18\n |\n 10 | let h: u32 = a * 1u8;\n | ^\nError [ETYC0372002]: Found type `u8` but type `u32` was expected\n --> compiler-test:10:22\n |\n 10 | let h: u32 = a * 1u8;\n | ^^^\n"
|
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
namespace: Compile
|
||||||
|
expectation: Fail
|
||||||
|
outputs:
|
||||||
|
- "Error [ETYC0372005]: The type `u8` is not negatable\n --> compiler-test:4:20\n |\n 4 | let b: bool = -a == -1u8;\n | ^\nError [ETYC0372005]: The type `u8` is not negatable\n --> compiler-test:4:26\n |\n 4 | let b: bool = -a == -1u8;\n | ^^^\nError [ETYC0372005]: The type `u8` is not negatable\n --> compiler-test:5:20\n |\n 5 | let c: bool = -a > -1u8;\n | ^\nError [ETYC0372005]: The type `u8` is not negatable\n --> compiler-test:5:25\n |\n 5 | let c: bool = -a > -1u8;\n | ^^^\nError [ETYC0372005]: The type `u8` is not negatable\n --> compiler-test:6:20\n |\n 6 | let d: bool = -a < -1u8;\n | ^\nError [ETYC0372005]: The type `u8` is not negatable\n --> compiler-test:6:25\n |\n 6 | let d: bool = -a < -1u8;\n | ^^^\nError [ETYC0372005]: The type `u8` is not negatable\n --> compiler-test:7:20\n |\n 7 | let e: bool = -a >= -1u8;\n | ^\nError [ETYC0372005]: The type `u8` is not negatable\n --> compiler-test:7:26\n |\n 7 | let e: bool = -a >= -1u8;\n | ^^^\nError [ETYC0372005]: The type `u8` is not negatable\n --> compiler-test:8:20\n |\n 8 | let f: bool = -a <= -1u8;\n | ^\nError [ETYC0372005]: The type `u8` is not negatable\n --> compiler-test:8:26\n |\n 8 | let f: bool = -a <= -1u8;\n | ^^^\nError [ETYC0372005]: The type `u8` is not negatable\n --> compiler-test:9:18\n |\n 9 | let g: u8 = -a * -1u8;\n | ^\nError [ETYC0372005]: The type `u8` is not negatable\n --> compiler-test:9:23\n |\n 9 | let g: u8 = -a * -1u8;\n | ^^^\nError [ETYC0372005]: The type `u8` is not negatable\n --> compiler-test:10:18\n |\n 10 | let h: u8 = -a ** -1u8;\n | ^\nError [ETYC0372005]: The type `u8` is not negatable\n --> compiler-test:10:24\n |\n 10 | let h: u8 = -a ** -1u8;\n | ^^^\n"
|
@ -2,4 +2,4 @@
|
|||||||
namespace: Compile
|
namespace: Compile
|
||||||
expectation: Fail
|
expectation: Fail
|
||||||
outputs:
|
outputs:
|
||||||
- "Error [EAST0372015]: variable `x` shadowed\n --> compiler-test:4:2\n |\n 4 | \tlet x: u8 = 1u8;\n | ^^^^^^^^^^^^^^^\nError [EAST0372015]: variable `x` shadowed\n --> compiler-test:4:2\n |\n 4 | \tlet x: u8 = 1u8;\n | ^^^^^^^^^^^^^^^"
|
- "Error [EAST0372015]: variable `x` shadowed\n --> compiler-test:4:2\n |\n 4 | \tlet x: u8 = 1u8;\n | ^^^^^^^^^^^^^^^\n"
|
||||||
|
Loading…
Reference in New Issue
Block a user