Skip to content

Commit 04e2f34

Browse files
committed
[Type checker] Ensure that synthesized accessors get generic parameter lists.
When we synthesize the declaration for getters and setters from (e.g.) an addressor, ensure that we clone the generic parameter list when we have a generic subscript. Fixes rdar://problem/45046969.
1 parent 2bcdcdd commit 04e2f34

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)