From b357a05cb064eb21fed110b6d7c5f543f72c18e8 Mon Sep 17 00:00:00 2001 From: Michael <78988079+mhasel@users.noreply.github.com> Date: Mon, 18 Mar 2024 13:52:41 +0100 Subject: [PATCH] fix: false-positive downcast warnings (#1114) * fix: false-positive downcast warnings Fixes false-positive downcast warnings on integrally promoted expressions. This is achieved by checking each element's type in the expression individually and comparing it to the resulting type rather than checking the expression's type as a whole. --------- Co-authored-by: Mathias Rieder Co-authored-by: Volkan Sagcan --- compiler/plc_ast/src/ast.rs | 16 +- compiler/plc_ast/src/literals.rs | 12 + .../src/diagnostics/diagnostics_registry.rs | 2 +- src/resolver.rs | 2 +- src/validation.rs | 12 +- src/validation/statement.rs | 119 ++++++++-- .../tests/assignment_validation_tests.rs | 217 ++++++++++++++++++ .../tests/builtin_validation_tests.rs | 3 +- ...on_tests__array_assignment_validation.snap | 26 ++- ...tion_tests__bit_assignment_validation.snap | 86 ++++++- ...ort_downcasts_depending_on_parameters.snap | 15 ++ ...l_results_are_validated_for_downcasts.snap | 9 + ...ion_tests__date_assignment_validation.snap | 8 +- ...ill_report_bigger_types_in_expression.snap | 15 ++ ...tests__duration_assignment_validation.snap | 8 +- ...idation_tests__enum_variants_mismatch.snap | 29 --- ...plicit_action_downcasts_are_validated.snap | 14 +- ...tion_tests__int_assignment_validation.snap | 110 ++++++++- ...r_lhs_will_result_in_downcast_warning.snap | 27 +++ ...t_hand_type_fits_into_the_target_type.snap | 9 + ..._tests__pointer_assignment_validation.snap | 38 ++- ...ion_tests__real_assignment_validation.snap | 32 ++- ...ins_allow_mixing_of_fp_and_int_params.snap | 15 ++ ...ation_tests__action_implicit_downcast.snap | 14 +- ...ith_incorrect_operator_causes_warning.snap | 8 +- ...sts__function_block_implicit_downcast.snap | 30 ++- ...s__function_call_parameter_validation.snap | 12 +- ...licit_param_downcast_in_function_call.snap | 36 ++- ...ation_tests__method_implicit_downcast.snap | 8 +- ...numeric_types_to_functions_is_allowed.snap | 9 + ...ts__program_call_parameter_validation.snap | 12 +- ...tion_tests__program_implicit_downcast.snap | 30 ++- .../tests/statement_validation_tests.rs | 2 +- tests/integration/data/json/simple_program.st | 2 +- 34 files changed, 890 insertions(+), 97 deletions(-) create mode 100644 src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__builtins_report_downcasts_depending_on_parameters.snap create mode 100644 src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__call_results_are_validated_for_downcasts.snap create mode 100644 src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__downcast_will_report_bigger_types_in_expression.snap delete mode 100644 src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__enum_variants_mismatch.snap create mode 100644 src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__literals_out_of_range_for_lhs_will_result_in_downcast_warning.snap create mode 100644 src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__modulo_operation_validates_if_the_left_hand_type_fits_into_the_target_type.snap create mode 100644 src/validation/tests/snapshots/rusty__validation__tests__builtin_validation_tests__arithmetic_builtins_allow_mixing_of_fp_and_int_params.snap create mode 100644 src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__passing_compatible_numeric_types_to_functions_is_allowed.snap diff --git a/compiler/plc_ast/src/ast.rs b/compiler/plc_ast/src/ast.rs index fa62eeefc5..83a218d5ec 100644 --- a/compiler/plc_ast/src/ast.rs +++ b/compiler/plc_ast/src/ast.rs @@ -1057,20 +1057,8 @@ pub fn pre_process(unit: &mut CompilationUnit, id_provider: IdProvider) { pre_processor::pre_process(unit, id_provider) } impl Operator { - /// returns true, if this operator results in a bool value - pub fn is_bool_type(&self) -> bool { - matches!( - self, - Operator::Equal - | Operator::NotEqual - | Operator::Less - | Operator::Greater - | Operator::LessOrEqual - | Operator::GreaterOrEqual - ) - } - - /// returns true, if this operator is a comparison operator + /// returns true, if this operator is a comparison operator, + /// resulting in a bool value /// (=, <>, >, <, >=, <=) pub fn is_comparison_operator(&self) -> bool { matches!( diff --git a/compiler/plc_ast/src/literals.rs b/compiler/plc_ast/src/literals.rs index 130da73b61..0ae714d346 100644 --- a/compiler/plc_ast/src/literals.rs +++ b/compiler/plc_ast/src/literals.rs @@ -259,6 +259,18 @@ impl AstLiteral { | AstLiteral::DateAndTime { .. } ) } + + pub fn is_numerical(&self) -> bool { + matches!( + self, + AstLiteral::Integer { .. } + | AstLiteral::Real { .. } + | AstLiteral::Time { .. } + | AstLiteral::Date { .. } + | AstLiteral::TimeOfDay { .. } + | AstLiteral::DateAndTime { .. } + ) + } } impl Debug for AstLiteral { diff --git a/compiler/plc_diagnostics/src/diagnostics/diagnostics_registry.rs b/compiler/plc_diagnostics/src/diagnostics/diagnostics_registry.rs index e70d967784..396f16502e 100644 --- a/compiler/plc_diagnostics/src/diagnostics/diagnostics_registry.rs +++ b/compiler/plc_diagnostics/src/diagnostics/diagnostics_registry.rs @@ -300,7 +300,7 @@ lazy_static! { Error, include_str!("./error_codes/E066.md"), E067, - Info, + Warning, include_str!("./error_codes/E067.md"), //Implicit typecast E068, Error, diff --git a/src/resolver.rs b/src/resolver.rs index 8124b54bf0..13610f19c0 100644 --- a/src/resolver.rs +++ b/src/resolver.rs @@ -1327,7 +1327,7 @@ impl<'i> TypeAnnotator<'i> { ) }; - let target_name = if data.operator.is_bool_type() { + let target_name = if data.operator.is_comparison_operator() { BOOL_TYPE.to_string() } else { bigger_type.get_name().to_string() diff --git a/src/validation.rs b/src/validation.rs index d470db4c89..57a3d7a343 100644 --- a/src/validation.rs +++ b/src/validation.rs @@ -30,7 +30,6 @@ mod variable; #[cfg(test)] mod tests; -#[derive(Clone)] pub struct ValidationContext<'s, T: AnnotationMap> { annotations: &'s T, index: &'s Index, @@ -86,6 +85,17 @@ impl<'s, T: AnnotationMap> ValidationContext<'s, T> { } } +impl<'s, T: AnnotationMap> Clone for ValidationContext<'s, T> { + fn clone(&self) -> Self { + ValidationContext { + annotations: self.annotations, + index: self.index, + qualifier: self.qualifier, + is_call: self.is_call, + } + } +} + /// This trait should be implemented by any validator used by `validation::Validator` pub trait Validators { fn push_diagnostic(&mut self, diagnostic: Diagnostic); diff --git a/src/validation/statement.rs b/src/validation/statement.rs index 8b92e653d3..6292443376 100644 --- a/src/validation/statement.rs +++ b/src/validation/statement.rs @@ -3,8 +3,8 @@ use std::{collections::HashSet, mem::discriminant}; use plc_ast::control_statements::ForLoopStatement; use plc_ast::{ ast::{ - flatten_expression_list, AstNode, AstStatement, DirectAccess, DirectAccessType, JumpStatement, - Operator, ReferenceAccess, + flatten_expression_list, AstNode, AstStatement, BinaryExpression, CallStatement, DirectAccess, + DirectAccessType, JumpStatement, Operator, ReferenceAccess, UnaryExpression, }, control_statements::{AstControlStatement, ConditionalBlock}, literals::{Array, AstLiteral, StringValue}, @@ -833,9 +833,8 @@ fn validate_assignment( location.clone(), )); } - } else if right.is_literal() { - // TODO: See https://github.com/PLC-lang/rusty/issues/857 - // validate_assignment_type_sizes(validator, left_type, right_type, location, context) + } else { + validate_assignment_type_sizes(validator, left_type, right, context) } } } @@ -1343,26 +1342,106 @@ fn validate_type_nature( } } -fn _validate_assignment_type_sizes( +fn validate_assignment_type_sizes( validator: &mut Validator, left: &DataType, - right: &DataType, - location: &SourceLocation, + right: &AstNode, context: &ValidationContext, ) { - if left.get_type_information().get_size(context.index) - < right.get_type_information().get_size(context.index) - { - validator.push_diagnostic( - Diagnostic::new(format!( - "Potential loss of information due to assigning '{}' to variable of type '{}'.", - left.get_name(), - right.get_name() - )) - .with_error_code("E067") - .with_location(location.clone()), - ) + use std::collections::HashMap; + fn get_expression_types_and_locations<'b, T: AnnotationMap>( + expression: &AstNode, + context: &'b ValidationContext, + lhs_is_signed_int: bool, + is_builtin_call: bool, + ) -> HashMap<&'b DataType, Vec> { + let mut map: HashMap<&DataType, Vec> = HashMap::new(); + match expression.get_stmt_peeled() { + AstStatement::BinaryExpression(BinaryExpression { operator, left, right, .. }) + if !operator.is_comparison_operator() => + { + get_expression_types_and_locations(left, context, lhs_is_signed_int, false) + .into_iter() + .for_each(|(k, v)| map.entry(k).or_default().extend(v)); + // the RHS type in a MOD expression has no impact on the resulting value type + if matches!(operator, Operator::Modulo) { + return map + }; + get_expression_types_and_locations(right, context, lhs_is_signed_int, false) + .into_iter() + .for_each(|(k, v)| map.entry(k).or_default().extend(v)); + } + AstStatement::UnaryExpression(UnaryExpression { operator, value }) + if !operator.is_comparison_operator() => + { + get_expression_types_and_locations(value, context, lhs_is_signed_int, false) + .into_iter() + .for_each(|(k, v)| map.entry(k).or_default().extend(v)); + } + // `get_literal_actual_signed_type_name` will always return `LREAL` for FP literals, so they will be handled by the fall-through case according to their annotated type + AstStatement::Literal(lit) if !matches!(lit, &AstLiteral::Real(_)) => { + if !lit.is_numerical() { + return map + } + if let Some(dt) = get_literal_actual_signed_type_name(lit, lhs_is_signed_int) + .map(|name| context.index.get_type(name).unwrap_or(context.index.get_void_type())) + { + map.entry(dt).or_default().push(expression.get_location()); + } + } + AstStatement::CallStatement(CallStatement { operator, parameters }) + // special handling for builtin selector functions MUX and SEL + if matches!(operator.get_flat_reference_name().unwrap_or_default(), "MUX" | "SEL") => + { + let Some(args) = parameters else { + return map + }; + if let AstStatement::ExpressionList(list) = args.get_stmt_peeled() { + // skip the selector argument since it will never be assigned to the target type + list.iter().skip(1).flat_map(|arg| { + get_expression_types_and_locations(arg, context, lhs_is_signed_int, true) + }) + .for_each(|(k, v)| map.entry(k).or_default().extend(v)); + }; + } + _ => { + if !(context.annotations.get_generic_nature(expression).is_none() || is_builtin_call) { + return map + }; + if let Some(dt) = context.annotations.get_type(expression, context.index) { + map.entry(dt).or_default().push(expression.get_location()); + } + } + }; + map } + + let lhs = left.get_type_information(); + let lhs_size = lhs.get_size(context.index); + let results_in_truncation = |rhs: &DataType| { + let rhs = rhs.get_type_information(); + let rhs_size = rhs.get_size(context.index); + lhs_size < rhs_size + || (lhs_size == rhs_size + && ((lhs.is_signed_int() && rhs.is_unsigned_int()) || (lhs.is_int() && rhs.is_float()))) + }; + + get_expression_types_and_locations(right, context, lhs.is_signed_int(), false) + .into_iter() + .filter(|(dt, _)| !dt.is_aggregate_type() && results_in_truncation(dt)) + .for_each(|(dt, location)| { + location.into_iter().for_each(|loc| { + validator.push_diagnostic( + Diagnostic::new(format!( + "Implicit downcast from '{}' to '{}'.", + get_datatype_name_or_slice(validator.context, dt), + get_datatype_name_or_slice(validator.context, left) + )) + .with_error_code("E067") + .with_location(loc), + ); + }) + }); } mod helper { diff --git a/src/validation/tests/assignment_validation_tests.rs b/src/validation/tests/assignment_validation_tests.rs index 4d36838a0c..9903c2c83b 100644 --- a/src/validation/tests/assignment_validation_tests.rs +++ b/src/validation/tests/assignment_validation_tests.rs @@ -963,6 +963,223 @@ fn string_type_alias_assignment_can_be_validated() { assert_snapshot!(diagnostics); } +#[test] +fn integral_promotion_in_expression_does_not_cause_downcast_warning() { + let diagnostics = parse_and_validate_buffered( + " + FUNCTION main : INT + VAR + a, b, c : SINT; + END_VAR + + a := a + b + c + 100; + END_FUNCTION + ", + ); + + assert!(diagnostics.is_empty()) +} + +#[test] +fn downcast_will_report_bigger_types_in_expression() { + let diagnostics = parse_and_validate_buffered( + " + FUNCTION main : INT + VAR + a, b, c : SINT; + d, e : DINT; + END_VAR + a := a + b + c + d + e; + END_FUNCTION + ", + ); + + assert_snapshot!(diagnostics) +} + +#[test] +fn literals_out_of_range_for_lhs_will_result_in_downcast_warning() { + let diagnostics = parse_and_validate_buffered( + " + FUNCTION main : INT + VAR + a : SINT; + b : USINT; + END_VAR + + a := a + 255 + 1000; // literals out of range of i8 -> warning + b := b + 255; // 255 is in range of u8 -> no warning, but will silently overflow for anything other than b == 0. Not sure if there is a better way to guard against this + a := a + b; // B is same size as a, but unsigned -> warning + a := a + USINT#100; // will fit into a, but is cast to unsigned type -> warning + END_FUNCTION + ", + ); + + assert_snapshot!(diagnostics) +} + +#[test] +fn literals_out_of_range_inside_unary_expressions_will_cause_no_warning() { + // GIVEN literals behind unary expressions (which will be annotated as DINT) + // WHEN we validate + let diagnostics = parse_and_validate_buffered( + " + FUNCTION main : INT + VAR + a : INT; + END_VAR + a := a; + a := a + 254; + a := a + 254 - 20; + a := a + 254 + (-(10+10)); //rewrite this as a unary expression + END_FUNCTION + ", + ); + //WE EXPECT NO VALIDATION PROBLEMS + assert!(diagnostics.is_empty()) +} + +#[test] +fn literals_out_of_range_in_a_modulo_operation_cannot_exceed_the_left_operand() { + // GIVEN an expression INT MOD DINT + // WHEN we validate + let diagnostics = parse_and_validate_buffered( + " + FUNCTION main : INT + VAR + a : INT; + END_VAR + a := a + (a MOD 40000); + END_FUNCTION + ", + ); + //THEN we expect no validation problems, since a mod d should remain in a's datatype + assert!(diagnostics.is_empty()) +} + +#[test] +fn modulo_operation_validates_if_the_left_hand_type_fits_into_the_target_type() { + // GIVEN an expression INT MOD DINT + // WHEN we validate + let diagnostics = parse_and_validate_buffered( + " + FUNCTION main : INT + VAR + a : INT; + d : DINT := 9; + END_VAR + a := a + (d MOD a); + END_FUNCTION + ", + ); + //THEN we expect a downcast warning, since d mod a might overflow INT + assert_snapshot!(diagnostics) +} + +#[test] +fn rhs_of_a_mod_operation_is_ignored_in_downcast_validation() { + // GIVEN an expression INT MOD DINT + // WHEN we validate + let diagnostics = parse_and_validate_buffered( + " + FUNCTION main : INT + VAR + a : INT; + d : DINT := 9; + l : LINT; + END_VAR + a := a + (a MOD d); + a := a + (a MOD LINT#10); + a := a + (a MOD l); + END_FUNCTION + ", + ); + //THEN we expect a downcast warning, since d mod a might overflow INT + assert!(diagnostics.is_empty()) +} + +#[test] +fn builtin_sel_does_not_report_false_positive_downcasts_for_literals() { + // GIVEN an expression INT MOD DINT + // WHEN we validate + let diagnostics = parse_and_validate_buffered( + " + FUNCTION main : INT + VAR + a : INT; + b : INT; + END_VAR + a := SEL(TRUE, a, b); + a := SEL(FALSE, a, 1000); + END_FUNCTION + ", + ); + //THEN we expect no validation problems, since all arguments to SEL fit into the target type + assert!(diagnostics.is_empty()) +} + +#[test] +fn builtin_mux_does_not_report_false_positive_downcasts() { + // GIVEN an expression INT MOD DINT + // WHEN we validate + let diagnostics = parse_and_validate_buffered( + " + FUNCTION main : INT + VAR + a : INT; + b : INT; + END_VAR + a := MUX(0, a, b); + a := MUX(2, a, b, 1000); + END_FUNCTION + ", + ); + //THEN we expect no validation problems, since all arguments to MUX fit into the target type + assert!(diagnostics.is_empty()) +} + +#[test] +fn builtins_report_downcasts_depending_on_parameters() { + // GIVEN an expression INT MOD DINT + // WHEN we validate + let diagnostics = parse_and_validate_buffered( + " + FUNCTION main : INT + VAR + a : INT; + b : DINT; + END_VAR + a := SEL(TRUE, a, b); // b: DINT => INT + a := MUX(0, a, b); // b: DINT => INT + a := MUX(b, a, 1000); // selector arg is ignored + END_FUNCTION + ", + ); + //THEN we expect individual parameters to be validated and the selector argument to be ignored + assert_snapshot!(diagnostics) +} + +#[test] +fn call_results_are_validated_for_downcasts() { + // GIVEN a call-result assignment DINT to INT + // WHEN we validate + let diagnostics = parse_and_validate_buffered( + " + FUNCTION foo : DINT + foo := 9; + END_FUNCTION + FUNCTION main : INT + VAR + a : INT; + END_VAR + a := FOO(); + END_FUNCTION + ", + ); + //THEN we expect a downcast validation + assert_snapshot!(diagnostics) +} + #[test] fn void_assignment_validation() { let diagnostics = parse_and_validate_buffered( diff --git a/src/validation/tests/builtin_validation_tests.rs b/src/validation/tests/builtin_validation_tests.rs index d59f82d946..154791af4e 100644 --- a/src/validation/tests/builtin_validation_tests.rs +++ b/src/validation/tests/builtin_validation_tests.rs @@ -19,8 +19,7 @@ fn arithmetic_builtins_allow_mixing_of_fp_and_int_params() { END_FUNCTION ", ); - - assert!(diagnostics.is_empty()); + assert_snapshot!(diagnostics); } #[test] diff --git a/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__array_assignment_validation.snap b/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__array_assignment_validation.snap index d096315314..7f65f283d0 100644 --- a/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__array_assignment_validation.snap +++ b/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__array_assignment_validation.snap @@ -56,6 +56,30 @@ error[E043]: Array assignments must be surrounded with `[]` 39 │ v_arr_int_3 := (1, 2, 3, 4, 5, 6); // INVALID -> missing │ ^^^^^^^^^^^^^^^^ Array assignments must be surrounded with `[]` +warning[E067]: Implicit downcast from 'DINT' to 'INT'. + ┌─ :40:23 + │ +40 │ v_arr_int_3[0] := v_dint; // valid + │ ^^^^^^ Implicit downcast from 'DINT' to 'INT'. + +warning[E067]: Implicit downcast from 'DINT' to 'INT'. + ┌─ :41:23 + │ +41 │ v_arr_int_3[0] := DINT#10; // valid + │ ^^^^^^^ Implicit downcast from 'DINT' to 'INT'. + +warning[E067]: Implicit downcast from 'REAL' to 'INT'. + ┌─ :42:23 + │ +42 │ v_arr_int_3[0] := v_real; // valid + │ ^^^^^^ Implicit downcast from 'REAL' to 'INT'. + +warning[E067]: Implicit downcast from 'REAL' to 'INT'. + ┌─ :43:23 + │ +43 │ v_arr_int_3[0] := REAL#2.0; // valid + │ ^^^^^^^^ Implicit downcast from 'REAL' to 'INT'. + error[E037]: Invalid assignment: cannot assign 'STRING' to 'INT' ┌─ :44:5 │ @@ -103,5 +127,3 @@ error[E037]: Invalid assignment: cannot assign 'ARRAY[0..3] OF INT' to 'DINT' │ 52 │ v_dint := v_arr_int_3; // INVALID │ ^^^^^^^^^^^^^^^^^^^^^ Invalid assignment: cannot assign 'ARRAY[0..3] OF INT' to 'DINT' - - diff --git a/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__bit_assignment_validation.snap b/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__bit_assignment_validation.snap index 19c391902d..b07e175e1a 100644 --- a/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__bit_assignment_validation.snap +++ b/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__bit_assignment_validation.snap @@ -2,6 +2,66 @@ source: src/validation/tests/assignment_validation_tests.rs expression: diagnostics --- +warning[E067]: Implicit downcast from 'LREAL' to 'BYTE'. + ┌─ :29:15 + │ +29 │ v_byte := v_lreal; // valid + │ ^^^^^^^ Implicit downcast from 'LREAL' to 'BYTE'. + +warning[E067]: Implicit downcast from 'REAL' to 'BYTE'. + ┌─ :30:15 + │ +30 │ v_byte := REAL#2.0; // valid + │ ^^^^^^^^ Implicit downcast from 'REAL' to 'BYTE'. + +warning[E067]: Implicit downcast from 'UDINT' to 'BYTE'. + ┌─ :31:15 + │ +31 │ v_byte := v_udint; // valid + │ ^^^^^^^ Implicit downcast from 'UDINT' to 'BYTE'. + +warning[E067]: Implicit downcast from 'UDINT' to 'BYTE'. + ┌─ :32:15 + │ +32 │ v_byte := UDINT#10; // valid + │ ^^^^^^^^ Implicit downcast from 'UDINT' to 'BYTE'. + +warning[E067]: Implicit downcast from 'DINT' to 'BYTE'. + ┌─ :33:15 + │ +33 │ v_byte := v_dint; // valid + │ ^^^^^^ Implicit downcast from 'DINT' to 'BYTE'. + +warning[E067]: Implicit downcast from 'DINT' to 'BYTE'. + ┌─ :34:15 + │ +34 │ v_byte := DINT#20; // valid + │ ^^^^^^^ Implicit downcast from 'DINT' to 'BYTE'. + +warning[E067]: Implicit downcast from 'TIME' to 'BYTE'. + ┌─ :35:15 + │ +35 │ v_byte := v_time; // valid + │ ^^^^^^ Implicit downcast from 'TIME' to 'BYTE'. + +warning[E067]: Implicit downcast from 'TIME' to 'BYTE'. + ┌─ :36:15 + │ +36 │ v_byte := TIME#10h20m30s; // valid + │ ^^^^^^^^^^^^^^ Implicit downcast from 'TIME' to 'BYTE'. + +warning[E067]: Implicit downcast from 'WORD' to 'BYTE'. + ┌─ :37:15 + │ +37 │ v_byte := v_word; // valid + │ ^^^^^^ Implicit downcast from 'WORD' to 'BYTE'. + +warning[E067]: Implicit downcast from 'WORD' to 'BYTE'. + ┌─ :38:15 + │ +38 │ v_byte := WORD#16#ffff; // valid + │ ^^^^^^^^^^^^ Implicit downcast from 'WORD' to 'BYTE'. + error[E037]: Invalid assignment: cannot assign 'STRING' to 'BYTE' ┌─ :39:5 │ @@ -32,16 +92,38 @@ error[E037]: Invalid assignment: cannot assign 'CHAR' to 'BYTE' 43 │ v_byte := CHAR#'c'; // INVALID │ ^^^^^^^^^^^^^^^^^^ Invalid assignment: cannot assign 'CHAR' to 'BYTE' +warning[E067]: Implicit downcast from 'TIME_OF_DAY' to 'BYTE'. + ┌─ :44:15 + │ +44 │ v_byte := v_tod; // valid + │ ^^^^^ Implicit downcast from 'TIME_OF_DAY' to 'BYTE'. + +warning[E067]: Implicit downcast from 'TIME_OF_DAY' to 'BYTE'. + ┌─ :45:15 + │ +45 │ v_byte := TOD#15:36:30; // valid + │ ^^^^^^^^^^^^ Implicit downcast from 'TIME_OF_DAY' to 'BYTE'. + +warning[E067]: Implicit downcast from 'INT' to 'BYTE'. + ┌─ :46:15 + │ +46 │ v_byte := v_ptr_int^; // valid + │ ^^^^^^^^^^ Implicit downcast from 'INT' to 'BYTE'. + error[E037]: Invalid assignment: cannot assign 'STRING' to 'BYTE' ┌─ :47:5 │ 47 │ v_byte := v_ptr_string^; // INVALID │ ^^^^^^^^^^^^^^^^^^^^^^^ Invalid assignment: cannot assign 'STRING' to 'BYTE' +warning[E067]: Implicit downcast from 'INT' to 'BYTE'. + ┌─ :48:15 + │ +48 │ v_byte := v_arr_int_3[0]; // valid + │ ^^^^^^^^^^^^^^ Implicit downcast from 'INT' to 'BYTE'. + error[E037]: Invalid assignment: cannot assign 'STRING' to 'BYTE' ┌─ :49:5 │ 49 │ v_byte := v_arr_string_3[0]; // INVALID │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Invalid assignment: cannot assign 'STRING' to 'BYTE' - - diff --git a/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__builtins_report_downcasts_depending_on_parameters.snap b/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__builtins_report_downcasts_depending_on_parameters.snap new file mode 100644 index 0000000000..ba1b9e9af4 --- /dev/null +++ b/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__builtins_report_downcasts_depending_on_parameters.snap @@ -0,0 +1,15 @@ +--- +source: src/validation/tests/assignment_validation_tests.rs +expression: diagnostics +--- +warning[E067]: Implicit downcast from 'DINT' to 'INT'. + ┌─ :7:31 + │ +7 │ a := SEL(TRUE, a, b); // b: DINT => INT + │ ^ Implicit downcast from 'DINT' to 'INT'. + +warning[E067]: Implicit downcast from 'DINT' to 'INT'. + ┌─ :8:28 + │ +8 │ a := MUX(0, a, b); // b: DINT => INT + │ ^ Implicit downcast from 'DINT' to 'INT'. diff --git a/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__call_results_are_validated_for_downcasts.snap b/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__call_results_are_validated_for_downcasts.snap new file mode 100644 index 0000000000..8b0c123eb3 --- /dev/null +++ b/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__call_results_are_validated_for_downcasts.snap @@ -0,0 +1,9 @@ +--- +source: src/validation/tests/assignment_validation_tests.rs +expression: diagnostics +--- +warning[E067]: Implicit downcast from 'DINT' to 'INT'. + ┌─ :9:18 + │ +9 │ a := FOO(); + │ ^^^^^^ Implicit downcast from 'DINT' to 'INT'. diff --git a/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__date_assignment_validation.snap b/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__date_assignment_validation.snap index fd54249f7a..d73081d983 100644 --- a/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__date_assignment_validation.snap +++ b/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__date_assignment_validation.snap @@ -2,6 +2,12 @@ source: src/validation/tests/assignment_validation_tests.rs expression: "&diagnostics" --- +warning[E067]: Implicit downcast from 'LREAL' to 'DATE'. + ┌─ :29:15 + │ +29 │ v_date := v_lreal; // valid + │ ^^^^^^^ Implicit downcast from 'LREAL' to 'DATE'. + error[E037]: Invalid assignment: cannot assign 'STRING' to 'DATE' ┌─ :39:5 │ @@ -43,5 +49,3 @@ error[E037]: Invalid assignment: cannot assign 'STRING' to 'DATE' │ 49 │ v_date := v_arr_string_3[0]; // INVALID │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Invalid assignment: cannot assign 'STRING' to 'DATE' - - diff --git a/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__downcast_will_report_bigger_types_in_expression.snap b/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__downcast_will_report_bigger_types_in_expression.snap new file mode 100644 index 0000000000..8577a360f4 --- /dev/null +++ b/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__downcast_will_report_bigger_types_in_expression.snap @@ -0,0 +1,15 @@ +--- +source: src/validation/tests/assignment_validation_tests.rs +expression: diagnostics +--- +warning[E067]: Implicit downcast from 'DINT' to 'SINT'. + ┌─ :7:30 + │ +7 │ a := a + b + c + d + e; + │ ^ Implicit downcast from 'DINT' to 'SINT'. + +warning[E067]: Implicit downcast from 'DINT' to 'SINT'. + ┌─ :7:34 + │ +7 │ a := a + b + c + d + e; + │ ^ Implicit downcast from 'DINT' to 'SINT'. diff --git a/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__duration_assignment_validation.snap b/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__duration_assignment_validation.snap index 47ade9ba95..d24db4067d 100644 --- a/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__duration_assignment_validation.snap +++ b/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__duration_assignment_validation.snap @@ -2,6 +2,12 @@ source: src/validation/tests/assignment_validation_tests.rs expression: diagnostics --- +warning[E067]: Implicit downcast from 'LREAL' to 'TIME'. + ┌─ :29:15 + │ +29 │ v_time := v_lreal; // valid + │ ^^^^^^^ Implicit downcast from 'LREAL' to 'TIME'. + error[E037]: Invalid assignment: cannot assign 'STRING' to 'TIME' ┌─ :39:5 │ @@ -43,5 +49,3 @@ error[E037]: Invalid assignment: cannot assign 'STRING' to 'TIME' │ 49 │ v_time := v_arr_string_3[0]; // INVALID │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Invalid assignment: cannot assign 'STRING' to 'TIME' - - diff --git a/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__enum_variants_mismatch.snap b/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__enum_variants_mismatch.snap deleted file mode 100644 index ebd8b7082f..0000000000 --- a/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__enum_variants_mismatch.snap +++ /dev/null @@ -1,29 +0,0 @@ ---- -source: src/validation/tests/assignment_validation_tests.rs -expression: diagnostics ---- -error[E040]: Assigned value is not a variant of main.color - ┌─ :11:22 - │ -11 │ color := Dog; // warning - │ ^^^ Assigned value is not a variant of main.color - -error[E040]: Assigned value is not a variant of main.water - ┌─ :12:22 - │ -12 │ water := blue; // warning - │ ^^^^ Assigned value is not a variant of main.water - -error[E040]: Assigned value is not a variant of main.color - ┌─ :13:22 - │ -13 │ color := sparkling; // warning - │ ^^^^^^^^^ Assigned value is not a variant of main.color - -error[E040]: Assigned value is not a variant of main.color - ┌─ :14:22 - │ -14 │ color := 2; // warning - │ ^ Assigned value is not a variant of main.color - - diff --git a/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__implicit_action_downcasts_are_validated.snap b/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__implicit_action_downcasts_are_validated.snap index e77131d0e7..339554e9bc 100644 --- a/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__implicit_action_downcasts_are_validated.snap +++ b/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__implicit_action_downcasts_are_validated.snap @@ -2,10 +2,20 @@ source: src/validation/tests/assignment_validation_tests.rs expression: "&diagnostics" --- +warning[E067]: Implicit downcast from 'LINT' to 'DINT'. + ┌─ :26:20 + │ +26 │ fb.foo(var1, var2, var3); + │ ^^^^ Implicit downcast from 'LINT' to 'DINT'. + +warning[E067]: Implicit downcast from 'LWORD' to 'DWORD'. + ┌─ :26:26 + │ +26 │ fb.foo(var1, var2, var3); + │ ^^^^ Implicit downcast from 'LWORD' to 'DWORD'. + error[E037]: Invalid assignment: cannot assign 'STRING' to 'BYTE' ┌─ :26:32 │ 26 │ fb.foo(var1, var2, var3); │ ^^^^ Invalid assignment: cannot assign 'STRING' to 'BYTE' - - diff --git a/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__int_assignment_validation.snap b/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__int_assignment_validation.snap index 1459585992..c37018fd02 100644 --- a/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__int_assignment_validation.snap +++ b/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__int_assignment_validation.snap @@ -2,6 +2,42 @@ source: src/validation/tests/assignment_validation_tests.rs expression: diagnostics --- +warning[E067]: Implicit downcast from 'LREAL' to 'UDINT'. + ┌─ :31:16 + │ +31 │ v_udint := v_lreal; // valid + │ ^^^^^^^ Implicit downcast from 'LREAL' to 'UDINT'. + +warning[E067]: Implicit downcast from 'REAL' to 'UDINT'. + ┌─ :32:16 + │ +32 │ v_udint := REAL#2.0; // valid + │ ^^^^^^^^ Implicit downcast from 'REAL' to 'UDINT'. + +warning[E067]: Implicit downcast from 'ULINT' to 'UDINT'. + ┌─ :33:16 + │ +33 │ v_udint := v_ulint; // valid + │ ^^^^^^^ Implicit downcast from 'ULINT' to 'UDINT'. + +warning[E067]: Implicit downcast from 'ULINT' to 'UDINT'. + ┌─ :34:16 + │ +34 │ v_udint := ULINT#10; // valid + │ ^^^^^^^^ Implicit downcast from 'ULINT' to 'UDINT'. + +warning[E067]: Implicit downcast from 'TIME' to 'UDINT'. + ┌─ :37:16 + │ +37 │ v_udint := v_time; // valid + │ ^^^^^^ Implicit downcast from 'TIME' to 'UDINT'. + +warning[E067]: Implicit downcast from 'TIME' to 'UDINT'. + ┌─ :38:16 + │ +38 │ v_udint := TIME#10h20m30s; // valid + │ ^^^^^^^^^^^^^^ Implicit downcast from 'TIME' to 'UDINT'. + error[E037]: Invalid assignment: cannot assign 'STRING' to 'UDINT' ┌─ :41:5 │ @@ -32,6 +68,18 @@ error[E037]: Invalid assignment: cannot assign 'CHAR' to 'UDINT' 45 │ v_udint := CHAR#'c'; // INVALID │ ^^^^^^^^^^^^^^^^^^^ Invalid assignment: cannot assign 'CHAR' to 'UDINT' +warning[E067]: Implicit downcast from 'TIME_OF_DAY' to 'UDINT'. + ┌─ :46:16 + │ +46 │ v_udint := v_tod; // valid + │ ^^^^^ Implicit downcast from 'TIME_OF_DAY' to 'UDINT'. + +warning[E067]: Implicit downcast from 'TIME_OF_DAY' to 'UDINT'. + ┌─ :47:16 + │ +47 │ v_udint := TOD#15:36:30; // valid + │ ^^^^^^^^^^^^ Implicit downcast from 'TIME_OF_DAY' to 'UDINT'. + error[E037]: Invalid assignment: cannot assign 'STRING' to 'UDINT' ┌─ :49:5 │ @@ -44,6 +92,54 @@ error[E037]: Invalid assignment: cannot assign 'STRING' to 'UDINT' 51 │ v_udint := v_arr_string_3[0]; // INVALID │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Invalid assignment: cannot assign 'STRING' to 'UDINT' +warning[E067]: Implicit downcast from 'LREAL' to 'DINT'. + ┌─ :54:15 + │ +54 │ v_dint := v_lreal; // valid + │ ^^^^^^^ Implicit downcast from 'LREAL' to 'DINT'. + +warning[E067]: Implicit downcast from 'REAL' to 'DINT'. + ┌─ :55:15 + │ +55 │ v_dint := REAL#2.0; // valid + │ ^^^^^^^^ Implicit downcast from 'REAL' to 'DINT'. + +warning[E067]: Implicit downcast from 'UDINT' to 'DINT'. + ┌─ :56:15 + │ +56 │ v_dint := v_udint; // valid + │ ^^^^^^^ Implicit downcast from 'UDINT' to 'DINT'. + +warning[E067]: Implicit downcast from 'UDINT' to 'DINT'. + ┌─ :57:15 + │ +57 │ v_dint := UDINT#10; // valid + │ ^^^^^^^^ Implicit downcast from 'UDINT' to 'DINT'. + +warning[E067]: Implicit downcast from 'LINT' to 'DINT'. + ┌─ :58:15 + │ +58 │ v_dint := v_lint; // valid + │ ^^^^^^ Implicit downcast from 'LINT' to 'DINT'. + +warning[E067]: Implicit downcast from 'LINT' to 'DINT'. + ┌─ :59:15 + │ +59 │ v_dint := LINT#20; // valid + │ ^^^^^^^ Implicit downcast from 'LINT' to 'DINT'. + +warning[E067]: Implicit downcast from 'TIME' to 'DINT'. + ┌─ :60:15 + │ +60 │ v_dint := v_time; // valid + │ ^^^^^^ Implicit downcast from 'TIME' to 'DINT'. + +warning[E067]: Implicit downcast from 'TIME' to 'DINT'. + ┌─ :61:15 + │ +61 │ v_dint := TIME#10h20m30s; // valid + │ ^^^^^^^^^^^^^^ Implicit downcast from 'TIME' to 'DINT'. + error[E037]: Invalid assignment: cannot assign 'STRING' to 'DINT' ┌─ :64:5 │ @@ -74,6 +170,18 @@ error[E037]: Invalid assignment: cannot assign 'CHAR' to 'DINT' 68 │ v_dint := CHAR#'c'; // INVALID │ ^^^^^^^^^^^^^^^^^^ Invalid assignment: cannot assign 'CHAR' to 'DINT' +warning[E067]: Implicit downcast from 'TIME_OF_DAY' to 'DINT'. + ┌─ :69:15 + │ +69 │ v_dint := v_tod; // valid + │ ^^^^^ Implicit downcast from 'TIME_OF_DAY' to 'DINT'. + +warning[E067]: Implicit downcast from 'TIME_OF_DAY' to 'DINT'. + ┌─ :70:15 + │ +70 │ v_dint := TOD#15:36:30; // valid + │ ^^^^^^^^^^^^ Implicit downcast from 'TIME_OF_DAY' to 'DINT'. + error[E037]: Invalid assignment: cannot assign 'STRING' to 'DINT' ┌─ :72:5 │ @@ -85,5 +193,3 @@ error[E037]: Invalid assignment: cannot assign 'STRING' to 'DINT' │ 74 │ v_dint := v_arr_string_3[0]; // INVALID │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Invalid assignment: cannot assign 'STRING' to 'DINT' - - diff --git a/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__literals_out_of_range_for_lhs_will_result_in_downcast_warning.snap b/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__literals_out_of_range_for_lhs_will_result_in_downcast_warning.snap new file mode 100644 index 0000000000..88a9a1fd9b --- /dev/null +++ b/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__literals_out_of_range_for_lhs_will_result_in_downcast_warning.snap @@ -0,0 +1,27 @@ +--- +source: src/validation/tests/assignment_validation_tests.rs +expression: diagnostics +--- +warning[E067]: Implicit downcast from 'INT' to 'SINT'. + ┌─ :8:22 + │ +8 │ a := a + 255 + 1000; // literals out of range of i8 -> warning + │ ^^^ Implicit downcast from 'INT' to 'SINT'. + +warning[E067]: Implicit downcast from 'INT' to 'SINT'. + ┌─ :8:28 + │ +8 │ a := a + 255 + 1000; // literals out of range of i8 -> warning + │ ^^^^ Implicit downcast from 'INT' to 'SINT'. + +warning[E067]: Implicit downcast from 'USINT' to 'SINT'. + ┌─ :10:22 + │ +10 │ a := a + b; // B is same size as a, but unsigned -> warning + │ ^ Implicit downcast from 'USINT' to 'SINT'. + +warning[E067]: Implicit downcast from 'USINT' to 'SINT'. + ┌─ :11:22 + │ +11 │ a := a + USINT#100; // will fit into a, but is cast to unsigned type -> warning + │ ^^^^^^^^^ Implicit downcast from 'USINT' to 'SINT'. diff --git a/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__modulo_operation_validates_if_the_left_hand_type_fits_into_the_target_type.snap b/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__modulo_operation_validates_if_the_left_hand_type_fits_into_the_target_type.snap new file mode 100644 index 0000000000..20d4c089bb --- /dev/null +++ b/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__modulo_operation_validates_if_the_left_hand_type_fits_into_the_target_type.snap @@ -0,0 +1,9 @@ +--- +source: src/validation/tests/assignment_validation_tests.rs +expression: diagnostics +--- +warning[E067]: Implicit downcast from 'DINT' to 'INT'. + ┌─ :7:23 + │ +7 │ a := a + (d MOD a); + │ ^ Implicit downcast from 'DINT' to 'INT'. diff --git a/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__pointer_assignment_validation.snap b/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__pointer_assignment_validation.snap index bdf0f60aab..ba7d90088a 100644 --- a/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__pointer_assignment_validation.snap +++ b/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__pointer_assignment_validation.snap @@ -32,6 +32,36 @@ warning[E090]: Pointers REF_TO INT and __POINTER_TO_REAL have different types 31 │ v_ptr_int := &v_real; // INVALID -> TODO: should be valid │ ^^^^^^^^^^^^^^^^^^^^ Pointers REF_TO INT and __POINTER_TO_REAL have different types +warning[E067]: Implicit downcast from 'REAL' to 'INT'. + ┌─ :32:19 + │ +32 │ v_ptr_int^ := v_real; // valid + │ ^^^^^^ Implicit downcast from 'REAL' to 'INT'. + +warning[E067]: Implicit downcast from 'UDINT' to 'INT'. + ┌─ :34:19 + │ +34 │ v_ptr_int^ := v_udint; // valid + │ ^^^^^^^ Implicit downcast from 'UDINT' to 'INT'. + +warning[E067]: Implicit downcast from 'DINT' to 'INT'. + ┌─ :36:19 + │ +36 │ v_ptr_int^ := v_dint; // valid + │ ^^^^^^ Implicit downcast from 'DINT' to 'INT'. + +warning[E067]: Implicit downcast from 'TIME' to 'INT'. + ┌─ :38:19 + │ +38 │ v_ptr_int^ := v_time; // valid + │ ^^^^^^ Implicit downcast from 'TIME' to 'INT'. + +warning[E067]: Implicit downcast from 'WORD' to 'INT'. + ┌─ :40:19 + │ +40 │ v_ptr_int^ := v_word; // valid + │ ^^^^^^ Implicit downcast from 'WORD' to 'INT'. + warning[E090]: Pointers REF_TO INT and __POINTER_TO_STRING have different types ┌─ :41:5 │ @@ -50,10 +80,14 @@ error[E037]: Invalid assignment: cannot assign 'CHAR' to 'INT' 44 │ v_ptr_int^ := v_char; // INVALID │ ^^^^^^^^^^^^^^^^^^^^ Invalid assignment: cannot assign 'CHAR' to 'INT' +warning[E067]: Implicit downcast from 'DATE' to 'INT'. + ┌─ :46:19 + │ +46 │ v_ptr_int^ := v_date; // valid + │ ^^^^^^ Implicit downcast from 'DATE' to 'INT'. + error[E037]: Invalid assignment: cannot assign 'STRING' to 'INT' ┌─ :48:5 │ 48 │ v_ptr_int^ := v_arr_string_3[0]; // INVALID │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Invalid assignment: cannot assign 'STRING' to 'INT' - - diff --git a/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__real_assignment_validation.snap b/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__real_assignment_validation.snap index 0d761baa6d..f890b8eaf5 100644 --- a/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__real_assignment_validation.snap +++ b/src/validation/tests/snapshots/rusty__validation__tests__assignment_validation_tests__real_assignment_validation.snap @@ -2,6 +2,24 @@ source: src/validation/tests/assignment_validation_tests.rs expression: diagnostics --- +warning[E067]: Implicit downcast from 'LREAL' to 'REAL'. + ┌─ :29:15 + │ +29 │ v_real := v_lreal; // valid + │ ^^^^^^^ Implicit downcast from 'LREAL' to 'REAL'. + +warning[E067]: Implicit downcast from 'TIME' to 'REAL'. + ┌─ :35:15 + │ +35 │ v_real := v_time; // valid + │ ^^^^^^ Implicit downcast from 'TIME' to 'REAL'. + +warning[E067]: Implicit downcast from 'TIME' to 'REAL'. + ┌─ :36:15 + │ +36 │ v_real := TIME#10h20m30s; // valid + │ ^^^^^^^^^^^^^^ Implicit downcast from 'TIME' to 'REAL'. + error[E037]: Invalid assignment: cannot assign 'STRING' to 'REAL' ┌─ :39:5 │ @@ -32,6 +50,18 @@ error[E037]: Invalid assignment: cannot assign 'CHAR' to 'REAL' 43 │ v_real := CHAR#'c'; // INVALID │ ^^^^^^^^^^^^^^^^^^ Invalid assignment: cannot assign 'CHAR' to 'REAL' +warning[E067]: Implicit downcast from 'TIME_OF_DAY' to 'REAL'. + ┌─ :44:15 + │ +44 │ v_real := v_tod; // valid + │ ^^^^^ Implicit downcast from 'TIME_OF_DAY' to 'REAL'. + +warning[E067]: Implicit downcast from 'TIME_OF_DAY' to 'REAL'. + ┌─ :45:15 + │ +45 │ v_real := TOD#15:36:30; // valid + │ ^^^^^^^^^^^^ Implicit downcast from 'TIME_OF_DAY' to 'REAL'. + error[E037]: Invalid assignment: cannot assign 'STRING' to 'REAL' ┌─ :47:5 │ @@ -43,5 +73,3 @@ error[E037]: Invalid assignment: cannot assign 'STRING' to 'REAL' │ 49 │ v_real := v_arr_string_3[0]; // INVALID │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Invalid assignment: cannot assign 'STRING' to 'REAL' - - diff --git a/src/validation/tests/snapshots/rusty__validation__tests__builtin_validation_tests__arithmetic_builtins_allow_mixing_of_fp_and_int_params.snap b/src/validation/tests/snapshots/rusty__validation__tests__builtin_validation_tests__arithmetic_builtins_allow_mixing_of_fp_and_int_params.snap new file mode 100644 index 0000000000..20cdea0801 --- /dev/null +++ b/src/validation/tests/snapshots/rusty__validation__tests__builtin_validation_tests__arithmetic_builtins_allow_mixing_of_fp_and_int_params.snap @@ -0,0 +1,15 @@ +--- +source: src/validation/tests/builtin_validation_tests.rs +expression: diagnostics +--- +warning[E067]: Implicit downcast from 'LREAL' to 'DINT'. + ┌─ :9:22 + │ +9 │ res_i := ADD(i1, i2, f1, f2); + │ ^^^^^^^^^^^^^^^^^^^ Implicit downcast from 'LREAL' to 'DINT'. + +warning[E067]: Implicit downcast from 'LREAL' to 'DINT'. + ┌─ :11:22 + │ +11 │ res_i := SUB(i1, f2); + │ ^^^^^^^^^^^ Implicit downcast from 'LREAL' to 'DINT'. diff --git a/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__action_implicit_downcast.snap b/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__action_implicit_downcast.snap index 766289fba1..511b7e1951 100644 --- a/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__action_implicit_downcast.snap +++ b/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__action_implicit_downcast.snap @@ -2,16 +2,26 @@ source: src/validation/tests/statement_validation_tests.rs expression: "&diagnostics" --- +warning[E067]: Implicit downcast from 'LINT' to 'DINT'. + ┌─ :9:20 + │ +9 │ fb.foo(var_lint, var_wstr); // downcast, invalid + │ ^^^^^^^^ Implicit downcast from 'LINT' to 'DINT'. + error[E037]: Invalid assignment: cannot assign 'WSTRING' to 'STRING' ┌─ :9:30 │ 9 │ fb.foo(var_lint, var_wstr); // downcast, invalid │ ^^^^^^^^ Invalid assignment: cannot assign 'WSTRING' to 'STRING' +warning[E067]: Implicit downcast from 'LINT' to 'INT'. + ┌─ :10:22 + │ +10 │ prog.bar(var_lint, var_arr); // downcast, invalid + │ ^^^^^^^^ Implicit downcast from 'LINT' to 'INT'. + error[E037]: Invalid assignment: cannot assign 'ARRAY[1..3] OF LINT' to 'STRING' ┌─ :10:32 │ 10 │ prog.bar(var_lint, var_arr); // downcast, invalid │ ^^^^^^^ Invalid assignment: cannot assign 'ARRAY[1..3] OF LINT' to 'STRING' - - diff --git a/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__bit_access_with_incorrect_operator_causes_warning.snap b/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__bit_access_with_incorrect_operator_causes_warning.snap index f16cb4ac90..bcfc58f16c 100644 --- a/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__bit_access_with_incorrect_operator_causes_warning.snap +++ b/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__bit_access_with_incorrect_operator_causes_warning.snap @@ -2,6 +2,12 @@ source: src/validation/tests/statement_validation_tests.rs expression: diagnostics --- +warning[E067]: Implicit downcast from 'DWORD' to 'BOOL'. + ┌─ :11:43 + │ +11 │ Output.var1.%Wn1.%Bn1.%Xn1 := Input.var1; // OK + │ ^^^^^^^^^^ Implicit downcast from 'DWORD' to 'BOOL'. + error[E048]: Could not resolve reference to n1 ┌─ :12:25 │ @@ -13,5 +19,3 @@ note[E060]: If you meant to directly access a bit/byte/word/..., use %X/%B/%Wn1 │ 12 │ Output.var1.n1 := Input.var1; // bitaccess without %X -> Warning │ ^^ If you meant to directly access a bit/byte/word/..., use %X/%B/%Wn1 instead. - - diff --git a/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__function_block_implicit_downcast.snap b/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__function_block_implicit_downcast.snap index cc7dc3d07d..54fb892dd7 100644 --- a/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__function_block_implicit_downcast.snap +++ b/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__function_block_implicit_downcast.snap @@ -2,10 +2,38 @@ source: src/validation/tests/statement_validation_tests.rs expression: "&diagnostics" --- +warning[E067]: Implicit downcast from 'LINT' to 'INT'. + ┌─ :11:17 + │ +11 │ var1_lint, // downcast + │ ^^^^^^^^^ Implicit downcast from 'LINT' to 'INT'. + +warning[E067]: Implicit downcast from 'LWORD' to 'DWORD'. + ┌─ :12:17 + │ +12 │ var_lword, // downcast + │ ^^^^^^^^^ Implicit downcast from 'LWORD' to 'DWORD'. + +warning[E067]: Implicit downcast from 'INT' to 'SINT'. + ┌─ :14:17 + │ +14 │ INT#var1_lint, // downcast + │ ^^^^^^^^^^^^^ Implicit downcast from 'INT' to 'SINT'. + +warning[E067]: Implicit downcast from 'LINT' to 'INT'. + ┌─ :15:17 + │ +15 │ var2_lint, // downcast + │ ^^^^^^^^^ Implicit downcast from 'LINT' to 'INT'. + error[E037]: Invalid assignment: cannot assign 'WSTRING' to 'STRING' ┌─ :16:17 │ 16 │ var_wstr, // invalid │ ^^^^^^^^ Invalid assignment: cannot assign 'WSTRING' to 'STRING' - +warning[E067]: Implicit downcast from 'LINT' to 'DINT'. + ┌─ :17:17 + │ +17 │ var1_lint // downcast + │ ^^^^^^^^^ Implicit downcast from 'LINT' to 'DINT'. diff --git a/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__function_call_parameter_validation.snap b/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__function_call_parameter_validation.snap index e0ac09e1e5..47700cf136 100644 --- a/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__function_call_parameter_validation.snap +++ b/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__function_call_parameter_validation.snap @@ -32,6 +32,12 @@ error[E037]: Invalid assignment: cannot assign 'REF_TO WSTRING' to 'DINT' 25 │ foo(input1 := var2, inout1 := var3, output1 => var4); // invalid types assigned │ ^^^^^^^^^^^^^^ Invalid assignment: cannot assign 'REF_TO WSTRING' to 'DINT' +warning[E067]: Implicit downcast from 'REAL' to 'DINT'. + ┌─ :25:60 + │ +25 │ foo(input1 := var2, inout1 := var3, output1 => var4); // invalid types assigned + │ ^^^^ Implicit downcast from 'REAL' to 'DINT'. + error[E037]: Invalid assignment: cannot assign 'STRING' to 'DINT' ┌─ :27:17 │ @@ -50,4 +56,8 @@ error[E037]: Invalid assignment: cannot assign 'REF_TO WSTRING' to 'DINT' 27 │ foo(var2, var3, var4); // invalid types assigned │ ^^^^ Invalid assignment: cannot assign 'REF_TO WSTRING' to 'DINT' - +warning[E067]: Implicit downcast from 'REAL' to 'DINT'. + ┌─ :27:29 + │ +27 │ foo(var2, var3, var4); // invalid types assigned + │ ^^^^ Implicit downcast from 'REAL' to 'DINT'. diff --git a/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__implicit_param_downcast_in_function_call.snap b/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__implicit_param_downcast_in_function_call.snap index 57795d7afc..e9dfd83fda 100644 --- a/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__implicit_param_downcast_in_function_call.snap +++ b/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__implicit_param_downcast_in_function_call.snap @@ -2,10 +2,44 @@ source: src/validation/tests/statement_validation_tests.rs expression: "&diagnostics" --- +warning[E067]: Implicit downcast from 'LINT' to 'INT'. + ┌─ :12:17 + │ +12 │ var1_lint, // downcast + │ ^^^^^^^^^ Implicit downcast from 'LINT' to 'INT'. + +warning[E067]: Implicit downcast from 'LWORD' to 'DWORD'. + ┌─ :13:17 + │ +13 │ var_lword, // downcast + │ ^^^^^^^^^ Implicit downcast from 'LWORD' to 'DWORD'. + +warning[E067]: Implicit downcast from 'LREAL' to 'REAL'. + ┌─ :14:17 + │ +14 │ var_lreal, // downcast + │ ^^^^^^^^^ Implicit downcast from 'LREAL' to 'REAL'. + +warning[E067]: Implicit downcast from 'INT' to 'SINT'. + ┌─ :15:17 + │ +15 │ INT#var1_lint, // downcast + │ ^^^^^^^^^^^^^ Implicit downcast from 'INT' to 'SINT'. + +warning[E067]: Implicit downcast from 'LINT' to 'INT'. + ┌─ :16:17 + │ +16 │ var2_lint, // downcast + │ ^^^^^^^^^ Implicit downcast from 'LINT' to 'INT'. + error[E037]: Invalid assignment: cannot assign 'WSTRING' to 'STRING' ┌─ :17:17 │ 17 │ var_in_out_wstr, // invalid │ ^^^^^^^^^^^^^^^ Invalid assignment: cannot assign 'WSTRING' to 'STRING' - +warning[E067]: Implicit downcast from 'LINT' to 'DINT'. + ┌─ :18:17 + │ +18 │ var1_lint // downcast + │ ^^^^^^^^^ Implicit downcast from 'LINT' to 'DINT'. diff --git a/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__method_implicit_downcast.snap b/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__method_implicit_downcast.snap index c49875e165..e9fb62df16 100644 --- a/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__method_implicit_downcast.snap +++ b/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__method_implicit_downcast.snap @@ -2,10 +2,14 @@ source: src/validation/tests/statement_validation_tests.rs expression: "&diagnostics" --- +warning[E067]: Implicit downcast from 'LINT' to 'INT'. + ┌─ :8:23 + │ +8 │ cl.testMethod(var_lint, var_arr, ADR(var_arr)); // downcast, invalid, ok + │ ^^^^^^^^ Implicit downcast from 'LINT' to 'INT'. + error[E037]: Invalid assignment: cannot assign 'ARRAY[1..3] OF DINT' to 'ARRAY[1..3] OF SINT' ┌─ :8:33 │ 8 │ cl.testMethod(var_lint, var_arr, ADR(var_arr)); // downcast, invalid, ok │ ^^^^^^^ Invalid assignment: cannot assign 'ARRAY[1..3] OF DINT' to 'ARRAY[1..3] OF SINT' - - diff --git a/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__passing_compatible_numeric_types_to_functions_is_allowed.snap b/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__passing_compatible_numeric_types_to_functions_is_allowed.snap new file mode 100644 index 0000000000..6794ceb25a --- /dev/null +++ b/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__passing_compatible_numeric_types_to_functions_is_allowed.snap @@ -0,0 +1,9 @@ +--- +source: src/validation/tests/statement_validation_tests.rs +expression: diagnostics +--- +warning[E067]: Implicit downcast from 'LREAL' to 'LINT'. + ┌─ :8:13 + │ +8 │ bar(lreal_); + │ ^^^^^^ Implicit downcast from 'LREAL' to 'LINT'. diff --git a/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__program_call_parameter_validation.snap b/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__program_call_parameter_validation.snap index ccd2988c30..b6a9bb04c0 100644 --- a/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__program_call_parameter_validation.snap +++ b/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__program_call_parameter_validation.snap @@ -32,6 +32,12 @@ error[E037]: Invalid assignment: cannot assign 'REF_TO WSTRING' to 'DINT' 25 │ prog(input1 := var2, inout1 := var3, output1 => var4); // invalid types assigned │ ^^^^^^^^^^^^^^ Invalid assignment: cannot assign 'REF_TO WSTRING' to 'DINT' +warning[E067]: Implicit downcast from 'REAL' to 'DINT'. + ┌─ :25:61 + │ +25 │ prog(input1 := var2, inout1 := var3, output1 => var4); // invalid types assigned + │ ^^^^ Implicit downcast from 'REAL' to 'DINT'. + error[E037]: Invalid assignment: cannot assign 'STRING' to 'DINT' ┌─ :27:18 │ @@ -50,4 +56,8 @@ error[E037]: Invalid assignment: cannot assign 'REF_TO WSTRING' to 'DINT' 27 │ prog(var2, var3, var4); // invalid types assigned │ ^^^^ Invalid assignment: cannot assign 'REF_TO WSTRING' to 'DINT' - +warning[E067]: Implicit downcast from 'REAL' to 'DINT'. + ┌─ :27:30 + │ +27 │ prog(var2, var3, var4); // invalid types assigned + │ ^^^^ Implicit downcast from 'REAL' to 'DINT'. diff --git a/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__program_implicit_downcast.snap b/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__program_implicit_downcast.snap index cc7dc3d07d..54fb892dd7 100644 --- a/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__program_implicit_downcast.snap +++ b/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__program_implicit_downcast.snap @@ -2,10 +2,38 @@ source: src/validation/tests/statement_validation_tests.rs expression: "&diagnostics" --- +warning[E067]: Implicit downcast from 'LINT' to 'INT'. + ┌─ :11:17 + │ +11 │ var1_lint, // downcast + │ ^^^^^^^^^ Implicit downcast from 'LINT' to 'INT'. + +warning[E067]: Implicit downcast from 'LWORD' to 'DWORD'. + ┌─ :12:17 + │ +12 │ var_lword, // downcast + │ ^^^^^^^^^ Implicit downcast from 'LWORD' to 'DWORD'. + +warning[E067]: Implicit downcast from 'INT' to 'SINT'. + ┌─ :14:17 + │ +14 │ INT#var1_lint, // downcast + │ ^^^^^^^^^^^^^ Implicit downcast from 'INT' to 'SINT'. + +warning[E067]: Implicit downcast from 'LINT' to 'INT'. + ┌─ :15:17 + │ +15 │ var2_lint, // downcast + │ ^^^^^^^^^ Implicit downcast from 'LINT' to 'INT'. + error[E037]: Invalid assignment: cannot assign 'WSTRING' to 'STRING' ┌─ :16:17 │ 16 │ var_wstr, // invalid │ ^^^^^^^^ Invalid assignment: cannot assign 'WSTRING' to 'STRING' - +warning[E067]: Implicit downcast from 'LINT' to 'DINT'. + ┌─ :17:17 + │ +17 │ var1_lint // downcast + │ ^^^^^^^^^ Implicit downcast from 'LINT' to 'DINT'. diff --git a/src/validation/tests/statement_validation_tests.rs b/src/validation/tests/statement_validation_tests.rs index 30418a7679..db4302bd8c 100644 --- a/src/validation/tests/statement_validation_tests.rs +++ b/src/validation/tests/statement_validation_tests.rs @@ -1321,7 +1321,7 @@ fn passing_compatible_numeric_types_to_functions_is_allowed() { "#, ); - assert!(diagnostics.is_empty()); + assert_snapshot!(diagnostics); } #[test] diff --git a/tests/integration/data/json/simple_program.st b/tests/integration/data/json/simple_program.st index 4d45f7e3f6..3bd848ecf2 100644 --- a/tests/integration/data/json/simple_program.st +++ b/tests/integration/data/json/simple_program.st @@ -4,5 +4,5 @@ PROGRAM prg b : REAL; END_VAR b := 1.5; - a := b; + a := INT#b; END_PROGRAM