Skip to content

Commit 04bc382

Browse files
authored
Merge pull request #10709 from CodaFi/a-touch-of-varnish
2 parents b76794c + 43f2939 commit 04bc382

File tree

11 files changed

+43
-118
lines changed

11 files changed

+43
-118
lines changed

include/swift/AST/Decl.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4509,7 +4509,7 @@ class VarDecl : public AbstractStorageDecl {
45094509
class ParamDecl : public VarDecl {
45104510
Identifier ArgumentName;
45114511
SourceLoc ArgumentNameLoc;
4512-
SourceLoc LetVarInOutLoc;
4512+
SourceLoc SpecifierLoc;
45134513

45144514
struct StoredDefaultArgument {
45154515
Expr *DefaultArg = nullptr;
@@ -4530,7 +4530,7 @@ class ParamDecl : public VarDecl {
45304530
DefaultArgumentKind defaultArgumentKind = DefaultArgumentKind::None;
45314531

45324532
public:
4533-
ParamDecl(bool isLet, SourceLoc letVarInOutLoc, SourceLoc argumentNameLoc,
4533+
ParamDecl(bool isLet, SourceLoc specifierLoc, SourceLoc argumentNameLoc,
45344534
Identifier argumentName, SourceLoc parameterNameLoc,
45354535
Identifier parameterName, Type ty, DeclContext *dc);
45364536

@@ -4548,7 +4548,7 @@ class ParamDecl : public VarDecl {
45484548
/// was specified separately from the parameter name.
45494549
SourceLoc getArgumentNameLoc() const { return ArgumentNameLoc; }
45504550

4551-
SourceLoc getLetVarInOutLoc() const { return LetVarInOutLoc; }
4551+
SourceLoc getSpecifierLoc() const { return SpecifierLoc; }
45524552

45534553
bool isTypeLocImplicit() const { return IsTypeLocImplicit; }
45544554
void setIsTypeLocImplicit(bool val) { IsTypeLocImplicit = val; }

include/swift/AST/DiagnosticsParse.def

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -814,8 +814,8 @@ ERROR(inout_as_attr_disallowed,none,
814814
ERROR(parameter_inout_var_let_repeated,none,
815815
"parameter may not have multiple 'inout', 'var', or 'let' specifiers",
816816
())
817-
ERROR(parameter_let_as_attr,none,
818-
"'let' as a parameter attribute is not allowed", ())
817+
ERROR(parameter_let_var_as_attr,none,
818+
"'%select{var|let}0' as a parameter attribute is not allowed", (unsigned))
819819

820820

821821
ERROR(expected_behavior_name,none,

include/swift/AST/DiagnosticsSema.def

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,10 +1006,6 @@ ERROR(attribute_requires_operator_identifier,none,
10061006
ERROR(attribute_requires_single_argument,none,
10071007
"'%0' requires a function with one argument", (StringRef))
10081008

1009-
ERROR(var_parameter_not_allowed,none,
1010-
"parameters may not have the 'var' specifier", ())
1011-
1012-
10131009
ERROR(mutating_invalid_global_scope,none,
10141010
"'mutating' is only valid on methods", ())
10151011
ERROR(mutating_invalid_classes,none,

include/swift/Parse/Parser.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -977,15 +977,14 @@ class Parser {
977977
/// Any declaration attributes attached to the parameter.
978978
DeclAttributes Attrs;
979979

980-
/// The location of the 'let', 'var', or 'inout' keyword, if present.
981-
SourceLoc LetVarInOutLoc;
980+
/// The location of the 'inout' keyword, if present.
981+
SourceLoc SpecifierLoc;
982982

983983
enum SpecifierKindTy {
984-
Let,
985-
Var,
984+
None,
986985
InOut
987986
};
988-
SpecifierKindTy SpecifierKind = Let; // Defaults to let.
987+
SpecifierKindTy SpecifierKind = None; // Defaults to 'no value'.
989988

990989
/// The location of the first name.
991990
///

lib/AST/Decl.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4114,13 +4114,13 @@ void VarDecl::emitLetToVarNoteIfSimple(DeclContext *UseDC) const {
41144114
}
41154115

41164116
ParamDecl::ParamDecl(bool isLet,
4117-
SourceLoc letVarInOutLoc, SourceLoc argumentNameLoc,
4117+
SourceLoc specifierLoc, SourceLoc argumentNameLoc,
41184118
Identifier argumentName, SourceLoc parameterNameLoc,
41194119
Identifier parameterName, Type ty, DeclContext *dc)
41204120
: VarDecl(DeclKind::Param, /*IsStatic*/false, /*IsLet*/isLet,
41214121
/*IsCaptureList*/false, parameterNameLoc, parameterName, ty, dc),
41224122
ArgumentName(argumentName), ArgumentNameLoc(argumentNameLoc),
4123-
LetVarInOutLoc(letVarInOutLoc) {
4123+
SpecifierLoc(specifierLoc) {
41244124
}
41254125

41264126
/// Clone constructor, allocates a new ParamDecl identical to the first.
@@ -4131,7 +4131,7 @@ ParamDecl::ParamDecl(ParamDecl *PD)
41314131
PD->hasType() ? PD->getType() : Type(), PD->getDeclContext()),
41324132
ArgumentName(PD->getArgumentName()),
41334133
ArgumentNameLoc(PD->getArgumentNameLoc()),
4134-
LetVarInOutLoc(PD->getLetVarInOutLoc()),
4134+
SpecifierLoc(PD->getSpecifierLoc()),
41354135
DefaultValueAndIsVariadic(nullptr, PD->DefaultValueAndIsVariadic.getInt()),
41364136
IsTypeLocImplicit(PD->IsTypeLocImplicit),
41374137
defaultArgumentKind(PD->defaultArgumentKind) {

lib/Parse/ParsePattern.cpp

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -184,20 +184,20 @@ Parser::parseParameterClause(SourceLoc &leftParenLoc,
184184
bool hasSpecifier = false;
185185
while (Tok.isAny(tok::kw_inout, tok::kw_let, tok::kw_var)) {
186186
if (!hasSpecifier) {
187-
if (Tok.is(tok::kw_let)) {
188-
diagnose(Tok, diag::parameter_let_as_attr)
189-
.fixItRemove(Tok.getLoc());
187+
if (Tok.is(tok::kw_inout)) {
188+
// This case is handled later when mapping to ParamDecls for
189+
// better fixits.
190+
param.SpecifierKind = ParsedParameter::InOut;
190191
} else {
191-
// We handle the var error in sema for a better fixit and inout is
192-
// handled later in this function for better fixits.
193-
param.SpecifierKind = Tok.is(tok::kw_inout) ? ParsedParameter::InOut :
194-
ParsedParameter::Var;
192+
diagnose(Tok, diag::parameter_let_var_as_attr,
193+
unsigned(Tok.is(tok::kw_let)))
194+
.fixItRemove(Tok.getLoc());
195195
}
196-
param.LetVarInOutLoc = consumeToken();
196+
param.SpecifierLoc = consumeToken();
197197
hasSpecifier = true;
198198
} else {
199-
// Redundant specifiers are fairly common, recognize, reject, and recover
200-
// from this gracefully.
199+
// Redundant specifiers are fairly common, recognize, reject, and
200+
// recover from this gracefully.
201201
diagnose(Tok, diag::parameter_inout_var_let_repeated)
202202
.fixItRemove(Tok.getLoc());
203203
consumeToken();
@@ -342,8 +342,8 @@ mapParsedParameters(Parser &parser,
342342
Identifier paramName, SourceLoc paramNameLoc)
343343
-> ParamDecl * {
344344
auto specifierKind = paramInfo.SpecifierKind;
345-
bool isLet = specifierKind == Parser::ParsedParameter::Let;
346-
auto param = new (ctx) ParamDecl(isLet, paramInfo.LetVarInOutLoc,
345+
bool isLet = specifierKind == Parser::ParsedParameter::None;
346+
auto param = new (ctx) ParamDecl(isLet, paramInfo.SpecifierLoc,
347347
argNameLoc, argName,
348348
paramNameLoc, paramName, Type(),
349349
parser.CurDeclContext);
@@ -360,7 +360,7 @@ mapParsedParameters(Parser &parser,
360360
if (auto type = paramInfo.Type) {
361361
// If 'inout' was specified, turn the type into an in-out type.
362362
if (specifierKind == Parser::ParsedParameter::InOut) {
363-
auto InOutLoc = paramInfo.LetVarInOutLoc;
363+
auto InOutLoc = paramInfo.SpecifierLoc;
364364
if (isa<InOutTypeRepr>(type)) {
365365
parser.diagnose(InOutLoc, diag::parameter_inout_var_let_repeated)
366366
.fixItRemove(InOutLoc);
@@ -380,9 +380,9 @@ mapParsedParameters(Parser &parser,
380380
param->getTypeLoc() = TypeLoc::withoutLoc(ErrorType::get(ctx));
381381
param->setInvalid();
382382
} else if (specifierKind == Parser::ParsedParameter::InOut) {
383-
parser.diagnose(paramInfo.LetVarInOutLoc, diag::inout_must_have_type);
384-
paramInfo.LetVarInOutLoc = SourceLoc();
385-
specifierKind = Parser::ParsedParameter::Let;
383+
parser.diagnose(paramInfo.SpecifierLoc, diag::inout_must_have_type);
384+
paramInfo.SpecifierLoc = SourceLoc();
385+
specifierKind = Parser::ParsedParameter::None;
386386
}
387387
return param;
388388
};

lib/Sema/TypeCheckPattern.cpp

Lines changed: 1 addition & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -671,74 +671,6 @@ static bool validateTypedPattern(TypeChecker &TC, DeclContext *DC,
671671
return hadError;
672672
}
673673

674-
static void diagnoseAndMigrateVarParameterToBody(ParamDecl *decl,
675-
AbstractFunctionDecl *func,
676-
TypeChecker &TC) {
677-
if (!func || !func->hasBody()) {
678-
// If there is no function body, just suggest removal.
679-
TC.diagnose(decl->getLetVarInOutLoc(),
680-
diag::var_parameter_not_allowed)
681-
.fixItRemove(decl->getLetVarInOutLoc());
682-
return;
683-
}
684-
// Insert the shadow copy. The computations that follow attempt to
685-
// 'best guess' the indentation and new lines so that the user
686-
// doesn't have to add any whitespace.
687-
auto declBody = func->getBody();
688-
689-
auto &SM = TC.Context.SourceMgr;
690-
691-
SourceLoc insertionStartLoc;
692-
std::string start;
693-
std::string end;
694-
695-
auto lBraceLine = SM.getLineNumber(declBody->getLBraceLoc());
696-
auto rBraceLine = SM.getLineNumber(declBody->getRBraceLoc());
697-
698-
if (!declBody->getNumElements()) {
699-
700-
// Empty function body.
701-
insertionStartLoc = declBody->getRBraceLoc();
702-
703-
if (lBraceLine == rBraceLine) {
704-
// Same line braces, means we probably have something
705-
// like {} as the func body. Insert directly into body with spaces.
706-
start = " ";
707-
end = " ";
708-
} else {
709-
// Different line braces, so use RBrace's indentation.
710-
end = "\n" + Lexer::getIndentationForLine(SM, declBody->
711-
getRBraceLoc()).str();
712-
start = " "; // Guess 4 spaces as extra indentation.
713-
}
714-
} else {
715-
auto firstLine = declBody->getElement(0);
716-
insertionStartLoc = firstLine.getStartLoc();
717-
if (lBraceLine == SM.getLineNumber(firstLine.getStartLoc())) {
718-
// Function on same line, insert with semi-colon. Not ideal but
719-
// better than weird space alignment.
720-
start = "";
721-
end = "; ";
722-
} else {
723-
start = "";
724-
end = "\n" + Lexer::getIndentationForLine(SM, firstLine.
725-
getStartLoc()).str();
726-
}
727-
}
728-
if (insertionStartLoc.isInvalid()) {
729-
TC.diagnose(decl->getLetVarInOutLoc(),
730-
diag::var_parameter_not_allowed)
731-
.fixItRemove(decl->getLetVarInOutLoc());
732-
return;
733-
}
734-
auto parameterName = decl->getNameStr().str();
735-
TC.diagnose(decl->getLetVarInOutLoc(),
736-
diag::var_parameter_not_allowed)
737-
.fixItRemove(decl->getLetVarInOutLoc())
738-
.fixItInsert(insertionStartLoc, start + "var " + parameterName + " = " +
739-
parameterName + end);
740-
}
741-
742674
static bool validateParameterType(ParamDecl *decl, DeclContext *DC,
743675
TypeResolutionOptions options,
744676
GenericTypeResolver &resolver,
@@ -772,16 +704,14 @@ static bool validateParameterType(ParamDecl *decl, DeclContext *DC,
772704

773705
// If the user did not explicitly write 'let', 'var', or 'inout', we'll let
774706
// type inference figure out what went wrong in detail.
775-
if (decl->getLetVarInOutLoc().isValid()) {
707+
if (decl->getSpecifierLoc().isValid()) {
776708
// If the param is not a 'let' and it is not an 'inout'.
777709
// It must be a 'var'. Provide helpful diagnostics like a shadow copy
778710
// in the function body to fix the 'var' attribute.
779711
if (!decl->isLet() &&
780712
!decl->isImplicit() &&
781713
(Ty.isNull() || !Ty->is<InOutType>()) &&
782714
!hadError) {
783-
auto func = dyn_cast_or_null<AbstractFunctionDecl>(DC);
784-
diagnoseAndMigrateVarParameterToBody(decl, func, TC);
785715
decl->setInvalid();
786716
hadError = true;
787717
}

test/Parse/invalid.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -82,18 +82,18 @@ func SR979d(let let a: Int) {} // expected-error {{'let' as a parameter attribu
8282
// expected-error @-1 {{parameter may not have multiple 'inout', 'var', or 'let' specifiers}} {{17-21=}}
8383
func SR979e(inout x: inout String) {} // expected-error {{parameter may not have multiple 'inout', 'var', or 'let' specifiers}} {{13-18=}}
8484
func SR979f(var inout x : Int) { // expected-error {{parameter may not have multiple 'inout', 'var', or 'let' specifiers}} {{17-23=}}
85-
// expected-error @-1 {{parameters may not have the 'var' specifier}} {{13-16=}}{{3-3=var x = x\n }}
86-
x += 10
85+
// expected-error @-1 {{'var' as a parameter attribute is not allowed}}
86+
x += 10 // expected-error {{left side of mutating operator isn't mutable: 'x' is a 'let' constant}}
8787
}
8888
func SR979g(inout i: inout Int) {} // expected-error {{parameter may not have multiple 'inout', 'var', or 'let' specifiers}} {{13-18=}}
8989
func SR979h(let inout x : Int) {} // expected-error {{parameter may not have multiple 'inout', 'var', or 'let' specifiers}} {{17-23=}}
9090
// expected-error @-1 {{'let' as a parameter attribute is not allowed}}
9191
class VarTester {
92-
init(var a: Int, var b: Int) {} // expected-error {{parameters may not have the 'var' specifier}} {{8-11=}} {{33-33= var a = a }}
93-
// expected-error @-1 {{parameters may not have the 'var' specifier}} {{20-24=}} {{33-33= var b = b }}
94-
func x(var b: Int) { //expected-error {{parameters may not have the 'var' specifier}} {{12-15=}} {{9-9=var b = b\n }}
95-
b += 10
96-
}
92+
init(var a: Int, var b: Int) {} // expected-error {{'var' as a parameter attribute is not allowed}}
93+
// expected-error @-1 {{'var' as a parameter attribute is not allowed}}
94+
func x(var b: Int) { //expected-error {{'var' as a parameter attribute is not allowed}}
95+
b += 10 // expected-error {{left side of mutating operator isn't mutable: 'b' is a 'let' constant}}
96+
}
9797
}
9898

9999
func repeat() {}

test/Sema/immutability.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -348,11 +348,11 @@ func testSelectorStyleArguments3(_ x: Int, bar y: Int) {
348348
func invalid_inout(inout var x : Int) { // expected-error {{parameter may not have multiple 'inout', 'var', or 'let' specifiers}} {{26-30=}}
349349
// expected-error @-1 {{'inout' before a parameter name is not allowed, place it before the parameter type instead}}{{20-25=}}{{34-34=inout }}
350350
}
351-
func invalid_var(var x: Int) { // expected-error {{parameters may not have the 'var' specifier}}{{18-21=}} {{1-1= var x = x\n}}
351+
func invalid_var(var x: Int) { // expected-error {{'var' as a parameter attribute is not allowed}}
352352

353353
}
354354
func takesClosure(_: (Int) -> Int) {
355-
takesClosure { (var d) in d } // expected-error {{parameters may not have the 'var' specifier}}
355+
takesClosure { (var d) in d } // expected-error {{'var' as a parameter attribute is not allowed}}
356356
}
357357

358358
func updateInt(_ x : inout Int) {}

test/decl/class/override.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,8 @@ class H : G {
169169

170170
func manyA(_: AnyObject, _: AnyObject) {}
171171
func manyB(_ a: AnyObject, b: AnyObject) {}
172-
func manyC(var a: AnyObject, // expected-error {{parameters may not have the 'var' specifier}} {{14-17=}}
173-
var b: AnyObject) {} // expected-error {{parameters may not have the 'var' specifier}} {{14-18=}}
172+
func manyC(var a: AnyObject, // expected-error {{'var' as a parameter attribute is not allowed}}
173+
var b: AnyObject) {} // expected-error {{'var' as a parameter attribute is not allowed}}
174174

175175
func result() -> AnyObject? { return nil }
176176
func both(_ x: AnyObject) -> AnyObject? { return x }

test/decl/var/usage.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ func basicTests() -> Int {
1212
return y
1313
}
1414

15-
func mutableParameter(_ a : Int, h : Int, var i : Int, j: Int, g: Int) -> Int { // expected-error {{parameters may not have the 'var' specifier}}
16-
i += 1
15+
func mutableParameter(_ a : Int, h : Int, var i : Int, j: Int, g: Int) -> Int { // expected-error {{'var' as a parameter attribute is not allowed}}
16+
i += 1 // expected-error {{left side of mutating operator isn't mutable: 'i' is a 'let' constant}}
1717
var j = j
18-
swap(&i, &j)
18+
swap(&i, &j) // expected-error {{cannot pass immutable value as inout argument: 'i' is a 'let' constant}}
1919
return i+g
2020
}
2121

0 commit comments

Comments
 (0)