Skip to content

Commit 6f4e65a

Browse files
committed
SIL: Canonicalize capture types with the AST function's generic signature.
When lowering closures, we avoid capturing the enclosing generic context when possible. However, the generic context may still be necessary to canonicalize types mentioned inside the closure, such as when an associated type is referred to that is same-typed to a concrete type. Fixes rdar://problem/30254048.
1 parent 0502fb8 commit 6f4e65a

File tree

5 files changed

+51
-6
lines changed

5 files changed

+51
-6
lines changed

include/swift/AST/AnyFunctionRef.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,16 @@ class AnyFunctionRef {
176176
}
177177
llvm_unreachable("unexpected AnyFunctionRef representation");
178178
}
179+
180+
GenericSignature *getGenericSignature() const {
181+
if (auto afd = TheFunction.dyn_cast<AbstractFunctionDecl *>()) {
182+
return afd->getGenericSignature();
183+
}
184+
if (auto ce = TheFunction.dyn_cast<AbstractClosureExpr *>()) {
185+
return ce->getGenericSignatureOfContext();
186+
}
187+
llvm_unreachable("unexpected AnyFunctionRef representation");
188+
}
179189
};
180190
#if SWIFT_COMPILER_IS_MSVC
181191
#pragma warning(pop)

lib/SIL/SILFunctionType.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "swift/AST/Decl.h"
2424
#include "swift/AST/DiagnosticsSIL.h"
2525
#include "swift/AST/ForeignErrorConvention.h"
26+
#include "swift/AST/GenericEnvironment.h"
2627
#include "swift/Basic/Fallthrough.h"
2728
#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
2829
#include "clang/AST/Attr.h"
@@ -742,9 +743,17 @@ static CanSILFunctionType getSILFunctionType(SILModule &M,
742743
// from the function to which the argument is attached.
743744
if (constant && !constant->isDefaultArgGenerator())
744745
if (auto function = constant->getAnyFunctionRef()) {
745-
auto getCanonicalType = [&](Type t) -> CanType {
746-
if (genericSig)
747-
return genericSig->getCanonicalTypeInContext(t, *M.getSwiftModule());
746+
// NB: The generic signature may be elided from the lowered function type
747+
// if the function is in a fully-specialized context, but we still need to
748+
// canonicalize references to the generic parameters that may appear in
749+
// non-canonical types in that context. We need the original generic
750+
// signature from the AST for that.
751+
auto origGenericSig
752+
= function->getGenericSignature();
753+
auto getCanonicalType = [origGenericSig, &M](Type t) -> CanType {
754+
if (origGenericSig)
755+
return origGenericSig->getCanonicalTypeInContext(t,
756+
*M.getSwiftModule());
748757
return t->getCanonicalType();
749758
};
750759

lib/SIL/SILInstructions.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,11 @@ ApplyInst *ApplyInst::create(SILDebugLocation Loc, SILValue Callee,
408408
ArrayRef<SILValue> Args, bool isNonThrowing,
409409
SILFunction &F,
410410
SILOpenedArchetypesState &OpenedArchetypes) {
411+
if (!F.getModule().Types.getCurGenericContext())
412+
assert(Callee->getType().castTo<SILFunctionType>()
413+
->substGenericArgs(F.getModule(), Subs)
414+
== SubstCalleeTy.getSwiftRValueType());
415+
411416
SmallVector<SILValue, 32> TypeDependentOperands;
412417
collectTypeDependentOperands(TypeDependentOperands, OpenedArchetypes, F,
413418
SubstCalleeTy.getSwiftRValueType(), Subs);

lib/SILGen/SILGenProlog.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,9 @@ void SILGenFunction::bindParametersForForwarding(const ParameterList *params,
344344
}
345345
}
346346

347-
static void emitCaptureArguments(SILGenFunction &gen, CapturedValue capture,
347+
static void emitCaptureArguments(SILGenFunction &gen,
348+
AnyFunctionRef closure,
349+
CapturedValue capture,
348350
unsigned ArgNo) {
349351

350352
auto *VD = capture.getDecl();
@@ -357,7 +359,12 @@ static void emitCaptureArguments(SILGenFunction &gen, CapturedValue capture,
357359
auto interfaceType = cast<VarDecl>(VD)->getInterfaceType();
358360
if (!interfaceType->hasTypeParameter()) return interfaceType;
359361

360-
auto genericEnv = gen.F.getGenericEnvironment();
362+
// NB: The generic signature may be elided from the lowered function type
363+
// if the function is in a fully-specialized context, but we still need to
364+
// canonicalize references to the generic parameters that may appear in
365+
// non-canonical types in that context. We need the original generic
366+
// environment from the AST for that.
367+
auto genericEnv = closure.getGenericEnvironment();
361368
return genericEnv->mapTypeIntoContext(gen.F.getModule().getSwiftModule(),
362369
interfaceType);
363370
};
@@ -446,7 +453,7 @@ void SILGenFunction::emitProlog(AnyFunctionRef TheClosure,
446453
return;
447454
}
448455

449-
emitCaptureArguments(*this, capture, ++ArgNo);
456+
emitCaptureArguments(*this, TheClosure, capture, ++ArgNo);
450457
}
451458
}
452459

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: %target-swift-frontend -emit-silgen %s | %FileCheck %s
2+
3+
struct Foo<T> {}
4+
struct Bar {}
5+
6+
extension Foo where T == Bar {
7+
func foo(x: T) -> Bar {
8+
// CHECK-LABEL: sil shared @{{.*}}3foo{{.*}}4foo2{{.*}} : $@convention(thin) (Bar) -> Bar
9+
func foo2() -> Bar {
10+
return x
11+
}
12+
return foo2()
13+
}
14+
}

0 commit comments

Comments
 (0)