From 0e28ba25599a2c133284fdad9efbd248ffdec5e9 Mon Sep 17 00:00:00 2001 From: Elias Batek Date: Tue, 18 Feb 2025 04:38:18 +0100 Subject: [PATCH] Fix #20888 - Compiler spits out implicit conversion technobabble when a return statement doesn't match the return type of a function --- compiler/src/dmd/semantic3.d | 32 ++++++++- compiler/test/fail_compilation/diag20888.d | 71 +++++++++++++++++++ compiler/test/fail_compilation/fail100.d | 2 +- compiler/test/fail_compilation/fail13498.d | 2 +- compiler/test/fail_compilation/fail20073.d | 2 +- compiler/test/fail_compilation/fail20376.d | 2 +- compiler/test/fail_compilation/noreturn2.d | 2 +- compiler/test/fail_compilation/shared.d | 2 +- compiler/test/fail_compilation/test14538.d | 2 +- .../test/fail_compilation/testInference.d | 34 ++++----- 10 files changed, 126 insertions(+), 25 deletions(-) create mode 100644 compiler/test/fail_compilation/diag20888.d diff --git a/compiler/src/dmd/semantic3.d b/compiler/src/dmd/semantic3.d index 349e108a2166..f7a7ce150b32 100644 --- a/compiler/src/dmd/semantic3.d +++ b/compiler/src/dmd/semantic3.d @@ -933,7 +933,37 @@ private extern(C++) final class Semantic3Visitor : Visitor // if a copy constructor is present, the return type conversion will be handled by it const hasCopyCtor = exp.type.ty == Tstruct && (cast(TypeStruct)exp.type).sym.hasCopyCtor; if (!hasCopyCtor || !exp.isLvalue()) - exp = exp.implicitCastTo(sc2, tret); + { + const errors = global.startGagging(); + auto implicitlyCastedExp = exp.implicitCastTo(sc2, tret); + global.endGagging(errors); + + // + if (implicitlyCastedExp.isErrorExp()) + { + auto types = toAutoQualChars(exp.type, tret); + error( + exp.loc, + "return value `%s` of type `%s` does not match return type `%s`" + ~ ", and cannot be implicitly converted", + exp.toErrMsg(), + types[0], + types[1], + ); + + if (const func = exp.type.isFunction_Delegate_PtrToFunction()) + if (func.next.equals(tret)) + errorSupplemental( + exp.loc, + "Did you intend to call the %s?", + (exp.type.isPtrToFunction()) + ? "function pointer" + : exp.type.kind + ); + } + + exp = implicitlyCastedExp; + } exp = exp.optimize(WANTvalue); diff --git a/compiler/test/fail_compilation/diag20888.d b/compiler/test/fail_compilation/diag20888.d new file mode 100644 index 000000000000..84af42533fcc --- /dev/null +++ b/compiler/test/fail_compilation/diag20888.d @@ -0,0 +1,71 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/diag20888.d(24): Error: return value `callback` of type `int function()` does not match return type `int`, and cannot be implicitly converted +fail_compilation/diag20888.d(24): Did you intend to call the function pointer? +fail_compilation/diag20888.d(29): Error: return value `s` of type `string` does not match return type `int`, and cannot be implicitly converted +fail_compilation/diag20888.d(34): Error: return value `callback` of type `int delegate()` does not match return type `int`, and cannot be implicitly converted +fail_compilation/diag20888.d(34): Did you intend to call the delegate? +fail_compilation/diag20888.d(39): Error: return value `callback` of type `int delegate()` does not match return type `int`, and cannot be implicitly converted +fail_compilation/diag20888.d(39): Did you intend to call the delegate? +fail_compilation/diag20888.d(44): Error: return value `callback` of type `int delegate()*` does not match return type `int`, and cannot be implicitly converted +fail_compilation/diag20888.d(49): Error: return value `callback` of type `int delegate()` does not match return type `string`, and cannot be implicitly converted +fail_compilation/diag20888.d(54): Error: return value `() => 3755` of type `int function() pure nothrow @nogc @safe` does not match return type `int`, and cannot be implicitly converted +fail_compilation/diag20888.d(54): Did you intend to call the function pointer? +fail_compilation/diag20888.d(59): Error: `return` expression expected +fail_compilation/diag20888.d(64): Error: cannot return non-void from `void` function +fail_compilation/diag20888.d(70): Error: return value `() => i` of type `int delegate() pure nothrow @nogc @safe` does not match return type `int`, and cannot be implicitly converted +fail_compilation/diag20888.d(70): Did you intend to call the delegate? +--- +*/ + +int alpha(int function() callback) +{ + return callback; +} + +int beta(string s) +{ + return s; +} + +int gamma(int delegate() callback) +{ + return callback; +} + +int delta(int delegate() callback) +{ + return callback; +} + +int epsilon(int delegate()* callback) +{ + return callback; // no supplemental yet +} + +string zeta(int delegate() callback) +{ + return callback; +} + +int eta() +{ + return () => 0xEAB; +} + +int theta() +{ + return; +} + +void iota() +{ + return 0xEAB; +} + +int kappa() +{ + int i = 0xEAB; + return () { return i; }; +} diff --git a/compiler/test/fail_compilation/fail100.d b/compiler/test/fail_compilation/fail100.d index a8189ecb0af7..0ebb92102394 100644 --- a/compiler/test/fail_compilation/fail100.d +++ b/compiler/test/fail_compilation/fail100.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail100.d(24): Error: cannot implicitly convert expression `f` of type `Class[]` to `I[]` +fail_compilation/fail100.d(24): Error: return value `f` of type `Class[]` does not match return type `I[]`, and cannot be implicitly converted --- */ diff --git a/compiler/test/fail_compilation/fail13498.d b/compiler/test/fail_compilation/fail13498.d index 27f47b3f7abd..e8099f3cd80b 100644 --- a/compiler/test/fail_compilation/fail13498.d +++ b/compiler/test/fail_compilation/fail13498.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail13498.d(11): Error: cannot implicitly convert expression `"foo"` of type `string` to `int` +fail_compilation/fail13498.d(11): Error: return value `"foo"` of type `string` does not match return type `int`, and cannot be implicitly converted fail_compilation/fail13498.d(16): Error: template instance `fail13498.foo!()` error instantiating --- */ diff --git a/compiler/test/fail_compilation/fail20073.d b/compiler/test/fail_compilation/fail20073.d index 01a9ede4622c..5353016d797d 100644 --- a/compiler/test/fail_compilation/fail20073.d +++ b/compiler/test/fail_compilation/fail20073.d @@ -3,7 +3,7 @@ TEST_OUTPUT: --- fail_compilation/fail20073.d(20): Error: cannot implicitly convert expression `s` of type `S` to `string` -fail_compilation/fail20073.d(21): Error: cannot implicitly convert expression `s` of type `S` to `string` +fail_compilation/fail20073.d(21): Error: return value `s` of type `S` does not match return type `string`, and cannot be implicitly converted --- */ diff --git a/compiler/test/fail_compilation/fail20376.d b/compiler/test/fail_compilation/fail20376.d index 8410af535e2f..dbd0061ef880 100644 --- a/compiler/test/fail_compilation/fail20376.d +++ b/compiler/test/fail_compilation/fail20376.d @@ -3,7 +3,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail20376.d(17): Error: cannot implicitly convert expression `Foo()` of type `Foo` to `ubyte` +fail_compilation/fail20376.d(17): Error: return value `Foo()` of type `Foo` does not match return type `ubyte`, and cannot be implicitly converted --- */ diff --git a/compiler/test/fail_compilation/noreturn2.d b/compiler/test/fail_compilation/noreturn2.d index 66c1d5287f59..ec6bd3ebce99 100644 --- a/compiler/test/fail_compilation/noreturn2.d +++ b/compiler/test/fail_compilation/noreturn2.d @@ -55,7 +55,7 @@ NR returns() /+ TEST_OUTPUT: --- -fail_compilation/noreturn2.d(64): Error: cannot implicitly convert expression `1` of type `int` to `noreturn` +fail_compilation/noreturn2.d(64): Error: return value `1` of type `int` does not match return type `noreturn`, and cannot be implicitly converted --- +/ diff --git a/compiler/test/fail_compilation/shared.d b/compiler/test/fail_compilation/shared.d index 1af95949d7aa..7ab1d7cd1737 100644 --- a/compiler/test/fail_compilation/shared.d +++ b/compiler/test/fail_compilation/shared.d @@ -96,7 +96,7 @@ fail_compilation/shared.d(2216): return value `getSharedObject()` is not fail_compilation/shared.d(2222): Error: direct access to shared `a` is not allowed, see `core.atomic` fail_compilation/shared.d(2220): Error: function `shared.test_inference_4` function returns `shared` but cannot be inferred `ref` fail_compilation/shared.d(2222): cannot implicitly convert `a` of type `shared(const(Object))` to `object.Object` -fail_compilation/shared.d(2222): Error: cannot implicitly convert expression `a` of type `shared(const(Object))` to `object.Object` +fail_compilation/shared.d(2222): Error: return value `a` of type `shared(const(Object))` does not match return type `object.Object`, and cannot be implicitly converted --- */ diff --git a/compiler/test/fail_compilation/test14538.d b/compiler/test/fail_compilation/test14538.d index 1ad2126fd431..c912d165a2dc 100644 --- a/compiler/test/fail_compilation/test14538.d +++ b/compiler/test/fail_compilation/test14538.d @@ -2,7 +2,7 @@ /* TEST_OUTPUT: --- -fail_compilation/test14538.d(18): Error: cannot implicitly convert expression `x ? cast(uint)this.fCells[x].code : 32u` of type `uint` to `Cell` +fail_compilation/test14538.d(18): Error: return value `x ? cast(uint)this.fCells[x].code : 32u` of type `uint` does not match return type `Cell`, and cannot be implicitly converted --- */ diff --git a/compiler/test/fail_compilation/testInference.d b/compiler/test/fail_compilation/testInference.d index 1b4b1223daae..fbbde87c060f 100644 --- a/compiler/test/fail_compilation/testInference.d +++ b/compiler/test/fail_compilation/testInference.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/testInference.d(24): Error: cannot implicitly convert expression `this.a` of type `inout(A8998)` to `immutable(A8998)` +fail_compilation/testInference.d(24): Error: return value `this.a` of type `inout(A8998)` does not match return type `immutable(A8998)`, and cannot be implicitly converted --- */ @@ -28,10 +28,10 @@ class C8998 /* TEST_OUTPUT: --- -fail_compilation/testInference.d(39): Error: cannot implicitly convert expression `s` of type `const(char[])` to `string` -fail_compilation/testInference.d(44): Error: cannot implicitly convert expression `a` of type `int[]` to `immutable(int[])` -fail_compilation/testInference.d(49): Error: cannot implicitly convert expression `a` of type `int[]` to `immutable(int[])` -fail_compilation/testInference.d(54): Error: cannot implicitly convert expression `a` of type `int[]` to `immutable(int[])` +fail_compilation/testInference.d(39): Error: return value `s` of type `const(char[])` does not match return type `string`, and cannot be implicitly converted +fail_compilation/testInference.d(44): Error: return value `a` of type `int[]` does not match return type `immutable(int[])`, and cannot be implicitly converted +fail_compilation/testInference.d(49): Error: return value `a` of type `int[]` does not match return type `immutable(int[])`, and cannot be implicitly converted +fail_compilation/testInference.d(54): Error: return value `a` of type `int[]` does not match return type `immutable(int[])`, and cannot be implicitly converted --- */ string foo(in char[] s) pure @@ -58,18 +58,18 @@ immutable(int[]) x3(immutable(int[]) org) /*pure*/ /* TEST_OUTPUT: --- -fail_compilation/testInference.d(94): Error: cannot implicitly convert expression `c` of type `testInference.C1` to `immutable(C1)` -fail_compilation/testInference.d(95): Error: cannot implicitly convert expression `c` of type `testInference.C1` to `immutable(C1)` -fail_compilation/testInference.d(96): Error: cannot implicitly convert expression `c` of type `testInference.C3` to `immutable(C3)` -fail_compilation/testInference.d(97): Error: cannot implicitly convert expression `c` of type `testInference.C3` to `immutable(C3)` +fail_compilation/testInference.d(94): Error: return value `c` of type `testInference.C1` does not match return type `immutable(C1)`, and cannot be implicitly converted +fail_compilation/testInference.d(95): Error: return value `c` of type `testInference.C1` does not match return type `immutable(C1)`, and cannot be implicitly converted +fail_compilation/testInference.d(96): Error: return value `c` of type `testInference.C3` does not match return type `immutable(C3)`, and cannot be implicitly converted +fail_compilation/testInference.d(97): Error: return value `c` of type `testInference.C3` does not match return type `immutable(C3)`, and cannot be implicitly converted fail_compilation/testInference.d(100): Error: undefined identifier `X1`, did you mean function `x1`? -fail_compilation/testInference.d(106): Error: cannot implicitly convert expression `s` of type `S1` to `immutable(S1)` -fail_compilation/testInference.d(109): Error: cannot implicitly convert expression `a` of type `int*[]` to `immutable(int*[])` -fail_compilation/testInference.d(110): Error: cannot implicitly convert expression `a` of type `const(int)*[]` to `immutable(int*[])` -fail_compilation/testInference.d(114): Error: cannot implicitly convert expression `s` of type `S2` to `immutable(S2)` -fail_compilation/testInference.d(115): Error: cannot implicitly convert expression `s` of type `S2` to `immutable(S2)` -fail_compilation/testInference.d(116): Error: cannot implicitly convert expression `s` of type `S2` to `immutable(S2)` -fail_compilation/testInference.d(118): Error: cannot implicitly convert expression `a` of type `const(int)*[]` to `immutable(int*[])` +fail_compilation/testInference.d(106): Error: return value `s` of type `S1` does not match return type `immutable(S1)`, and cannot be implicitly converted +fail_compilation/testInference.d(109): Error: return value `a` of type `int*[]` does not match return type `immutable(int*[])`, and cannot be implicitly converted +fail_compilation/testInference.d(110): Error: return value `a` of type `const(int)*[]` does not match return type `immutable(int*[])`, and cannot be implicitly converted +fail_compilation/testInference.d(114): Error: return value `s` of type `S2` does not match return type `immutable(S2)`, and cannot be implicitly converted +fail_compilation/testInference.d(115): Error: return value `s` of type `S2` does not match return type `immutable(S2)`, and cannot be implicitly converted +fail_compilation/testInference.d(116): Error: return value `s` of type `S2` does not match return type `immutable(S2)`, and cannot be implicitly converted +fail_compilation/testInference.d(118): Error: return value `a` of type `const(int)*[]` does not match return type `immutable(int*[])`, and cannot be implicitly converted --- */ immutable(Object) get(inout int*) pure @@ -122,7 +122,7 @@ immutable(int*[]) bar2c( S2 prm) pure { immutable(int)*[] a; return /* TEST_OUTPUT: --- -fail_compilation/testInference.d(134): Error: cannot implicitly convert expression `f10063(cast(inout(void*))p)` of type `inout(void)*` to `immutable(void)*` +fail_compilation/testInference.d(134): Error: return value `f10063(cast(inout(void*))p)` of type `inout(void)*` does not match return type `immutable(void)*`, and cannot be implicitly converted --- */ inout(void)* f10063(inout void* p) pure