From a03aa271f8a7b1847a95919bf44ef0e0388ddc37 Mon Sep 17 00:00:00 2001 From: Abul Hossain Khan <140191921+abulgit@users.noreply.github.com> Date: Mon, 7 Apr 2025 11:39:25 +0530 Subject: [PATCH] Improve override suggestions to exclude final methods (#21138) --- compiler/src/dmd/funcsem.d | 40 +++++++++++++++++++++++ compiler/test/fail_compilation/fix19613.d | 16 +++++++++ 2 files changed, 56 insertions(+) create mode 100644 compiler/test/fail_compilation/fix19613.d diff --git a/compiler/src/dmd/funcsem.d b/compiler/src/dmd/funcsem.d index 8a46dda270..3daafa3f07 100644 --- a/compiler/src/dmd/funcsem.d +++ b/compiler/src/dmd/funcsem.d @@ -986,6 +986,46 @@ void funcDeclarationSemantic(Scope* sc, FuncDeclaration funcdecl) errorSupplemental(fd.loc, "Function `%s` contains errors in its declaration, therefore it cannot be correctly overridden", fd.toPrettyChars()); } + else if (fd.isFinalFunc()) + { + // When trying to override a final method, don't suggest it as a candidate(Issue #19613) + .error(funcdecl.loc, "%s `%s` does not override any function", funcdecl.kind, funcdecl.toPrettyChars); + + // Look for a non-final method with the same name to suggest as an alternative + auto cdparent = fd.parent ? fd.parent.isClassDeclaration() : null; + if (cdparent) + { + Dsymbol nonFinalAlt = null; + + auto overloadableSyms = cdparent.symtab.lookup(fd.ident); + if (overloadableSyms) + { + // Check each overload to find one that's not final + overloadApply(overloadableSyms, (Dsymbol s) + { + if (auto funcAlt = s.isFuncDeclaration()) + { + if (funcAlt != fd && !funcAlt.isFinalFunc()) + { + nonFinalAlt = funcAlt; + return 1; + } + } + return 0; + }); + + // Provide a helpful suggestion if we found a viable alternative + if (nonFinalAlt) + { + auto funcAlt = nonFinalAlt.isFuncDeclaration(); + OutBuffer buf2; + functionToBufferFull(cast(TypeFunction)(funcAlt.type), buf2, + new Identifier(funcAlt.toPrettyChars()), hgs, null); + errorSupplemental(funcdecl.loc, "Did you mean to override `%s`?", buf2.peekChars()); + } + } + } + } else { functionToBufferFull(cast(TypeFunction)(fd.type), buf1, diff --git a/compiler/test/fail_compilation/fix19613.d b/compiler/test/fail_compilation/fix19613.d new file mode 100644 index 0000000000..beca56fd70 --- /dev/null +++ b/compiler/test/fail_compilation/fix19613.d @@ -0,0 +1,16 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/fix19613.d(15): Error: function `fix19613.B.a` cannot override `final` function `fix19613.A.a` +fail_compilation/fix19613.d(15): Error: function `fix19613.B.a` does not override any function +fail_compilation/fix19613.d(15): Did you mean to override `void fix19613.A.a(string)`? +--- +*/ + +class A { + final void a(int) {} + void a(string) {} +} +class B : A { + override void a(int) {} +}