Skip to content

Commit 48c456d

Browse files
committed
SILOptimizer: Simplify combineSubstitutionMaps() and fix invariant violation
Fixes rdar://problem/134732867.
1 parent 43c7310 commit 48c456d

File tree

2 files changed

+55
-61
lines changed

2 files changed

+55
-61
lines changed

lib/SILOptimizer/Utils/Devirtualize.cpp

Lines changed: 42 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -407,71 +407,52 @@ combineSubstitutionMaps(SubstitutionMap firstSubMap,
407407
GenericSignature genericSig) {
408408
auto &ctx = genericSig->getASTContext();
409409

410-
auto replaceGenericParameter = [&](Type type) -> std::optional<Type> {
411-
if (auto gp = type->getAs<GenericTypeParamType>()) {
412-
if (gp->getDepth() < firstDepth)
413-
return Type();
414-
return Type(GenericTypeParamType::get(gp->isParameterPack(),
415-
gp->getDepth() + secondDepth -
416-
firstDepth,
417-
gp->getIndex(), ctx));
418-
}
419-
420-
return std::nullopt;
421-
};
422-
423410
return SubstitutionMap::get(
424411
genericSig,
425412
[&](SubstitutableType *type) {
426-
if (auto replacement = replaceGenericParameter(type))
427-
if (*replacement)
428-
return replacement->subst(secondSubMap);
429-
return Type(type).subst(firstSubMap);
413+
auto *gp = cast<GenericTypeParamType>(type);
414+
if (gp->getDepth() < firstDepth)
415+
return QuerySubstitutionMap{firstSubMap}(gp);
416+
417+
auto *replacement = GenericTypeParamType::get(
418+
gp->isParameterPack(),
419+
gp->getDepth() + secondDepth - firstDepth,
420+
gp->getIndex(), ctx);
421+
return QuerySubstitutionMap{secondSubMap}(replacement);
430422
},
431-
[&](CanType type, Type substType, ProtocolDecl *proto) {
432-
if (auto replacement = type.transformRec(replaceGenericParameter))
433-
return secondSubMap.lookupConformance(replacement->getCanonicalType(),
434-
proto);
435-
if (auto conformance = firstSubMap.lookupConformance(type, proto))
436-
return conformance;
437-
438-
// We might not have enough information in the substitution maps alone.
439-
//
440-
// Eg,
441-
//
442-
// class Base<T1> {
443-
// func foo<U1>(_: U1) where T1 : P {}
444-
// }
445-
//
446-
// class Derived<T2> : Base<Foo<T2>> {
447-
// override func foo<U2>(_: U2) where T2 : Q {}
448-
// }
449-
//
450-
// Suppose we're devirtualizing a call to Base.foo() on a value whose
451-
// type is known to be Derived<Bar>. We start with substitutions written
452-
// in terms of Base.foo()'s generic signature:
453-
//
454-
// <T1, U1 where T1 : P>
455-
// T1 := Foo<Bar>
456-
// T1 : P := Foo<Bar> : P
457-
//
458-
// We want to build substitutions in terms of Derived.foo()'s
459-
// generic signature:
460-
//
461-
// <T2, U2 where T2 : Q>
462-
// T2 := Bar
463-
// T2 : Q := Bar : Q
464-
//
465-
// The conformance Bar : Q is difficult to recover in the general case.
466-
//
467-
// Some combination of storing substitution maps in BoundGenericTypes
468-
// as well as for method overrides would solve this, but for now, just
469-
// punt to module lookup.
470-
if (substType->isTypeParameter())
471-
return ProtocolConformanceRef(proto);
472-
473-
return swift::lookupConformance(substType, proto);
474-
});
423+
// We might not have enough information in the substitution maps alone.
424+
//
425+
// Eg,
426+
//
427+
// class Base<T1> {
428+
// func foo<U1>(_: U1) where T1 : P {}
429+
// }
430+
//
431+
// class Derived<T2> : Base<Foo<T2>> {
432+
// override func foo<U2>(_: U2) where T2 : Q {}
433+
// }
434+
//
435+
// Suppose we're devirtualizing a call to Base.foo() on a value whose
436+
// type is known to be Derived<Bar>. We start with substitutions written
437+
// in terms of Base.foo()'s generic signature:
438+
//
439+
// <T1, U1 where T1 : P>
440+
// T1 := Foo<Bar>
441+
// T1 : P := Foo<Bar> : P
442+
//
443+
// We want to build substitutions in terms of Derived.foo()'s
444+
// generic signature:
445+
//
446+
// <T2, U2 where T2 : Q>
447+
// T2 := Bar
448+
// T2 : Q := Bar : Q
449+
//
450+
// The conformance Bar : Q is difficult to recover in the general case.
451+
//
452+
// Some combination of storing substitution maps in BoundGenericTypes
453+
// as well as for method overrides would solve this, but for now, just
454+
// punt to global lookup.
455+
LookUpConformanceInModule());
475456
}
476457

477458
// Start with the substitutions from the apply.

test/SILOptimizer/rdar134732867.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: %target-swift-frontend -emit-sil -O %s
2+
3+
public class Base<T> {
4+
@inline(never)
5+
func f<E>(_: E, _ t: T, _ elt: T.Element) -> Bool where T: Sequence, T.Element: Equatable {
6+
var iter = t.makeIterator()
7+
return iter.next()! == elt
8+
}
9+
}
10+
11+
public func caller(b: Base<Array<Int>>) -> Bool {
12+
return b.f(123, [1, 2, 3], 5)
13+
}

0 commit comments

Comments
 (0)