Skip to content

Commit 9cf5f91

Browse files
authored
Merge pull request #14214 from rudkx/iuo-attr-on-accessor-argument
IUO: Set the IUO attribute on ParamDecls for accessors arguments.
2 parents 3b2d4ac + 305a7eb commit 9cf5f91

File tree

2 files changed

+47
-15
lines changed

2 files changed

+47
-15
lines changed

lib/Parse/ParseDecl.cpp

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3547,9 +3547,10 @@ static AccessorDecl *createAccessorFunc(SourceLoc DeclLoc,
35473547
return D;
35483548
}
35493549

3550-
static ParamDecl *
3551-
createSetterAccessorArgument(SourceLoc nameLoc, Identifier name,
3552-
AccessorKind accessorKind, Parser &P) {
3550+
static ParamDecl *createSetterAccessorArgument(SourceLoc nameLoc,
3551+
Identifier name,
3552+
AccessorKind accessorKind,
3553+
Parser &P, TypeLoc elementType) {
35533554
// Add the parameter. If no name was specified, the name defaults to
35543555
// 'value'.
35553556
bool isNameImplicit = name.empty();
@@ -3568,15 +3569,25 @@ createSetterAccessorArgument(SourceLoc nameLoc, Identifier name,
35683569

35693570
// AST Walker shouldn't go into the type recursively.
35703571
result->setIsTypeLocImplicit(true);
3572+
3573+
if (auto *repr = elementType.getTypeRepr()) {
3574+
if (repr->getKind() ==
3575+
TypeReprKind::ImplicitlyUnwrappedOptional) {
3576+
result->getAttrs().add(
3577+
new (P.Context) ImplicitlyUnwrappedOptionalAttr(/* implicit= */ true));
3578+
}
3579+
}
3580+
35713581
return result;
35723582
}
35733583

35743584
/// Parse a "(value)" specifier for "set" or "willSet" if present. Create a
35753585
/// parameter list to represent the spelled argument or return null if none is
35763586
/// present.
3577-
static ParameterList *
3578-
parseOptionalAccessorArgument(SourceLoc SpecifierLoc,
3579-
Parser &P, AccessorKind Kind) {
3587+
static ParameterList *parseOptionalAccessorArgument(SourceLoc SpecifierLoc,
3588+
Parser &P,
3589+
AccessorKind Kind,
3590+
TypeLoc ElementTy) {
35803591
// 'set' and 'willSet' have a (value) parameter, 'didSet' takes an (oldValue)
35813592
// parameter and 'get' and always takes a () parameter.
35823593
if (Kind != AccessorKind::IsSetter && Kind != AccessorKind::IsWillSet &&
@@ -3614,7 +3625,7 @@ parseOptionalAccessorArgument(SourceLoc SpecifierLoc,
36143625
}
36153626

36163627
if (Name.empty()) NameLoc = SpecifierLoc;
3617-
auto param = createSetterAccessorArgument(NameLoc, Name, Kind, P);
3628+
auto param = createSetterAccessorArgument(NameLoc, Name, Kind, P, ElementTy);
36183629
return ParameterList::create(P.Context, StartLoc, param, EndLoc);
36193630
}
36203631

@@ -3846,8 +3857,8 @@ bool Parser::parseGetSetImpl(ParseDeclOptions Flags,
38463857
if (Tok.is(tok::l_paren))
38473858
diagnose(Loc, diag::protocol_setter_name);
38483859

3849-
auto *ValueNameParams
3850-
= parseOptionalAccessorArgument(Loc, *this, Kind);
3860+
auto *ValueNameParams =
3861+
parseOptionalAccessorArgument(Loc, *this, Kind, ElementTy);
38513862

38523863
// Set up a function declaration.
38533864
TheDecl = createAccessorFunc(Loc, ValueNameParams,
@@ -3970,7 +3981,7 @@ bool Parser::parseGetSetImpl(ParseDeclOptions Flags,
39703981
//
39713982
// set-name ::= '(' identifier ')'
39723983
auto *ValueNamePattern =
3973-
parseOptionalAccessorArgument(Loc, *this, Kind);
3984+
parseOptionalAccessorArgument(Loc, *this, Kind, ElementTy);
39743985

39753986
SyntaxParsingContext BlockCtx(SyntaxContext, SyntaxKind::CodeBlock);
39763987
if (AccessorKeywordLoc.isInvalid()) {
@@ -4426,8 +4437,8 @@ void Parser::ParsedAccessors::record(Parser &P, AbstractStorageDecl *storage,
44264437
auto argFunc = (WillSet ? WillSet : DidSet);
44274438
auto argLoc = argFunc->getParameterLists().back()->getStartLoc();
44284439

4429-
auto argument = createSetterAccessorArgument(argLoc, Identifier(),
4430-
AccessorKind::IsSetter, P);
4440+
auto argument = createSetterAccessorArgument(
4441+
argLoc, Identifier(), AccessorKind::IsSetter, P, elementTy);
44314442
auto argList = ParameterList::create(P.Context, argument);
44324443
Set = createImplicitAccessor(AccessorKind::IsSetter,
44334444
AddressorKind::NotAddressor, argList);
@@ -4448,8 +4459,8 @@ void Parser::ParsedAccessors::record(Parser &P, AbstractStorageDecl *storage,
44484459
if (MutableAddressor) {
44494460
assert(Get && !Set);
44504461
auto argument =
4451-
createSetterAccessorArgument(MutableAddressor->getLoc(), Identifier(),
4452-
AccessorKind::IsSetter, P);
4462+
createSetterAccessorArgument(MutableAddressor->getLoc(), Identifier(),
4463+
AccessorKind::IsSetter, P, elementTy);
44534464
auto argList = ParameterList::create(P.Context, argument);
44544465
Set = createImplicitAccessor(AccessorKind::IsSetter,
44554466
AddressorKind::NotAddressor, argList);

test/Constraints/iuo.swift

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,34 @@ struct S {
1616
var j: Int!
1717
let k: Int
1818
var m: Int
19+
var n: Int! {
20+
get {
21+
return m
22+
}
23+
set {
24+
m = newValue
25+
}
26+
}
27+
var o: Int! {
28+
willSet {
29+
m = newValue
30+
}
31+
didSet {
32+
m = oldValue
33+
}
34+
}
1935

2036
func fn() -> Int! { return i }
2137

2238
static func static_fn() -> Int! { return 0 }
2339

2440
subscript(i: Int) -> Int! {
25-
return i
41+
set {
42+
m = newValue
43+
}
44+
get {
45+
return i
46+
}
2647
}
2748

2849
init(i: Int!, j: Int!, k: Int, m: Int) {

0 commit comments

Comments
 (0)