Require adjacent auto ref keywords

This commit is contained in:
Dennis Korpel 2024-08-14 17:10:24 +02:00 committed by The Dlang Bot
parent dfcee8d88b
commit ae2dc11619
5 changed files with 49 additions and 9 deletions

View file

@ -0,0 +1,18 @@
`auto ref` variables must have adjacent keywords `auto` and `ref`
It's now deprecated to declare `auto ref` parameters without putting those two keywords next to eachother.
This way it's clear that `auto ref` semantics are intended, rather than `ref` and `auto` semantics separately.
For the newly introduced `ref` local / global variables, it's an error immediately.
---
void t()(ref const auto int x) // Deprecation
{
ref auto y = x; // Error
}
// Correction:
void t()(auto ref const int x)
{
auto ref y = x;
}
---

View file

@ -616,7 +616,13 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
dsym.storage_class |= ad.storage_class & STC.TYPECTOR;
if ((dsym.storage_class & STC.auto_) && (dsym.storage_class & STC.ref_))
dsym.storage_class |= STC.autoref;
{
if (!(dsym.storage_class & STC.autoref))
{
.error(dsym.loc, "%s `%s` - `auto ref` variable must have `auto` and `ref` adjacent", dsym.kind, dsym.toChars());
dsym.storage_class |= STC.autoref;
}
}
/* If auto type inference, do the inference
*/

View file

@ -651,6 +651,8 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
case TOK.auto_:
stc = STC.auto_;
if (peekNext() == TOK.ref_)
stc |= STC.autoref;
goto Lstc;
case TOK.scope_:
@ -2935,6 +2937,8 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
case TOK.auto_:
stc = STC.auto_;
if (peekNext() == TOK.ref_)
stc |= STC.autoref;
goto L2;
case TOK.return_:
@ -2952,8 +2956,10 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
// if stcx is not a power of 2
if (stcx & (stcx - 1) && !(stcx == (STC.in_ | STC.ref_)))
error("incompatible parameter storage classes");
//if ((storageClass & STC.scope_) && (storageClass & (STC.ref_ | STC.out_)))
//error("scope cannot be ref or out");
// Deprecated in 2.111
if ((storageClass & STC.auto_) && (storageClass & STC.ref_) && !(storageClass & STC.autoref))
deprecation("`auto` and `ref` storage classes should be adjacent");
const tv = peekNext();
Loc loc;
@ -4259,6 +4265,8 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
case TOK.auto_:
stc = STC.auto_;
if (peekNext() == TOK.ref_)
stc |= STC.autoref;
goto L1;
case TOK.scope_:
@ -5079,7 +5087,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
{
// function auto ref (parameters) { statements... }
// delegate auto ref (parameters) { statements... }
stc = STC.auto_ | STC.ref_;
stc = STC.auto_ | STC.ref_ | STC.autoref;
nextToken();
}
else
@ -5121,7 +5129,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
{
// auto ref (parameters) => expression
// auto ref (parameters) { statements... }
stc = STC.auto_ | STC.ref_;
stc = STC.auto_ | STC.ref_ | STC.autoref;
nextToken();
}
else
@ -5678,6 +5686,8 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
case TOK.auto_:
stc = STC.auto_;
if (peekNext() == TOK.ref_)
stc |= STC.autoref;
break;
case TOK.const_:

View file

@ -1,6 +1,8 @@
/* REQUIRED_ARGS: -verrors=0
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`
@ -8,8 +10,6 @@ fail_compilation/diag9679.d(24): Error: returning `r` escapes a reference to loc
---
*/
void main()
{
if (ref n = 1) {}
@ -56,11 +56,11 @@ fail_compilation/diag9679.d(77): Error: type `immutable(int)` cannot be assigned
fail_compilation/diag9679.d(84): Error: returning `x` escapes a reference to local variable `x`
fail_compilation/diag9679.d(89): Error: variable `diag9679.test9.x` - void initializer not allowed for `ref` variable
fail_compilation/diag9679.d(90): Error: variable `diag9679.test9.y` - void initializer not allowed for `ref` variable
fail_compilation/diag9679.d(96): Error: variable `x` - `auto ref` variable must have `auto` and `ref` adjacent
---
*/
void test5()
{
ref int r5;
@ -89,3 +89,9 @@ void test9()
ref int x = void;
auto ref int y = void;
}
void testKeywordOrder()(ref auto int x, auto const ref float y) {}
void testKeywordOrder()
{
ref auto int x = 3;
}

View file

@ -1699,7 +1699,7 @@ template forward(args...)
{
x_ = forward!x;
}
this()(auto const ref X x)
this()(auto ref const X x)
{
x_ = forward!x;
}