Skip to content

SIL: Don't drop generic signatures where all parameters are concrete #23291

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3971,12 +3971,8 @@ SILFunctionType::SILFunctionType(GenericSignature *genericSig, ExtInfo ext,
assert(!WitnessMethodConformance &&
"non-witness_method SIL function with a conformance");

// Make sure the interface types are sane.
// Make sure the interface types do not contain archetypes or error types.
if (genericSig) {
assert(!genericSig->areAllParamsConcrete() &&
"If all generic parameters are concrete, SILFunctionType should "
"not have a generic signature at all");

for (auto gparam : genericSig->getGenericParams()) {
(void)gparam;
assert(gparam->isCanonical() && "generic signature is not canonicalized");
Expand Down
4 changes: 0 additions & 4 deletions lib/IRGen/Callee.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,10 +157,6 @@ namespace irgen {
CanSILFunctionType getSubstFunctionType() const {
return Info.SubstFnType;
}

bool hasSubstitutions() const {
return Info.Substitutions.hasAnySubstitutableParams();
}

SubstitutionMap getSubstitutions() const { return Info.Substitutions; }

Expand Down
4 changes: 2 additions & 2 deletions lib/IRGen/GenFunc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -876,9 +876,9 @@ static llvm::Function *emitPartialApplicationForwarder(IRGenModule &IGM,
Explosion polyArgs;

// Emit the polymorphic arguments.
assert((subs.hasAnySubstitutableParams()
assert((!subs.empty()
== hasPolymorphicParameters(origType) ||
(!subs.hasAnySubstitutableParams() && origType->getRepresentation() ==
(subs.empty() && origType->getRepresentation() ==
SILFunctionTypeRepresentation::WitnessMethod))
&& "should have substitutions iff original function is generic");
WitnessMetadata witnessMetadata;
Expand Down
14 changes: 4 additions & 10 deletions lib/SIL/SILPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1056,17 +1056,12 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
printDebugVar(ABI->getVarInfo());
}

void printSubstitutions(SubstitutionMap Subs,
GenericSignature *Sig = nullptr) {
if (!Subs.hasAnySubstitutableParams()) return;

// FIXME: This is a hack to cope with cases where the substitution map uses
// a generic signature that's close-to-but-not-the-same-as expected.
auto genericSig = Sig ? Sig : Subs.getGenericSignature();
void printSubstitutions(SubstitutionMap Subs) {
if (Subs.empty()) return;

*this << '<';
bool first = true;
for (auto gp : genericSig->getGenericParams()) {
for (auto gp : Subs.getGenericSignature()->getGenericParams()) {
if (first) first = false;
else *this << ", ";

Expand All @@ -1078,8 +1073,7 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
template <class Inst>
void visitApplyInstBase(Inst *AI) {
*this << Ctx.getID(AI->getCallee());
printSubstitutions(AI->getSubstitutionMap(),
AI->getOrigCalleeType()->getGenericSignature());
printSubstitutions(AI->getSubstitutionMap());
*this << '(';
interleave(AI->getArguments(),
[&](const SILValue &arg) { *this << Ctx.getID(arg); },
Expand Down
2 changes: 1 addition & 1 deletion lib/SIL/SILVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1050,7 +1050,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
auto fnTy = requireObjectType(SILFunctionType, calleeTy, "callee operand");

// If there are substitutions, verify them and apply them to the callee.
if (!subs.hasAnySubstitutableParams()) {
if (subs.empty()) {
require(!fnTy->isPolymorphic(),
"callee of apply without substitutions must not be polymorphic");
return fnTy;
Expand Down
45 changes: 18 additions & 27 deletions lib/SIL/TypeLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1727,8 +1727,7 @@ getTypeLoweringForExpansion(TypeKey key,
}

/// Get the type of a global variable accessor function, () -> RawPointer.
static CanAnyFunctionType getGlobalAccessorType(CanType varType) {
ASTContext &C = varType->getASTContext();
static CanAnyFunctionType getGlobalAccessorType(ASTContext &C) {
return CanFunctionType::get({}, C.TheRawPointerType);
}

Expand Down Expand Up @@ -1844,8 +1843,6 @@ TypeConverter::getEffectiveGenericEnvironment(AnyFunctionRef fn,
CanGenericSignature
TypeConverter::getEffectiveGenericSignature(DeclContext *dc) {
if (auto sig = dc->getGenericSignatureOfContext()) {
if (sig->areAllParamsConcrete())
return nullptr;
return sig->getCanonicalSignature();
}

Expand Down Expand Up @@ -1878,8 +1875,10 @@ TypeConverter::getFunctionInterfaceTypeWithCaptures(CanAnyFunctionType funcType,
auto innerExtInfo = AnyFunctionType::ExtInfo(FunctionType::Representation::Thin,
funcType->throws());

return CanAnyFunctionType::get(genericSig, funcType.getParams(),
funcType.getResult(), innerExtInfo);
return CanAnyFunctionType::get(genericSig,
funcType.getParams(),
funcType.getResult(),
innerExtInfo);
}

CanAnyFunctionType TypeConverter::makeConstantInterfaceType(SILDeclRef c) {
Expand All @@ -1889,41 +1888,33 @@ CanAnyFunctionType TypeConverter::makeConstantInterfaceType(SILDeclRef c) {
case SILDeclRef::Kind::Func: {
if (auto *ACE = c.loc.dyn_cast<AbstractClosureExpr *>()) {
// FIXME: Closures could have an interface type computed by Sema.
auto funcTy = cast<AnyFunctionType>(ACE->getType()->getCanonicalType());
funcTy = cast<AnyFunctionType>(
funcTy->mapTypeOutOfContext()
auto funcTy = cast<AnyFunctionType>(
ACE->getType()->mapTypeOutOfContext()
->getCanonicalType());
return getFunctionInterfaceTypeWithCaptures(funcTy, ACE);
}

FuncDecl *func = cast<FuncDecl>(vd);
auto funcTy = cast<AnyFunctionType>(
func->getInterfaceType()->getCanonicalType());

// Fast path.
if (!func->getDeclContext()->isLocalContext())
return funcTy;

return getFunctionInterfaceTypeWithCaptures(funcTy, func);
}

case SILDeclRef::Kind::EnumElement: {
auto funcTy = cast<AnyFunctionType>(
vd->getInterfaceType()->getCanonicalType());
auto sig = getEffectiveGenericSignature(vd->getDeclContext());
return CanAnyFunctionType::get(sig,
funcTy->getParams(),
funcTy.getResult(),
funcTy->getExtInfo());
}

case SILDeclRef::Kind::EnumElement:
case SILDeclRef::Kind::Allocator: {
auto *cd = cast<ConstructorDecl>(vd);
auto funcTy = cast<AnyFunctionType>(
cd->getInterfaceType()->getCanonicalType());
return getFunctionInterfaceTypeWithCaptures(funcTy, cd);
return cast<AnyFunctionType>(
vd->getInterfaceType()->getCanonicalType());
}

case SILDeclRef::Kind::Initializer: {
auto *cd = cast<ConstructorDecl>(vd);
auto funcTy = cast<AnyFunctionType>(
cd->getInitializerInterfaceType()->getCanonicalType());
return getFunctionInterfaceTypeWithCaptures(funcTy, cd);
return cast<AnyFunctionType>(
cd->getInitializerInterfaceType()->getCanonicalType());
}

case SILDeclRef::Kind::Destroyer:
Expand All @@ -1937,7 +1928,7 @@ CanAnyFunctionType TypeConverter::makeConstantInterfaceType(SILDeclRef c) {
VarDecl *var = cast<VarDecl>(vd);
assert(var->hasStorage() &&
"constant ref to computed global var");
return getGlobalAccessorType(var->getInterfaceType()->getCanonicalType());
return getGlobalAccessorType(Context);
}
case SILDeclRef::Kind::DefaultArgGenerator:
return getDefaultArgGeneratorInterfaceType(*this, vd, vd->getDeclContext(),
Expand Down
7 changes: 0 additions & 7 deletions lib/SILGen/SILGenType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -626,13 +626,6 @@ SILFunction *SILGenModule::emitProtocolWitness(
reqtOrigTy->substGenericArgs(reqtSubMap)
->getCanonicalType(genericSig));

// Generic signatures where all parameters are concrete are lowered away
// at the SILFunctionType level.
if (genericSig && genericSig->areAllParamsConcrete()) {
genericSig = nullptr;
genericEnv = nullptr;
}

// Rewrite the conformance in terms of the requirement environment's Self
// type, which might have a different generic signature than the type
// itself.
Expand Down
5 changes: 2 additions & 3 deletions lib/SILOptimizer/IPO/CapturePromotion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1260,9 +1260,8 @@ processPartialApplyInst(SILOptFunctionBuilder &FuncBuilder,
// consideration any captures.
auto CalleeFunctionTy = PAI->getCallee()->getType().castTo<SILFunctionType>();
auto SubstCalleeFunctionTy = CalleeFunctionTy;
if (PAI->hasSubstitutions())
SubstCalleeFunctionTy =
CalleeFunctionTy->substGenericArgs(M, PAI->getSubstitutionMap());
SubstCalleeFunctionTy =
CalleeFunctionTy->substGenericArgs(M, PAI->getSubstitutionMap());
SILFunctionConventions calleeConv(SubstCalleeFunctionTy, M);
auto CalleePInfo = SubstCalleeFunctionTy->getParameters();
SILFunctionConventions paConv(PAI->getType().castTo<SILFunctionType>(), M);
Expand Down
14 changes: 9 additions & 5 deletions lib/SILOptimizer/IPO/ClosureSpecializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,9 @@ class CallSiteDescriptor {
createNewClosure(SILBuilder &B, SILValue V,
llvm::SmallVectorImpl<SILValue> &Args) const {
if (auto *PA = dyn_cast<PartialApplyInst>(getClosure()))
return B.createPartialApply(getClosure()->getLoc(), V, {}, Args,
return B.createPartialApply(getClosure()->getLoc(), V,
PA->getSubstitutionMap(),
Args,
getClosure()
->getType()
.getAs<SILFunctionType>()
Expand Down Expand Up @@ -436,8 +438,8 @@ static void rewriteApplyInst(const CallSiteDescriptor &CSDesc,
case FullApplySiteKind::TryApplyInst: {
auto *TAI = cast<TryApplyInst>(AI);
NewAI = Builder.createTryApply(AI.getLoc(), FRI,
SubstitutionMap(), NewArgs,
TAI->getNormalBB(), TAI->getErrorBB());
TAI->getSubstitutionMap(),
NewArgs, TAI->getNormalBB(), TAI->getErrorBB());
// If we passed in the original closure as @owned, then insert a release
// right after NewAI. This is to balance the +1 from being an @owned
// argument to AI.
Expand All @@ -457,7 +459,7 @@ static void rewriteApplyInst(const CallSiteDescriptor &CSDesc,
case FullApplySiteKind::ApplyInst: {
auto oldApply = cast<ApplyInst>(AI);
auto newApply = Builder.createApply(oldApply->getLoc(), FRI,
SubstitutionMap(),
oldApply->getSubstitutionMap(),
NewArgs, oldApply->isNonThrowing());
// If we passed in the original closure as @owned, then insert a release
// right after NewAI. This is to balance the +1 from being an @owned
Expand Down Expand Up @@ -733,7 +735,9 @@ SILValue ClosureSpecCloner::cloneCalleeConversion(
auto FunRef = Builder.createFunctionRef(CallSiteDesc.getLoc(),
PAI->getReferencedFunction());
auto NewPA = Builder.createPartialApply(
CallSiteDesc.getLoc(), FunRef, {}, {calleeValue},
CallSiteDesc.getLoc(), FunRef,
PAI->getSubstitutionMap(),
{calleeValue},
PAI->getType().getAs<SILFunctionType>()->getCalleeConvention(),
PAI->isOnStack());
// If the partial_apply is on stack we will emit a dealloc_stack in the
Expand Down
4 changes: 1 addition & 3 deletions lib/SILOptimizer/Utils/Generics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -731,9 +731,7 @@ ReabstractionInfo::createSubstitutedType(SILFunction *OrigF,
SubstitutionMap SubstMap,
bool HasUnboundGenericParams) {
auto &M = OrigF->getModule();
if ((SpecializedGenericSig &&
SpecializedGenericSig->areAllParamsConcrete()) ||
!HasUnboundGenericParams) {
if (!HasUnboundGenericParams) {
SpecializedGenericSig = nullptr;
SpecializedGenericEnv = nullptr;
}
Expand Down
2 changes: 1 addition & 1 deletion test/SILGen/capture-canonicalization.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ struct Bar {}

extension Foo where T == Bar {
func foo(x: T) -> Bar {
// CHECK-LABEL: sil private [ossa] @{{.*}}3foo{{.*}}4foo2{{.*}} : $@convention(thin) (Bar) -> Bar
// CHECK-LABEL: sil private [ossa] @{{.*}}3foo{{.*}}4foo2{{.*}} : $@convention(thin) <T where T == Bar> (Bar) -> Bar
func foo2() -> Bar {
return x
}
Expand Down
2 changes: 1 addition & 1 deletion test/SILGen/conditional_conformance.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ extension Conformance: P1 where A: P2 {
// This is defined below but is emitted before any witness tables.
// Just make sure it does not have a generic signature.
//
// CHECK-LABEL: sil private [transparent] [thunk] [ossa] @$s23conditional_conformance16SameTypeConcreteVyxGAA2P1AASiRszlAaEP6normalyyFTW : $@convention(witness_method: P1) (@in_guaranteed SameTypeConcrete<Int>) -> ()
// CHECK-LABEL: sil private [transparent] [thunk] [ossa] @$s23conditional_conformance16SameTypeConcreteVyxGAA2P1AASiRszlAaEP6normalyyFTW : $@convention(witness_method: P1) <τ_0_0 where τ_0_0 == Int> (@in_guaranteed SameTypeConcrete<Int>) -> ()


// CHECK-LABEL: sil_witness_table hidden <A where A : P2> Conformance<A>: P1 module conditional_conformance {
Expand Down
Loading