From 31bfe613b0941137b3ce9ce33499a4a4aac607c6 Mon Sep 17 00:00:00 2001 From: Dennis Date: Sat, 22 Mar 2025 22:59:00 +0100 Subject: [PATCH] Require adjacent auto ref return as well (#21061) --- changelog/dmd.auto-ref-return.dd | 12 ++++++++++++ compiler/src/dmd/funcsem.d | 12 +++++++++++- compiler/test/fail_compilation/diag9679.d | 19 +++++++++++-------- 3 files changed, 34 insertions(+), 9 deletions(-) create mode 100644 changelog/dmd.auto-ref-return.dd diff --git a/changelog/dmd.auto-ref-return.dd b/changelog/dmd.auto-ref-return.dd new file mode 100644 index 0000000000..a8872245b3 --- /dev/null +++ b/changelog/dmd.auto-ref-return.dd @@ -0,0 +1,12 @@ +Keywords `auto` and `ref` must be adjacent for `auto ref` return. + +Similar to `auto ref` parameters in 2.111, it's now deprecated to declare an `auto ref` return type without putting those two keywords next to each other as well. + +--- +ref auto int f() => 3; +auto { ref int g() => 3; } + +// Correction: +auto ref f() => 3; +auto ref g() => 3; +--- diff --git a/compiler/src/dmd/funcsem.d b/compiler/src/dmd/funcsem.d index 71d3dfa5f0..0a8a574c59 100644 --- a/compiler/src/dmd/funcsem.d +++ b/compiler/src/dmd/funcsem.d @@ -235,6 +235,17 @@ void funcDeclarationSemantic(Scope* sc, FuncDeclaration funcdecl) if ((funcdecl.storage_class & STC.TYPECTOR) && !(ad || funcdecl.isNested())) funcdecl.storage_class &= ~STC.TYPECTOR; + auto tf = funcdecl.type.isTypeFunction(); + if ((funcdecl.storage_class & STC.auto_) && tf.isRef && !funcdecl.inferRetType) + { + if (!(funcdecl.storage_class & STC.autoref)) + { + // @@@DEPRECATED_2.122@@@ + // Deprecated in 2.112, turn into an error in 2.122 + deprecation(funcdecl.loc, "`auto ref` return type must have `auto` and `ref` adjacent"); + funcdecl.storage_class |= STC.autoref; + } + } //printf("function storage_class = x%llx, sc.stc = x%llx, %x\n", storage_class, sc.stc, Declaration.isFinal()); if (sc.traitsCompiles) @@ -313,7 +324,6 @@ void funcDeclarationSemantic(Scope* sc, FuncDeclaration funcdecl) sc = sc.push(); sc.stc |= funcdecl.storage_class & (STC.disable | STC.deprecated_); // forward to function type - TypeFunction tf = funcdecl.type.toTypeFunction(); if (sc.func) { /* If the nesting parent is pure without inference, diff --git a/compiler/test/fail_compilation/diag9679.d b/compiler/test/fail_compilation/diag9679.d index 22e94e5759..50b8717adf 100644 --- a/compiler/test/fail_compilation/diag9679.d +++ b/compiler/test/fail_compilation/diag9679.d @@ -3,13 +3,14 @@ TEST_OUTPUT: --- fail_compilation/diag9679.d(93): Deprecation: `auto` and `ref` storage classes should be adjacent fail_compilation/diag9679.d(93): Deprecation: `auto` and `ref` storage classes should be adjacent -fail_compilation/diag9679.d(15): Error: rvalue `1` cannot be assigned to `ref n` -fail_compilation/diag9679.d(16): Error: variable `diag9679.main.n` - storage class `auto` has no effect if type is not inferred, did you mean `scope`? -fail_compilation/diag9679.d(17): Error: variable `diag9679.main.S.a` - field declarations cannot be `ref` -fail_compilation/diag9679.d(24): Error: returning `r` escapes a reference to local variable `i` +fail_compilation/diag9679.d(94): Deprecation: `auto ref` return type must have `auto` and `ref` adjacent +fail_compilation/diag9679.d(100): Deprecation: `auto ref` return type must have `auto` and `ref` adjacent +fail_compilation/diag9679.d(16): Error: rvalue `1` cannot be assigned to `ref n` +fail_compilation/diag9679.d(17): Error: variable `diag9679.main.n` - storage class `auto` has no effect if type is not inferred, did you mean `scope`? +fail_compilation/diag9679.d(18): Error: variable `diag9679.main.S.a` - field declarations cannot be `ref` +fail_compilation/diag9679.d(25): Error: returning `r` escapes a reference to local variable `i` --- */ - void main() { if (ref n = 1) {} @@ -60,7 +61,6 @@ fail_compilation/diag9679.d(96): Error: variable `x` - `auto ref` variable must --- */ - void test5() { ref int r5; @@ -90,8 +90,11 @@ void test9() auto ref int y = void; } -void testKeywordOrder()(ref auto int x, auto const ref float y) {} -void testKeywordOrder() +void testKeywordOrder()(ref auto int x, auto const ref float y) {}; +ref auto int testKeywordOrder() { ref auto int x = 3; + return 3; } + +auto { ref int autoFromScope() => 3; }