Skip to content

Commit af3aa03

Browse files
Merge pull request swiftlang#28697 from ravikandhadai/oslog-generic-operator-bug-fix
[Constant Evaluator] Fix a bug in the composition of substitution maps
2 parents a6168a9 + 7744720 commit af3aa03

File tree

4 files changed

+49
-18
lines changed

4 files changed

+49
-18
lines changed

include/swift/SIL/SILConstants.h

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#define SWIFT_SIL_CONSTANTS_H
2020

2121
#include "swift/AST/SubstitutionMap.h"
22+
#include "swift/SIL/SILInstruction.h"
2223
#include "swift/SIL/SILValue.h"
2324
#include "llvm/Support/CommandLine.h"
2425

@@ -572,7 +573,7 @@ class SymbolicValue {
572573
static SymbolicValue makeClosure(
573574
SILFunction *target,
574575
ArrayRef<std::pair<SILValue, Optional<SymbolicValue>>> capturedArguments,
575-
SubstitutionMap substMap, SILType closureType,
576+
SubstitutionMap substMap, SingleValueInstruction *closureInst,
576577
SymbolicValueAllocator &allocator);
577578

578579
SymbolicClosure *getClosure() const {
@@ -689,21 +690,25 @@ struct SymbolicClosure final
689690
// applied function to the generic arguments of passed to the call.
690691
SubstitutionMap substitutionMap;
691692

692-
SILType closureType;
693+
// The closure instruction such as partial apply that resulted in this
694+
// symbolic value. This is tracked to obtain SILType and other SIL-level
695+
// information of the symbolic closure.
696+
SingleValueInstruction *closureInst;
693697

694698
SymbolicClosure() = delete;
695699
SymbolicClosure(const SymbolicClosure &) = delete;
696700
SymbolicClosure(SILFunction *callee, unsigned numArguments,
697-
SubstitutionMap substMap, SILType closureType,
701+
SubstitutionMap substMap, SingleValueInstruction *inst,
698702
bool nonConstantCaptures)
699703
: target(callee), numCaptures(numArguments),
700704
hasNonConstantCaptures(nonConstantCaptures), substitutionMap(substMap),
701-
closureType(closureType) {}
705+
closureInst(inst) {}
702706

703707
public:
704708
static SymbolicClosure *create(SILFunction *callee,
705709
ArrayRef<SymbolicClosureArgument> args,
706-
SubstitutionMap substMap, SILType closureType,
710+
SubstitutionMap substMap,
711+
SingleValueInstruction *closureInst,
707712
SymbolicValueAllocator &allocator);
708713

709714
ArrayRef<SymbolicClosureArgument> getCaptures() const {
@@ -719,7 +724,9 @@ struct SymbolicClosure final
719724
return target;
720725
}
721726

722-
SILType getClosureType() { return closureType; }
727+
SingleValueInstruction *getClosureInst() { return closureInst; }
728+
729+
SILType getClosureType() { return closureInst->getType(); }
723730

724731
SubstitutionMap getCallSubstitutionMap() { return substitutionMap; }
725732
};

lib/SIL/SILConstants.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ SymbolicValue::cloneInto(SymbolicValueAllocator &allocator) const {
249249
ArrayRef<SymbolicClosureArgument> closureArgs = clo->getCaptures();
250250
return SymbolicValue::makeClosure(clo->getTarget(), closureArgs,
251251
clo->getCallSubstitutionMap(),
252-
clo->getClosureType(), allocator);
252+
clo->getClosureInst(), allocator);
253253
}
254254
}
255255
llvm_unreachable("covered switch");
@@ -747,10 +747,10 @@ Type SymbolicValue::getArrayType() const {
747747
SymbolicValue SymbolicValue::makeClosure(SILFunction *target,
748748
ArrayRef<SymbolicClosureArgument> args,
749749
SubstitutionMap substMap,
750-
SILType closureType,
750+
SingleValueInstruction *closureInst,
751751
SymbolicValueAllocator &allocator) {
752752
auto clo =
753-
SymbolicClosure::create(target, args, substMap, closureType, allocator);
753+
SymbolicClosure::create(target, args, substMap, closureInst, allocator);
754754
SymbolicValue result;
755755
result.representationKind = RK_Closure;
756756
result.value.closure = clo;
@@ -760,7 +760,7 @@ SymbolicValue SymbolicValue::makeClosure(SILFunction *target,
760760
SymbolicClosure *SymbolicClosure::create(SILFunction *target,
761761
ArrayRef<SymbolicClosureArgument> args,
762762
SubstitutionMap substMap,
763-
SILType closureType,
763+
SingleValueInstruction *closureInst,
764764
SymbolicValueAllocator &allocator) {
765765
// Determine whether there are captured arguments without a symbolic value.
766766
bool hasNonConstantCapture = false;
@@ -776,7 +776,7 @@ SymbolicClosure *SymbolicClosure::create(SILFunction *target,
776776
auto rawMem = allocator.allocate(byteSizeOfArgs, alignof(SymbolicClosure));
777777
// Placement initialize the object.
778778
auto closure = ::new (rawMem) SymbolicClosure(
779-
target, args.size(), substMap, closureType, hasNonConstantCapture);
779+
target, args.size(), substMap, closureInst, hasNonConstantCapture);
780780
std::uninitialized_copy(
781781
args.begin(), args.end(),
782782
closure->getTrailingObjects<SymbolicClosureArgument>());

lib/SILOptimizer/Utils/ConstExpr.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1147,8 +1147,10 @@ ConstExprFunctionState::computeCallResult(ApplyInst *apply) {
11471147
calleeFnType->getWitnessMethodConformanceOrInvalid().getRequirement();
11481148
// Compute a mapping that maps the Self type of the protocol given by
11491149
// 'requirement' to the concrete type available in the substitutionMap.
1150-
auto protoSelfToConcreteType =
1151-
apply->getSubstitutionMap().subst(substitutionMap);
1150+
SubstitutionMap applySubstMap = apply->getSubstitutionMap();
1151+
auto protoSelfToConcreteType = substitutionMap.empty()
1152+
? applySubstMap
1153+
: applySubstMap.subst(substitutionMap);
11521154
// Get a concrete protocol conformance by using the mapping for the
11531155
// Self type of the requirement.
11541156
auto conf = protoSelfToConcreteType.lookupConformance(
@@ -1174,7 +1176,8 @@ ConstExprFunctionState::computeCallResult(ApplyInst *apply) {
11741176
// or conformance, with the mapping introduced by the call itself. This
11751177
// ensures that the callee's substitution map can map from its type
11761178
// namespace back to concrete types and conformances.
1177-
calleeSubMap = callSubMap.subst(substitutionMap);
1179+
calleeSubMap = substitutionMap.empty() ? callSubMap
1180+
: callSubMap.subst(substitutionMap);
11781181
}
11791182

11801183
// Now that we have successfully folded all of the parameters, we can evaluate
@@ -1606,13 +1609,14 @@ llvm::Optional<SymbolicValue> ConstExprFunctionState::evaluateClosureCreation(
16061609
}
16071610
captures.push_back({capturedSILValue, capturedSymbolicValue});
16081611
}
1609-
callSubstMap = papply->getSubstitutionMap().subst(this->substitutionMap);
1612+
SubstitutionMap applySubstMap = papply->getSubstitutionMap();
1613+
callSubstMap = substitutionMap.empty()
1614+
? applySubstMap
1615+
: applySubstMap.subst(substitutionMap);
16101616
}
16111617

1612-
SILType closureType = closureInst->getType();
1613-
assert(closureType.is<SILFunctionType>());
16141618
auto closureVal = SymbolicValue::makeClosure(
1615-
target, captures, callSubstMap, closureType, evaluator.getAllocator());
1619+
target, captures, callSubstMap, closureInst, evaluator.getAllocator());
16161620
setValue(closureInst, closureVal);
16171621
return None;
16181622
}

test/stdlib/OSLogPrototypeExecTest.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -647,3 +647,23 @@ InterpolationTestSuite.test("NSObject") {
647647
})
648648
}
649649
}
650+
651+
// A generic function.
652+
func toString<T>(_ subject: T?) -> String {
653+
return ""
654+
}
655+
656+
protocol TestProto {
657+
}
658+
659+
InterpolationTestSuite.test("Interpolation of complex expressions") {
660+
class TestClass<T: TestProto>: NSObject {
661+
func testFunction() {
662+
// The following call should no crash.
663+
_checkFormatStringAndBuffer("A complex expression \(toString(self))") {
664+
(formatString, _) in
665+
expectEqual("A complex expression %s", formatString)
666+
}
667+
}
668+
}
669+
}

0 commit comments

Comments
 (0)