Skip to content

Commit 3ed0e19

Browse files
authored
Merge pull request swiftlang#28671 from jckarter/subst-function-type-basics
SIL: Parsing and serialization support for subst function types
2 parents c8d2ec2 + 4742968 commit 3ed0e19

20 files changed

+267
-53
lines changed

include/swift/AST/ASTMangler.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,9 @@ class ASTMangler : public Mangler {
245245
unsigned appendBoundGenericArgs(DeclContext *dc,
246246
SubstitutionMap subs,
247247
bool &isFirstArgList);
248+
249+
/// Append the bound generic arguments as a flat list, disregarding depth.
250+
void appendFlatGenericArgs(SubstitutionMap subs);
248251

249252
/// Append any retroactive conformances.
250253
void appendRetroactiveConformances(Type type);

include/swift/AST/DiagnosticsParse.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -803,6 +803,12 @@ ERROR(sil_box_expected_r_brace,none,
803803
ERROR(sil_box_expected_r_angle,none,
804804
"expected '>' to complete SIL box generic argument list", ())
805805

806+
// SIL function types
807+
ERROR(sil_function_subst_expected_l_angle,none,
808+
"expected '<' to begin SIL function type substitution list after 'for'", ())
809+
ERROR(sil_function_subst_expected_r_angle,none,
810+
"expected '>' to begin SIL function type substitution list after 'for'", ())
811+
806812
// Opaque types
807813
ERROR(opaque_mid_composition,none,
808814
"'some' should appear at the beginning of a composition", ())

include/swift/AST/TypeRepr.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -471,10 +471,12 @@ inline IdentTypeRepr::ComponentRange IdentTypeRepr::getComponentRange() {
471471
/// (x: Foo, y: Bar) -> Baz
472472
/// \endcode
473473
class FunctionTypeRepr : public TypeRepr {
474-
// These three are only used in SIL mode, which is the only time
475-
// we can have polymorphic function values.
474+
// These fields are only used in SIL mode, which is the only time
475+
// we can have polymorphic and substituted function values.
476476
GenericParamList *GenericParams;
477477
GenericEnvironment *GenericEnv;
478+
bool GenericParamsAreImplied;
479+
ArrayRef<TypeRepr *> GenericSubs;
478480

479481
TupleTypeRepr *ArgsTy;
480482
TypeRepr *RetTy;
@@ -483,16 +485,22 @@ class FunctionTypeRepr : public TypeRepr {
483485

484486
public:
485487
FunctionTypeRepr(GenericParamList *genericParams, TupleTypeRepr *argsTy,
486-
SourceLoc throwsLoc, SourceLoc arrowLoc, TypeRepr *retTy)
488+
SourceLoc throwsLoc, SourceLoc arrowLoc, TypeRepr *retTy,
489+
bool GenericParamsAreImplied = false,
490+
ArrayRef<TypeRepr *> GenericSubs = {})
487491
: TypeRepr(TypeReprKind::Function),
488492
GenericParams(genericParams),
489493
GenericEnv(nullptr),
494+
GenericParamsAreImplied(GenericParamsAreImplied),
495+
GenericSubs(GenericSubs),
490496
ArgsTy(argsTy), RetTy(retTy),
491497
ArrowLoc(arrowLoc), ThrowsLoc(throwsLoc) {
492498
}
493499

494500
GenericParamList *getGenericParams() const { return GenericParams; }
495501
GenericEnvironment *getGenericEnvironment() const { return GenericEnv; }
502+
bool areGenericParamsImplied() const { return GenericParamsAreImplied; }
503+
ArrayRef<TypeRepr*> getSubstitutions() const { return GenericSubs; }
496504

497505
void setGenericEnvironment(GenericEnvironment *genericEnv) {
498506
assert(GenericEnv == nullptr);

include/swift/Demangling/DemangleNodes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ NODE(ImplEscaping)
113113
NODE(ImplConvention)
114114
NODE(ImplFunctionAttribute)
115115
NODE(ImplFunctionType)
116+
NODE(ImplImpliedSubstitutions)
117+
NODE(ImplSubstitutions)
116118
CONTEXT_NODE(ImplicitClosure)
117119
NODE(ImplParameter)
118120
NODE(ImplResult)

include/swift/SIL/TypeLowering.h

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -967,23 +967,27 @@ class TypeConverter {
967967
enum class ABIDifference : uint8_t {
968968
// Types have compatible calling conventions and representations, so can
969969
// be trivially bitcast.
970+
//
971+
// Furthermore, if two function types have
972+
// arguments of function type that differ only in
973+
// `CompatibleRepresentation`, those outer function types are transitively
974+
// `CompatibleRepresentation`. (In all other cases, the outer function types
975+
// would fall into the `NeedsThunk` case, because a thunk would be needed
976+
// to change the representation of the function argument.)
970977
CompatibleRepresentation,
971978

972-
// No convention differences, function can be cast via `convert_function`
973-
// without a thunk.
974-
//
975-
// There may still be a representation difference between values of the
976-
// compared function types. This means that, if two function types
977-
// have a matching argument or return of function type with
978-
// `SameCallingConvention`, then the outer function types may not themselves
979-
// have the `SameCallingConvention` because they need a thunk to convert
980-
// the inner function value representation.
979+
// No convention differences, but there may still be a representation
980+
// difference between values of the compared function types, such as a
981+
// different ptrauth discriminator. The conversion can be performed by a
982+
// `convert_function` instruction.
981983
CompatibleCallingConvention,
982984

983-
// Representation difference requires thin-to-thick conversion.
985+
// Representation difference requires thin-to-thick conversion with a
986+
// `thin_to_thick_function` conversion.
984987
CompatibleRepresentation_ThinToThick,
985-
// Function types have the `SameCallingConvention` but additionally need
986-
// a thin-to-thick conversion.
988+
// Function types have `CompatibleCallingConvention` but additionally need
989+
// a thin-to-thick conversion, so a `convert_function` followed by a
990+
// `thin_to_thick_function` sequence is necessary to convert.
987991
CompatibleCallingConvention_ThinToThick,
988992

989993
// Non-trivial difference requires thunk.

lib/AST/ASTMangler.cpp

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1201,6 +1201,16 @@ void ASTMangler::bindGenericParameters(const DeclContext *DC) {
12011201
bindGenericParameters(sig->getCanonicalSignature());
12021202
}
12031203

1204+
void ASTMangler::appendFlatGenericArgs(SubstitutionMap subs) {
1205+
appendOperator("y");
1206+
1207+
for (auto replacement : subs.getReplacementTypes()) {
1208+
if (replacement->hasArchetype())
1209+
replacement = replacement->mapTypeOutOfContext();
1210+
appendType(replacement);
1211+
}
1212+
}
1213+
12041214
unsigned ASTMangler::appendBoundGenericArgs(DeclContext *dc,
12051215
SubstitutionMap subs,
12061216
bool &isFirstArgList) {
@@ -1429,6 +1439,13 @@ void ASTMangler::appendImplFunctionType(SILFunctionType *fn) {
14291439

14301440
llvm::SmallVector<char, 32> OpArgs;
14311441

1442+
if (fn->getSubstitutions()) {
1443+
OpArgs.push_back('s');
1444+
if (!fn->isGenericSignatureImplied()) {
1445+
OpArgs.push_back('i');
1446+
}
1447+
}
1448+
14321449
if (fn->isPolymorphic() && fn->isPseudogeneric())
14331450
OpArgs.push_back('P');
14341451

@@ -1465,7 +1482,7 @@ void ASTMangler::appendImplFunctionType(SILFunctionType *fn) {
14651482
OpArgs.push_back('W');
14661483
break;
14671484
}
1468-
1485+
14691486
// Mangle the parameters.
14701487
for (auto param : fn->getParameters()) {
14711488
OpArgs.push_back(getParamConvention(param.getConvention()));
@@ -1485,8 +1502,13 @@ void ASTMangler::appendImplFunctionType(SILFunctionType *fn) {
14851502
OpArgs.push_back(getResultConvention(error.getConvention()));
14861503
appendType(error.getInterfaceType());
14871504
}
1488-
if (fn->isPolymorphic())
1489-
appendGenericSignature(fn->getSubstGenericSignature());
1505+
if (auto sig = fn->getSubstGenericSignature()) {
1506+
appendGenericSignature(sig);
1507+
}
1508+
if (auto subs = fn->getSubstitutions()) {
1509+
appendFlatGenericArgs(subs);
1510+
appendRetroactiveConformances(subs, Mod);
1511+
}
14901512

14911513
OpArgs.push_back('_');
14921514

lib/AST/Type.cpp

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3559,8 +3559,8 @@ static Type substType(Type derivedType,
35593559
"should not be doing AST type-substitution on a lowered SIL type;"
35603560
"use SILType::subst");
35613561

3562-
// Special-case handle SILBoxTypes; we want to structurally substitute the
3563-
// substitutions.
3562+
// Special-case handle SILBoxTypes and substituted SILFunctionTypes;
3563+
// we want to structurally substitute the substitutions.
35643564
if (auto boxTy = dyn_cast<SILBoxType>(type)) {
35653565
auto subMap = boxTy->getSubstitutions();
35663566
auto newSubMap = subMap.subst(substitutions, lookupConformances);
@@ -3569,6 +3569,14 @@ static Type substType(Type derivedType,
35693569
boxTy->getLayout(),
35703570
newSubMap);
35713571
}
3572+
3573+
if (auto silFnTy = dyn_cast<SILFunctionType>(type)) {
3574+
if (auto subs = silFnTy->getSubstitutions()) {
3575+
auto newSubs = subs.subst(substitutions, lookupConformances);
3576+
return silFnTy->withSubstitutions(newSubs);
3577+
}
3578+
}
3579+
35723580

35733581
// Special-case TypeAliasType; we need to substitute conformances.
35743582
if (auto aliasTy = dyn_cast<TypeAliasType>(type)) {
@@ -4835,3 +4843,14 @@ CanType swift::substOpaqueTypesWithUnderlyingTypes(CanType ty,
48354843
SubstFlags::SubstituteOpaqueArchetypes | SubstFlags::AllowLoweredTypes;
48364844
return ty.subst(replacer, replacer, flags)->getCanonicalType();
48374845
}
4846+
4847+
CanSILFunctionType
4848+
SILFunctionType::withSubstitutions(SubstitutionMap subs) const {
4849+
return SILFunctionType::get(getSubstGenericSignature(),
4850+
getExtInfo(), getCoroutineKind(),
4851+
getCalleeConvention(),
4852+
getParameters(), getYields(), getResults(),
4853+
getOptionalErrorResult(),
4854+
subs, isGenericSignatureImplied(),
4855+
const_cast<SILFunctionType*>(this)->getASTContext());
4856+
}

lib/Demangling/Demangler.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1733,6 +1733,24 @@ NodePointer Demangler::demangleImplResultConvention(Node::Kind ConvKind) {
17331733
NodePointer Demangler::demangleImplFunctionType() {
17341734
NodePointer type = createNode(Node::Kind::ImplFunctionType);
17351735

1736+
if (nextIf('s')) {
1737+
Vector<NodePointer> Substitutions;
1738+
NodePointer SubstitutionRetroConformances;
1739+
if (!demangleBoundGenerics(Substitutions, SubstitutionRetroConformances))
1740+
return nullptr;
1741+
1742+
bool isImplied = !nextIf('i');
1743+
1744+
auto subsNode = createNode(isImplied
1745+
? Node::Kind::ImplImpliedSubstitutions
1746+
: Node::Kind::ImplSubstitutions);
1747+
assert(Substitutions.size() == 1);
1748+
subsNode->addChild(Substitutions[0], *this);
1749+
if (SubstitutionRetroConformances)
1750+
subsNode->addChild(SubstitutionRetroConformances, *this);
1751+
type->addChild(subsNode, *this);
1752+
}
1753+
17361754
NodePointer GenSig = popNode(Node::Kind::DependentGenericSignature);
17371755
if (GenSig && nextIf('P'))
17381756
GenSig = changeKind(GenSig, Node::Kind::DependentPseudogenericSignature);
@@ -1794,6 +1812,7 @@ NodePointer Demangler::demangleImplFunctionType() {
17941812
return nullptr;
17951813
type->getChild(type->getNumChildren() - Idx - 1)->addChild(ConvTy, *this);
17961814
}
1815+
17971816
return createType(type);
17981817
}
17991818

lib/Demangling/NodePrinter.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,8 @@ class NodePrinter {
390390
case Node::Kind::ImplConvention:
391391
case Node::Kind::ImplFunctionAttribute:
392392
case Node::Kind::ImplFunctionType:
393+
case Node::Kind::ImplImpliedSubstitutions:
394+
case Node::Kind::ImplSubstitutions:
393395
case Node::Kind::ImplicitClosure:
394396
case Node::Kind::ImplParameter:
395397
case Node::Kind::ImplResult:
@@ -979,7 +981,7 @@ static bool needSpaceBeforeType(NodePointer Type) {
979981
}
980982

981983
NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) {
982-
switch (Node->getKind()) {
984+
switch (auto kind = Node->getKind()) {
983985
case Node::Kind::Static:
984986
Printer << "static ";
985987
print(Node->getChild(0));
@@ -2016,6 +2018,14 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) {
20162018
case Node::Kind::ImplFunctionType:
20172019
printImplFunctionType(Node);
20182020
return nullptr;
2021+
case Node::Kind::ImplSubstitutions:
2022+
case Node::Kind::ImplImpliedSubstitutions:
2023+
Printer << "for <";
2024+
printChildren(Node->getChild(0), ", ");
2025+
Printer << '>';
2026+
if (kind == Node::Kind::ImplImpliedSubstitutions)
2027+
Printer << " in";
2028+
return nullptr;
20192029
case Node::Kind::ErrorType:
20202030
Printer << "<ERROR TYPE>";
20212031
return nullptr;

lib/Demangling/OldRemangler.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1252,6 +1252,14 @@ void Remangler::mangleImplEscaping(Node *node) {
12521252
// The old mangler does not encode escaping.
12531253
}
12541254

1255+
void Remangler::mangleImplSubstitutions(Node *node) {
1256+
// The old mangler does not encode substituted function types.
1257+
}
1258+
1259+
void Remangler::mangleImplImpliedSubstitutions(Node *node) {
1260+
// The old mangler does not encode substituted function types.
1261+
}
1262+
12551263
void Remangler::mangleImplConvention(Node *node) {
12561264
assert(node->getKind() == Node::Kind::ImplConvention);
12571265
StringRef text = node->getText();

0 commit comments

Comments
 (0)