Skip to content

Commit c009650

Browse files
committed
[SIL] Standardize on printing the replacement types for a SubstitutionMap.
SIL printing and parsing was based on printing substitution lists. Change that to instead print/parse based on the replacement types in substitution maps, which fits more closely with the rest of the system. This commit is papering over an issue where the substitution maps generated for the “apply” of a partial specialization use an ever-so-slightly different generic signature than partial specialization itself. The TODO in the SIL printer for covers that case.
1 parent f227952 commit c009650

File tree

7 files changed

+90
-101
lines changed

7 files changed

+90
-101
lines changed

lib/AST/ASTPrinter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4157,8 +4157,8 @@ void ProtocolConformance::printName(llvm::raw_ostream &os,
41574157
case ProtocolConformanceKind::Specialized: {
41584158
auto spec = cast<SpecializedProtocolConformance>(this);
41594159
os << "specialize <";
4160-
interleave(spec->getSubstitutionMap().toList(),
4161-
[&](const Substitution &s) { s.print(os, PO); },
4160+
interleave(spec->getSubstitutionMap().getReplacementTypes(),
4161+
[&](Type type) { type.print(os, PO); },
41624162
[&] { os << ", "; });
41634163

41644164
os << "> (";

lib/ParseSIL/ParseSIL.cpp

Lines changed: 67 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1566,57 +1566,58 @@ static bool getConformancesForSubstitution(Parser &P,
15661566
return false;
15671567
}
15681568

1569-
/// Reconstruct AST substitutions from parsed substitutions using archetypes
1570-
/// from a SILFunctionType.
1571-
bool getApplySubstitutionsFromParsed(
1569+
/// Reconstruct an AST substitution map from parsed substitutions.
1570+
SubstitutionMap getApplySubstitutionsFromParsed(
15721571
SILParser &SP,
15731572
GenericEnvironment *env,
1574-
ArrayRef<ParsedSubstitution> parses,
1575-
SmallVectorImpl<Substitution> &subs) {
1573+
ArrayRef<ParsedSubstitution> parses) {
15761574
if (parses.empty()) {
15771575
assert(!env);
1578-
return false;
1576+
return SubstitutionMap();
15791577
}
15801578

15811579
assert(env);
15821580

15831581
auto loc = parses[0].loc;
15841582

1585-
// The replacement is for the corresponding dependent type by ordering.
1586-
auto result = env->getGenericSignature()->enumeratePairedRequirements(
1587-
[&](Type depTy, ArrayRef<Requirement> reqts) -> bool {
1588-
if (parses.empty()) {
1589-
SP.P.diagnose(loc, diag::sil_missing_substitutions);
1590-
return true;
1591-
}
1592-
auto parsed = parses.front();
1593-
parses = parses.slice(1);
1594-
1595-
SmallVector<ProtocolConformanceRef, 2> conformances;
1596-
SmallVector<Type, 2> protocols;
1597-
for (auto reqt : reqts)
1598-
protocols.push_back(reqt.getSecondType());
1599-
1600-
if (getConformancesForSubstitution(SP.P,
1601-
ExistentialLayout::ProtocolTypeArrayRef(protocols),
1602-
parsed.replacement,
1603-
parsed.loc, conformances))
1604-
return true;
1605-
1606-
subs.push_back({parsed.replacement,
1607-
SP.P.Context.AllocateCopy(conformances)});
1608-
return false;
1583+
// Ensure that we have the right number of type arguments.
1584+
auto genericSig = env->getGenericSignature();
1585+
if (parses.size() != genericSig->getGenericParams().size()) {
1586+
bool hasTooFew = parses.size() < genericSig->getGenericParams().size();
1587+
SP.P.diagnose(loc,
1588+
hasTooFew ? diag::sil_missing_substitutions
1589+
: diag::sil_too_many_substitutions);
1590+
return SubstitutionMap();
1591+
}
1592+
1593+
bool failed = false;
1594+
SubstitutionMap subMap = genericSig->getSubstitutionMap(
1595+
[&](SubstitutableType *type) -> Type {
1596+
auto genericParam = dyn_cast<GenericTypeParamType>(type);
1597+
if (!genericParam) return nullptr;
1598+
1599+
auto index = genericSig->getGenericParamOrdinal(genericParam);
1600+
assert(index < genericSig->getGenericParams().size());
1601+
assert(index < parses.size());
1602+
1603+
// Provide the replacement type.
1604+
return parses[index].replacement;
1605+
},
1606+
[&](CanType dependentType, Type replacementType,
1607+
ProtocolType *protoTy) ->Optional<ProtocolConformanceRef> {
1608+
auto M = SP.P.SF.getParentModule();
1609+
auto conformance = M->lookupConformance(replacementType,
1610+
protoTy->getDecl());
1611+
if (conformance) return conformance;
1612+
1613+
SP.P.diagnose(loc, diag::sil_substitution_mismatch, replacementType,
1614+
protoTy);
1615+
failed = true;
1616+
1617+
return ProtocolConformanceRef(protoTy->getDecl());
16091618
});
16101619

1611-
if (result)
1612-
return true;
1613-
1614-
if (!parses.empty()) {
1615-
SP.P.diagnose(loc, diag::sil_too_many_substitutions);
1616-
return true;
1617-
}
1618-
1619-
return false;
1620+
return failed ? SubstitutionMap() : subMap;
16201621
}
16211622

16221623
static ArrayRef<ProtocolConformanceRef>
@@ -1993,17 +1994,13 @@ SILParser::parseKeyPathPatternComponent(KeyPathPatternComponent &component,
19931994
diag::sil_substitutions_on_non_polymorphic_type);
19941995
return true;
19951996
}
1996-
if (getApplySubstitutionsFromParsed(*this, genericEnv,
1997-
parsedSubs, subs))
1998-
return true;
1999-
1997+
subsMap = getApplySubstitutionsFromParsed(*this, genericEnv, parsedSubs);
1998+
if (!subsMap) return true;
1999+
20002000
// Map the substitutions out of the pattern context so that they
20012001
// use interface types.
2002-
subsMap = genericEnv->getGenericSignature()
2003-
->getSubstitutionMap(subs);
20042002
subsMap = subsMap.mapReplacementTypesOutOfContext().getCanonical();
20052003
}
2006-
20072004

20082005
auto indexesCopy = P.Context.AllocateCopy(indexes);
20092006

@@ -2563,11 +2560,9 @@ bool SILParser::parseSILInstruction(SILBuilder &B) {
25632560
P.diagnose(P.Tok, diag::sil_substitutions_on_non_polymorphic_type);
25642561
return true;
25652562
}
2566-
SmallVector<Substitution, 4> subs;
2567-
if (getApplySubstitutionsFromParsed(*this, genericEnv, parsedSubs, subs))
2563+
subMap = getApplySubstitutionsFromParsed(*this, genericEnv, parsedSubs);
2564+
if (!subMap)
25682565
return true;
2569-
2570-
subMap = genericEnv->getGenericSignature()->getSubstitutionMap(subs);
25712566
}
25722567

25732568
if (P.Tok.getKind() != tok::l_paren) {
@@ -2913,24 +2908,22 @@ bool SILParser::parseSILInstruction(SILBuilder &B) {
29132908
P.diagnose(InstLoc.getSourceLoc(), diag::sil_keypath_no_root);
29142909

29152910
SmallVector<ParsedSubstitution, 4> parsedSubs;
2916-
SmallVector<Substitution, 4> subs;
29172911
if (parseSubstitutions(parsedSubs, ContextGenericEnv))
29182912
return true;
29192913

2914+
SubstitutionMap subMap;
29202915
if (!parsedSubs.empty()) {
29212916
if (!patternEnv) {
29222917
P.diagnose(InstLoc.getSourceLoc(),
29232918
diag::sil_substitutions_on_non_polymorphic_type);
29242919
return true;
29252920
}
2926-
if (getApplySubstitutionsFromParsed(*this, patternEnv, parsedSubs, subs))
2921+
2922+
subMap = getApplySubstitutionsFromParsed(*this, patternEnv, parsedSubs);
2923+
if (!subMap)
29272924
return true;
29282925
}
29292926

2930-
SubstitutionMap subMap;
2931-
if (patternEnv && patternEnv->getGenericSignature())
2932-
subMap = patternEnv->getGenericSignature()->getSubstitutionMap(subs);
2933-
29342927
SmallVector<SILValue, 4> operands;
29352928

29362929
if (P.consumeIf(tok::l_paren)) {
@@ -3312,22 +3305,19 @@ bool SILParser::parseSILInstruction(SILBuilder &B) {
33123305

33133306
SubstitutionMap InitStorageSubs, SetterSubs;
33143307
{
3315-
SmallVector<Substitution, 4> InitStorageSubsVec, SetterSubsVec;
3316-
if (getApplySubstitutionsFromParsed(*this, InitStorageEnv,
3317-
ParsedInitStorageSubs,
3318-
InitStorageSubsVec)
3319-
|| getApplySubstitutionsFromParsed(*this, SetterEnv,
3320-
ParsedSetterSubs, SetterSubsVec))
3321-
return true;
3322-
33233308
if (InitStorageEnv) {
3324-
InitStorageSubs = InitStorageEnv->getGenericSignature()
3325-
->getSubstitutionMap(InitStorageSubsVec);
3309+
InitStorageSubs =
3310+
getApplySubstitutionsFromParsed(*this, InitStorageEnv,
3311+
ParsedInitStorageSubs);
3312+
if (!InitStorageSubs)
3313+
return true;
33263314
}
33273315

33283316
if (SetterEnv) {
3329-
SetterSubs = SetterEnv->getGenericSignature()
3330-
->getSubstitutionMap(SetterSubsVec);
3317+
SetterSubs = getApplySubstitutionsFromParsed(*this, SetterEnv,
3318+
ParsedSetterSubs);
3319+
if (!SetterSubs)
3320+
return true;
33313321
}
33323322
}
33333323

@@ -4861,14 +4851,11 @@ bool SILParser::parseSILInstruction(SILBuilder &B) {
48614851
P.diagnose(typeLoc, diag::sil_substitutions_on_non_polymorphic_type);
48624852
return true;
48634853
}
4864-
SmallVector<Substitution, 4> subs;
4865-
if (getApplySubstitutionsFromParsed(*this,
4866-
invokeGenericEnv,
4867-
parsedSubs, subs))
4868-
return true;
48694854

4870-
subMap = invokeGenericEnv->getGenericSignature()
4871-
->getSubstitutionMap(subs);
4855+
subMap = getApplySubstitutionsFromParsed(*this, invokeGenericEnv,
4856+
parsedSubs);
4857+
if (!subMap)
4858+
return true;
48724859
}
48734860

48744861
ResultVal = B.createInitBlockStorageHeader(InstLoc, Val, invokeVal,
@@ -4949,10 +4936,9 @@ bool SILParser::parseCallInstruction(SILLocation InstLoc,
49494936
P.diagnose(TypeLoc, diag::sil_substitutions_on_non_polymorphic_type);
49504937
return true;
49514938
}
4952-
SmallVector<Substitution, 4> subsVec;
4953-
if (getApplySubstitutionsFromParsed(*this, GenericEnv, parsedSubs, subsVec))
4939+
subs = getApplySubstitutionsFromParsed(*this, GenericEnv, parsedSubs);
4940+
if (!subs)
49544941
return true;
4955-
subs = GenericEnv->getGenericSignature()->getSubstitutionMap(subsVec);
49564942
}
49574943

49584944
SILValue FnVal = getLocalValue(FnName, Ty, InstLoc, B);
@@ -5809,13 +5795,11 @@ ProtocolConformance *SILParser::parseProtocolConformanceHelper(
58095795
if (P.parseToken(tok::r_paren, diag::expected_sil_witness_rparen))
58105796
return nullptr;
58115797

5812-
SmallVector<Substitution, 4> subs;
5813-
if (getApplySubstitutionsFromParsed(*this, specializedEnv, parsedSubs,
5814-
subs))
5798+
SubstitutionMap subMap =
5799+
getApplySubstitutionsFromParsed(*this, specializedEnv, parsedSubs);
5800+
if (!subMap)
58155801
return nullptr;
58165802

5817-
auto subMap =
5818-
genericConform->getGenericSignature()->getSubstitutionMap(subs);
58195803
auto result = P.Context.getSpecializedConformance(
58205804
ConformingTy, genericConform, subMap);
58215805
return result;

lib/SIL/SILPrinter.cpp

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,25 +1065,30 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
10651065
printDebugVar(ABI->getVarInfo());
10661066
}
10671067

1068-
void printSubstitutions(SubstitutionMap Subs) {
1069-
printSubstitutions(Subs.toList());
1070-
}
1068+
void printSubstitutions(SubstitutionMap Subs,
1069+
GenericSignature *Sig = nullptr) {
1070+
if (!Subs.hasAnySubstitutableParams()) return;
1071+
1072+
// FIXME: This is a hack to cope with cases where the substitution map uses
1073+
// a generic signature that's close-to-but-not-the-same-as expected.
1074+
auto genericSig = Sig ? Sig : Subs.getGenericSignature();
10711075

1072-
void printSubstitutions(SubstitutionList Subs) {
1073-
if (Subs.empty())
1074-
return;
1075-
10761076
*this << '<';
1077-
interleave(Subs,
1078-
[&](const Substitution &s) { *this << s.getReplacement(); },
1079-
[&] { *this << ", "; });
1077+
bool first = true;
1078+
for (auto gp : genericSig->getGenericParams()) {
1079+
if (first) first = false;
1080+
else *this << ", ";
1081+
1082+
*this << Type(gp).subst(Subs);
1083+
}
10801084
*this << '>';
10811085
}
10821086

10831087
template <class Inst>
10841088
void visitApplyInstBase(Inst *AI) {
10851089
*this << Ctx.getID(AI->getCallee());
1086-
printSubstitutions(AI->getSubstitutionMap());
1090+
printSubstitutions(AI->getSubstitutionMap(),
1091+
AI->getOrigCalleeType()->getGenericSignature());
10871092
*this << '(';
10881093
interleave(AI->getArguments(),
10891094
[&](const SILValue &arg) { *this << Ctx.getID(arg); },

test/IRGen/partial_apply.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ sil hidden_external @complex_generic_function : $@convention(thin) <T where T :
384384
sil @partial_apply_complex_generic_function : $@convention(thin) <T where T : P2, T.Y : P2> (Int) -> () {
385385
bb0(%0 : $Int):
386386
%fn = function_ref @complex_generic_function : $@convention(thin) <T where T : P2, T.Y : P2> (Int) -> ()
387-
%pa = partial_apply %fn <T, T.Y>(%0) : $@convention(thin) <T where T : P2, T.Y : P1, T.Y : P2> (Int) -> ()
387+
%pa = partial_apply %fn <T>(%0) : $@convention(thin) <T where T : P2, T.Y : P1, T.Y : P2> (Int) -> ()
388388
%result = tuple ()
389389
return %result : $()
390390
}

test/SILGen/newtype.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,14 @@ func bridgeToNewtype() -> MyString {
7070
// CHECK-RAW: [[TO_MY:%.*]] = function_ref @$Ss20_SwiftNewtypeWrapperPss21_ObjectiveCBridgeable8RawValueRpzrlE026_unconditionallyBridgeFromD1CyxAD_01_D5CTypeQZSgFZ : $@convention(method) <τ_0_0 where τ_0_0 : _SwiftNewtypeWrapper, τ_0_0.RawValue : _ObjectiveCBridgeable> (@guaranteed Optional<τ_0_0.RawValue._ObjectiveCType>, @thick τ_0_0.Type)
7171
// CHECK-RAW: [[OPTNS:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[NS]]
7272
// CHECK-RAW: [[META:%.*]] = metatype $@thick MyString.Type
73-
// CHECK-RAW: apply [[TO_MY]]<MyString, String>({{.*}}, [[OPTNS]], [[META]])
73+
// CHECK-RAW: apply [[TO_MY]]<MyString>({{.*}}, [[OPTNS]], [[META]])
7474
return "foo" as NSString as MyString
7575
}
7676

7777
// CHECK-RAW-LABEL: sil hidden @$S7newtype17bridgeFromNewtype6stringSSSo8MyStringa_tF
7878
func bridgeFromNewtype(string: MyString) -> String {
7979
// CHECK-RAW: [[FROM_MY:%.*]] = function_ref @$Ss20_SwiftNewtypeWrapperPss21_ObjectiveCBridgeable8RawValueRpzrlE09_bridgeToD1CAD_01_D5CTypeQZyF : $@convention(method) <τ_0_0 where τ_0_0 : _SwiftNewtypeWrapper, τ_0_0.RawValue : _ObjectiveCBridgeable> (@in_guaranteed τ_0_0) -> @owned τ_0_0.RawValue._ObjectiveCType
80-
// CHECK-RAW: [[NS:%.*]] = apply [[FROM_MY]]<MyString, String>(
80+
// CHECK-RAW: [[NS:%.*]] = apply [[FROM_MY]]<MyString>(
8181
// CHECK-RAW: [[FROM_NS:%.*]] = function_ref @$SSS10FoundationE36_unconditionallyBridgeFromObjectiveCySSSo8NSStringCSgFZ
8282
// CHECK-RAW: [[OPTNS:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[NS]]
8383
// CHECK-RAW: [[META:%.*]] = metatype $@thin String.Type

test/SILGen/opaque_ownership.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ public struct Int64 : ExpressibleByIntegerLiteral, _ExpressibleByBuiltinIntegerL
153153
// CHECK-LABEL: sil shared [transparent] [serialized] [thunk] @$Ss17FloatingPointSignOs9EquatablessACP2eeoiySbx_xtFZTW : $@convention(witness_method: Equatable) (@in_guaranteed FloatingPointSign, @in_guaranteed FloatingPointSign, @thick FloatingPointSign.Type) -> Bool {
154154
// CHECK: bb0(%0 : @trivial $FloatingPointSign, %1 : @trivial $FloatingPointSign, %2 : @trivial $@thick FloatingPointSign.Type):
155155
// CHECK: %3 = function_ref @$Ss2eeoiySbx_xts16RawRepresentableRzs9Equatable0B5ValueRpzlF : $@convention(thin) <τ_0_0 where τ_0_0 : RawRepresentable, τ_0_0.RawValue : Equatable> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0) -> Bool
156-
// CHECK: %4 = apply %3<FloatingPointSign, Int64>(%0, %1) : $@convention(thin) <τ_0_0 where τ_0_0 : RawRepresentable, τ_0_0.RawValue : Equatable> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0) -> Bool
156+
// CHECK: %4 = apply %3<FloatingPointSign>(%0, %1) : $@convention(thin) <τ_0_0 where τ_0_0 : RawRepresentable, τ_0_0.RawValue : Equatable> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0) -> Bool
157157
// CHECK: return %4 : $Bool
158158
// CHECK-LABEL: } // end sil function '$Ss17FloatingPointSignOs9EquatablessACP2eeoiySbx_xtFZTW'
159159
public enum FloatingPointSign: Int64 {

test/SILOptimizer/eager_specialize.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -638,7 +638,7 @@ bb0(%0 : $*T, %1 : $*S):
638638
// CHECK: %15 = unchecked_addr_cast %1 : $*S to $*S
639639
// function_ref specialized checkExplicitPartialSpecialization<A, B> (A, B) -> ()
640640
// CHECK: %16 = function_ref @$S16eager_specialize34checkExplicitPartialSpecializationyyx_q_tr0_lFs5Int64Vq_ADRszr0_lIetyi_Tp5 : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 == Int64> (Int64, @in τ_0_1) -> ()
641-
// CHECK: %17 = apply %16<S>(%14, %15) : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 == Int64> (Int64, @in τ_0_1) -> ()
641+
// CHECK: %17 = apply %16<Int64, S>(%14, %15) : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 == Int64> (Int64, @in τ_0_1) -> ()
642642
// CHECK: %18 = tuple ()
643643
// CHECK: %19 = unchecked_trivial_bit_cast %18 : $() to $()
644644
// CHECK: br bb2

0 commit comments

Comments
 (0)