Skip to content

Commit 3ec0149

Browse files
authored
Merge pull request swiftlang#67365 from xedin/minor-init-accessor-improvements-1-5.9
[5.9][Sema/SILGen] InitAccessors: A few improvements and bug fixes
2 parents 01564f6 + c47a834 commit 3ec0149

File tree

7 files changed

+128
-9
lines changed

7 files changed

+128
-9
lines changed

lib/Parse/ParseDecl.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7109,6 +7109,7 @@ struct Parser::ParsedAccessors {
71097109

71107110
/// Find the first accessor that can be used to perform mutation.
71117111
AccessorDecl *findFirstMutator() const {
7112+
if (Init) return Init;
71127113
if (Set) return Set;
71137114
if (Modify) return Modify;
71147115
if (MutableAddress) return MutableAddress;

lib/SIL/IR/SILFunctionType.cpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2381,22 +2381,27 @@ static CanSILFunctionType getSILFunctionTypeForInitAccessor(
23812381
// Drop `self` parameter.
23822382
inputs.pop_back();
23832383

2384+
auto getLoweredTypeOfProperty = [&](VarDecl *property) {
2385+
auto type = property->getInterfaceType();
2386+
AbstractionPattern pattern(genericSig, type->getCanonicalType());
2387+
auto loweredTy = TC.getLoweredType(pattern, type, context);
2388+
return loweredTy.getASTType();
2389+
};
2390+
23842391
// accessed properties appear as `inout` parameters because they could be
23852392
// read from and modified.
23862393
for (auto *property : accessor->getAccessedProperties()) {
2387-
inputs.push_back(
2388-
SILParameterInfo(property->getInterfaceType()->getCanonicalType(),
2389-
ParameterConvention::Indirect_Inout));
2394+
inputs.push_back(SILParameterInfo(getLoweredTypeOfProperty(property),
2395+
ParameterConvention::Indirect_Inout));
23902396
}
23912397

23922398
SmallVector<SILResultInfo, 8> results;
23932399

23942400
// initialized properties appear as `@out` results because they are
23952401
// initialized by the accessor.
23962402
for (auto *property : accessor->getInitializedProperties()) {
2397-
results.push_back(
2398-
SILResultInfo(property->getInterfaceType()->getCanonicalType(),
2399-
ResultConvention::Indirect));
2403+
results.push_back(SILResultInfo(getLoweredTypeOfProperty(property),
2404+
ResultConvention::Indirect));
24002405
}
24012406

24022407
auto calleeConvention = ParameterConvention::Direct_Unowned;

lib/SILGen/SILGenConstructor.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1584,8 +1584,8 @@ void SILGenFunction::emitInitAccessor(AccessorDecl *accessor) {
15841584
bool markUninitialized = false) {
15851585
auto *arg = ParamDecl::createImplicit(
15861586
getASTContext(), property->getBaseIdentifier(),
1587-
property->getBaseIdentifier(), type.getASTType()->mapTypeOutOfContext(),
1588-
accessor, ParamSpecifier::InOut);
1587+
property->getBaseIdentifier(), property->getInterfaceType(), accessor,
1588+
ParamSpecifier::InOut);
15891589

15901590
RegularLocation loc(property);
15911591
loc.markAutoGenerated();

lib/Serialization/Serialization.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2954,7 +2954,7 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
29542954
}
29552955

29562956
case DAK_StorageRestrictions: {
2957-
auto abbrCode = S.DeclTypeAbbrCodes[AccessesDeclAttrLayout::Code];
2957+
auto abbrCode = S.DeclTypeAbbrCodes[StorageRestrictionsDeclAttrLayout::Code];
29582958
auto attr = cast<StorageRestrictionsAttr>(DA);
29592959

29602960
SmallVector<IdentifierID, 4> properties;

test/SILOptimizer/init_accessors.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,30 @@ func test_local_with_memberwise() {
395395
_ = TestMemberwiseGeneric(a: 1, pair: ("a", [0]))
396396
}
397397

398+
// CHECK-LABEL: sil private [ossa] @$s14init_accessors023test_type_lowering_for_A9_accessoryyF4TestL_V2fnADyxq_Gq_xc_tcfC : $@convention(method) <T, U> (@owned @callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> @out τ_0_1 for <T, U>, @thin Test<T, U>.Type) -> @owned Test<T, U>
399+
// CHECK: {{.*}} = function_ref @$s14init_accessors023test_type_lowering_for_A9_accessoryyF4TestL_V2fnyq_xcvi : $@convention(thin) <τ_0_0, τ_0_1> (@owned @callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> @out τ_0_1 for <τ_0_0, τ_0_1>) -> @out Optional<@callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> @out τ_0_1 for <τ_0_0, τ_0_1>>
400+
func test_type_lowering_for_init_accessor() {
401+
struct Test<T, U> {
402+
var _fn: ((T) -> U)? = nil
403+
404+
// CHECK-LABEL: sil private [ossa] @$s14init_accessors023test_type_lowering_for_A9_accessoryyF4TestL_V2fnyq_xcvi : $@convention(thin) <T, U> (@owned @callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> @out τ_0_1 for <T, U>) -> @out Optional<@callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> @out τ_0_1 for <T, U>>
405+
var fn: (T) -> U {
406+
@storageRestrictions(initializes: _fn)
407+
init { _fn = newValue }
408+
get { _fn! }
409+
set { _fn = newValue }
410+
}
411+
412+
init(fn: @escaping (T) -> U) {
413+
self.fn = fn
414+
}
415+
}
416+
417+
_ = Test<Int, () -> Void> { _ in
418+
return {}
419+
} // Ok
420+
}
421+
398422
func test_assignments() {
399423
struct Test {
400424
var _a: Int
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %empty-directory(%t/src)
3+
// RUN: %empty-directory(%t/sdk)
4+
// RUN: split-file %s %t/src
5+
6+
// REQUIRES: asserts
7+
8+
// RUN: %target-swift-frontend -emit-module %t/src/PublicModule.swift \
9+
// RUN: -module-name PublicModule -swift-version 5 \
10+
// RUN: -emit-module-path %t/sdk/PublicModule.swiftmodule \
11+
// RUN: -enable-experimental-feature InitAccessors
12+
13+
// RUN: %target-swift-frontend -typecheck %t/src/Client.swift \
14+
// RUN: -enable-experimental-feature InitAccessors \
15+
// RUN: -module-name Client -I %t/sdk
16+
17+
//--- PublicModule.swift
18+
public struct Test<T> {
19+
private var _x: T
20+
21+
public var x: T {
22+
@storageRestrictions(initializes: _x)
23+
init {
24+
_x = newValue
25+
}
26+
27+
get { _x }
28+
set { _x = newValue }
29+
}
30+
31+
public init(data: T) {
32+
self.x = data
33+
}
34+
}
35+
36+
public struct TestMulti<T, U> {
37+
private var _a: T
38+
private var _c: U
39+
40+
public var b: Int
41+
42+
public var data: (T, U) {
43+
@storageRestrictions(initializes: _a, _c, accesses: b)
44+
init {
45+
_a = newValue.0
46+
_c = newValue.1
47+
b = 0
48+
}
49+
50+
get { (_a, _c) }
51+
}
52+
53+
public init(data: (T, U), b: Int) {
54+
self.b = b
55+
self.data = data
56+
}
57+
}
58+
59+
//--- Client.swift
60+
import PublicModule
61+
62+
let test1 = Test<[Int]>(data: [1, 2, 3])
63+
_ = test1.x
64+
65+
let test2 = TestMulti(data: ("Question", 42), b: -1)
66+
_ = print("\(test2.data), \(test2.b)")

test/decl/var/init_accessors.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,16 @@ func test_invalid_refs_in_init_attrs() {
8686
// expected-error@-2 {{find type 'b' in scope}}
8787
// expected-error@-3 {{init accessor cannot refer to property 'c'; init accessors can refer only to stored properties}}
8888
init(initialValue) {}
89+
90+
get { 0 }
8991
}
9092

9193
var y: String {
9294
@storageRestrictions(initializes: test)
9395
// expected-error@-1 {{ambiguous reference to member 'test'}}
9496
init(initialValue) {}
97+
98+
get { "" }
9599
}
96100

97101
func test(_: Int) {} // expected-note {{'test' declared here}}
@@ -110,6 +114,8 @@ func test_assignment_to_let_properties() {
110114
self.x = initialValue // Ok
111115
self.y = 42 // expected-error {{cannot assign to property: 'y' is a 'let' constant}}
112116
}
117+
118+
get { x }
113119
}
114120

115121
var point: (Int, Int) {
@@ -157,6 +163,8 @@ func test_duplicate_and_computed_lazy_properties() {
157163
// expected-error@-2 {{init accessor cannot refer to property 'b'; init accessors can refer only to stored properties}}
158164
// expected-error@-3 {{init accessor cannot refer to property 'c'; init accessors can refer only to stored properties}}
159165
init(initialValue) {}
166+
167+
get { _a }
160168
}
161169

162170
var b: Int {
@@ -475,11 +483,15 @@ func test_default_arguments_are_analyzed() {
475483
struct Test {
476484
var pair: (Int, Int) = (0, 1) { // Ok
477485
init {}
486+
487+
get { (0, 1) }
478488
}
479489

480490
var other: (Int, String) = ("", 42) {
481491
// expected-error@-1 {{cannot convert value of type '(String, Int)' to specified type '(Int, String)'}}
482492
init(initialValue) {}
493+
494+
get { (0, "") }
483495
}
484496

485497
var otherPair = (0, 1) {
@@ -558,36 +570,47 @@ func test_invalid_storage_restrictions() {
558570
@storageRestrictions()
559571
// expected-error@-1 {{missing label in @storageRestrictions attribute}}
560572
init {}
573+
574+
get { _a }
561575
}
562576

563577
var b: Int {
564578
@storageRestrictions(initializes:)
565579
// expected-error@-1 {{expected property name in @storageRestrictions list}}
566580
init {}
581+
582+
get { _b }
567583
}
568584

569585
var c: Int {
570586
@storageRestrictions(initializes: a, initializes: b)
571587
// expected-error@-1 {{duplicate label 'initializes' in @storageRestrictions attribute}}
572588
init {}
589+
590+
get { 0 }
573591
}
574592

575593
var d: Int {
576594
@storageRestrictions(accesses: a, accesses: c)
577595
// expected-error@-1 {{duplicate label 'accesses' in @storageRestrictions attribute}}
578596
init {}
597+
598+
get { 0 }
579599
}
580600

581601
var e: Int {
582602
@storageRestrictions(initialize: a, b, accesses: c, d)
583603
// expected-error@-1 {{unexpected label 'initialize' in @storageRestrictions attribute}}
584604
init {}
605+
606+
get { 0 }
585607
}
586608

587609
var f: Int {
588610
@storageRestrictions(initializes: _a, accesses: _b, _a)
589611
// expected-error@-1 {{property '_a' cannot be both initialized and accessed}}
590612
init {}
613+
// expected-error@-1 {{variable with an init accessor must also have a getter}}
591614
}
592615

593616
var g: Int {

0 commit comments

Comments
 (0)