Skip to content

Commit b9d0a49

Browse files
authored
Merge pull request #19738 from DougGregor/synthesize-getter-setter-generic-subscript
2 parents 30afc54 + 04e2f34 commit b9d0a49

File tree

2 files changed

+45
-12
lines changed

2 files changed

+45
-12
lines changed

lib/Sema/CodeSynthesis.cpp

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,20 @@ buildIndexForwardingParamList(AbstractStorageDecl *storage,
164164
return ParameterList::create(context, elements);
165165
}
166166

167+
/// Create the generic parameters needed for the given accessor, if any.
168+
static GenericParamList *createAccessorGenericParams(
169+
AbstractStorageDecl *storage) {
170+
// Accessors of generic subscripts get a copy of the subscript's
171+
// generic parameter list, because they're not nested inside the
172+
// subscript.
173+
if (auto *subscript = dyn_cast<SubscriptDecl>(storage)) {
174+
if (auto genericParams = subscript->getGenericParams())
175+
return genericParams->clone(subscript->getDeclContext());
176+
}
177+
178+
return nullptr;
179+
}
180+
167181
static AccessorDecl *createGetterPrototype(TypeChecker &TC,
168182
AbstractStorageDecl *storage) {
169183
assert(!storage->getGetter());
@@ -193,6 +207,8 @@ static AccessorDecl *createGetterPrototype(TypeChecker &TC,
193207
}
194208
}
195209

210+
GenericParamList *genericParams = createAccessorGenericParams(storage);
211+
196212
// Add an index-forwarding clause.
197213
auto *getterParams = buildIndexForwardingParamList(storage, {});
198214

@@ -209,7 +225,7 @@ static AccessorDecl *createGetterPrototype(TypeChecker &TC,
209225
AccessorKind::Get, AddressorKind::NotAddressor, storage,
210226
staticLoc, StaticSpellingKind::None,
211227
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
212-
/*GenericParams=*/nullptr,
228+
genericParams,
213229
getterParams,
214230
TypeLoc::withoutLoc(storageInterfaceType),
215231
storage->getDeclContext());
@@ -255,7 +271,9 @@ static AccessorDecl *createSetterPrototype(TypeChecker &TC,
255271

256272
bool isStatic = storage->isStatic();
257273
bool isMutating = storage->isSetterMutating();
258-
274+
275+
GenericParamList *genericParams = createAccessorGenericParams(storage);
276+
259277
// Add a "(value : T, indices...)" argument list.
260278
auto storageInterfaceType = storage->getValueInterfaceType();
261279
auto valueDecl = buildArgument(storage->getLoc(), storage->getDeclContext(),
@@ -269,7 +287,7 @@ static AccessorDecl *createSetterPrototype(TypeChecker &TC,
269287
AccessorKind::Set, AddressorKind::NotAddressor, storage,
270288
/*StaticLoc=*/SourceLoc(), StaticSpellingKind::None,
271289
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
272-
/*GenericParams=*/nullptr, params,
290+
genericParams, params,
273291
TypeLoc::withoutLoc(setterRetTy),
274292
storage->getDeclContext());
275293
setter->setImplicit();
@@ -379,15 +397,7 @@ createCoroutineAccessorPrototype(TypeChecker &TC,
379397
// Coroutine accessors always return ().
380398
Type retTy = TupleType::getEmpty(ctx);
381399

382-
// Accessors of generic subscripts get a copy of the subscript's
383-
// generic parameter list, because they're not nested inside the
384-
// subscript.
385-
GenericParamList *genericParams = nullptr;
386-
if (auto *subscript = dyn_cast<SubscriptDecl>(storage)) {
387-
genericParams = subscript->getGenericParams();
388-
if (genericParams)
389-
genericParams = genericParams->clone(dc);
390-
}
400+
GenericParamList *genericParams = createAccessorGenericParams(storage);
391401

392402
auto *accessor = AccessorDecl::create(
393403
ctx, loc, /*AccessorKeywordLoc=*/SourceLoc(),

test/SILGen/addressors.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,29 @@ class Sub : Base {
411411
}
412412
}
413413

414+
// rdar://problem/45046969
415+
struct Bar<T> { }
416+
417+
protocol FooProtocol {
418+
subscript<T>(index: Bar<T>) -> T { get set }
419+
}
420+
421+
// Make sure we get the right generic signatures for the synthesized
422+
// getter/setter.
423+
424+
// CHECK: sil hidden [transparent] @$s10addressors3FooVyqd__AA3BarVyqd__Gcluig : $@convention(method) <Base><T> (Bar<T>, Foo<Base>)
425+
// CHECK: sil hidden [transparent] @$s10addressors3FooVyqd__AA3BarVyqd__Gcluis : $@convention(method) <Base><T> (@in T, Bar<T>, @inout Foo<Base>) -> ()
426+
struct Foo<Base>: FooProtocol {
427+
subscript<T>(index: Bar<T>) -> T {
428+
unsafeAddress {
429+
return UnsafePointer<T>(bitPattern: 0)!
430+
}
431+
unsafeMutableAddress {
432+
return UnsafeMutablePointer<T>(bitPattern: 0)!
433+
}
434+
}
435+
}
436+
414437
// Make sure addressors don't get vtable entries.
415438
// CHECK-LABEL: sil_vtable Base {
416439
// CHECK-NEXT: #Base.data!getter.1: (Base) -> () -> UnsafeMutablePointer<Int32> : @$s10addressors4BaseC4dataSpys5Int32VGvg

0 commit comments

Comments
 (0)