From 75ca07a279f37aee1b2097ad73978a85d4968da1 Mon Sep 17 00:00:00 2001 From: Chris Rybicki Date: Mon, 19 Aug 2024 22:37:39 +0200 Subject: [PATCH] fix(compiler): improve error diagnostic for invalid string concat (#7025) Co-authored-by: wingbot <109207340+monadabot@users.noreply.github.com> Co-authored-by: monada-bot[bot] --- examples/tests/invalid/stringify.test.w | 8 ++++++ libs/wingc/src/type_check.rs | 25 +++++++++++------ tools/hangar/__snapshots__/invalid.ts.snap | 32 ++++++++++++++++++++++ 3 files changed, 56 insertions(+), 9 deletions(-) diff --git a/examples/tests/invalid/stringify.test.w b/examples/tests/invalid/stringify.test.w index 9f2231e8b3f..0cd33606a59 100644 --- a/examples/tests/invalid/stringify.test.w +++ b/examples/tests/invalid/stringify.test.w @@ -19,3 +19,11 @@ log(b); log(foo); // ^ Expected type to be "stringable", but got "Foo" instead + +let z = 42; + +log("value: " + z); +// ^ Binary operator '+' cannot be applied to operands of type 'str' and 'num' + +log(z + " is the value"); +// ^ Binary operator '+' cannot be applied to operands of type 'str' and 'num' diff --git a/libs/wingc/src/type_check.rs b/libs/wingc/src/type_check.rs index 0bd844934f7..4cf8d53b9d6 100644 --- a/libs/wingc/src/type_check.rs +++ b/libs/wingc/src/type_check.rs @@ -2296,17 +2296,24 @@ It should primarily be used in preflight or in inflights that are guaranteed to } else { // If any of the types are unresolved (error) then don't report this assuming the error has already been reported if !ltype.is_unresolved() && !rtype.is_unresolved() { - self.spanned_error( + let mut hints = vec![]; + // If one of the operands is a string type, add a hint to use string interpolation + if ltype.is_subtype_of(&self.types.string()) || rtype.is_subtype_of(&self.types.string()) { + hints.push("Consider using string interpolation: \"Hello, {name}\"".to_string()); + } + + self.spanned_error_with_hints( exp, format!( - "Binary operator '+' cannot be applied to operands of type '{}' and '{}'; only ({}, {}) and ({}, {}) are supported", - ltype, - rtype, - self.types.number(), - self.types.number(), - self.types.string(), - self.types.string(), - ), + "Binary operator '+' cannot be applied to operands of type '{}' and '{}'; only ({}, {}) and ({}, {}) are supported", + ltype, + rtype, + self.types.number(), + self.types.number(), + self.types.string(), + self.types.string(), + ), + &hints, ); } self.resolved_error() diff --git a/tools/hangar/__snapshots__/invalid.ts.snap b/tools/hangar/__snapshots__/invalid.ts.snap index 3b58593b615..e0ec8e10f2e 100644 --- a/tools/hangar/__snapshots__/invalid.ts.snap +++ b/tools/hangar/__snapshots__/invalid.ts.snap @@ -988,6 +988,8 @@ error: Binary operator '+' cannot be applied to operands of type 'num' and 'str' | 185 | 2 + "2"; | ^^^^^^^ + | + = hint: Consider using string interpolation: "Hello, {name}" error: Expected type to be "num", but got "str" instead @@ -1002,6 +1004,8 @@ error: Binary operator '+' cannot be applied to operands of type 'num' and 'str' | 198 | 2 + "2"; | ^^^^^^^ + | + = hint: Consider using string interpolation: "Hello, {name}" error: Expected type to be "str", but got "num" instead @@ -1016,6 +1020,8 @@ error: Binary operator '+' cannot be applied to operands of type 'num' and 'str' | 210 | 2 + "2"; | ^^^^^^^ + | + = hint: Consider using string interpolation: "Hello, {name}" error: Expected type to be "num", but got "str" instead @@ -1030,6 +1036,8 @@ error: Binary operator '+' cannot be applied to operands of type 'num' and 'str' | 221 | 2 + "2"; | ^^^^^^^ + | + = hint: Consider using string interpolation: "Hello, {name}" error: Expected type to be "str", but got "num" instead @@ -2307,6 +2315,8 @@ error: Binary operator '+' cannot be applied to operands of type 'num' and 'str' | 36 | let var x = 3 + "hello"; | ^^^^^^^^^^^ + | + = hint: Consider using string interpolation: "Hello, {name}" error: Unsupported reassignment of element of type unresolved @@ -4629,6 +4639,24 @@ error: Expected type to be "stringable", but got "Foo" instead | = hint: str, num, bool, json, and enums are stringable + +error: Binary operator '+' cannot be applied to operands of type 'str' and 'num'; only (num, num) and (str, str) are supported + --> ../../../examples/tests/invalid/stringify.test.w:25:5 + | +25 | log("value: " + z); + | ^^^^^^^^^^^^^ + | + = hint: Consider using string interpolation: "Hello, {name}" + + +error: Binary operator '+' cannot be applied to operands of type 'num' and 'str'; only (num, num) and (str, str) are supported + --> ../../../examples/tests/invalid/stringify.test.w:28:5 + | +28 | log(z + " is the value"); + | ^^^^^^^^^^^^^^^^^^^ + | + = hint: Consider using string interpolation: "Hello, {name}" + Tests 1 failed (1) Snapshots 1 skipped Test Files 1 failed (1) @@ -4974,6 +5002,8 @@ exports[`types_strings_arithmetic.test.w 1`] = ` | 1 | let e1 = 2 + "2"; | ^^^^^^^ + | + = hint: Consider using string interpolation: "Hello, {name}" error: Expected type to be "num", but got "str" instead @@ -5188,6 +5218,8 @@ error: Binary operator '+' cannot be applied to operands of type 'num' and 'str' | 20 | this.bucket.assert(2 + "2"); | ^^^^^^^ + | + = hint: Consider using string interpolation: "Hello, {name}" error: Member "assert" does not exist in "Bucket"