Skip to content

Commit 84e20b6

Browse files
committed
SIL parser support for substituted function types
1 parent 8a45d5a commit 84e20b6

File tree

6 files changed

+98
-7
lines changed

6 files changed

+98
-7
lines changed

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);

lib/AST/Type.cpp

Lines changed: 10 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)) {

lib/Parse/ParseType.cpp

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,12 +374,15 @@ ParserResult<TypeRepr> Parser::parseType(Diag<> MessageID,
374374

375375
// Parse generic parameters in SIL mode.
376376
GenericParamList *generics = nullptr;
377+
bool isImplied = false;
377378
if (isInSILMode()) {
378379
// If this is part of a sil function decl, generic parameters are visible in
379380
// the function body; otherwise, they are visible when parsing the type.
380381
if (!IsSILFuncDecl)
381382
GenericsScope.emplace(this, ScopeKind::Generics);
382383
generics = maybeParseGenericParams().getPtrOrNull();
384+
385+
isImplied = consumeIf(tok::kw_in);
383386
}
384387

385388
// In SIL mode, parse box types { ... }.
@@ -477,9 +480,42 @@ ParserResult<TypeRepr> Parser::parseType(Diag<> MessageID,
477480
tyR->getSourceRange());
478481
}
479482
}
483+
484+
// Parse substitutions for substituted SIL types.
485+
SourceLoc SubsLAngleLoc, SubsRAngleLoc;
486+
MutableArrayRef<TypeRepr *> SubsTypes;
487+
if (isInSILMode() && consumeIf(tok::kw_for)) {
488+
if (!Tok.isContextualPunctuator("<")) {
489+
diagnose(Tok, diag::sil_function_subst_expected_l_angle);
490+
return makeParserError();
491+
}
492+
493+
SubsLAngleLoc = consumeToken();
494+
495+
SmallVector<TypeRepr*, 4> SubsTypesVec;
496+
for (;;) {
497+
auto argTy = parseType();
498+
if (!argTy.getPtrOrNull())
499+
return makeParserError();
500+
SubsTypesVec.push_back(argTy.get());
501+
if (consumeIf(tok::comma))
502+
continue;
503+
break;
504+
}
505+
if (!Tok.isContextualPunctuator(">")) {
506+
diagnose(Tok, diag::sil_function_subst_expected_r_angle);
507+
return makeParserError();
508+
}
509+
510+
SubsRAngleLoc = consumeToken();
511+
512+
SubsTypes = Context.AllocateCopy(SubsTypesVec);
513+
}
480514

481515
tyR = new (Context) FunctionTypeRepr(generics, argsTyR, throwsLoc, arrowLoc,
482-
SecondHalf.get());
516+
SecondHalf.get(),
517+
isImplied,
518+
SubsTypes);
483519
} else if (generics) {
484520
// Only function types may be generic.
485521
auto brackets = generics->getSourceRange();

lib/Sema/TypeCheckType.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2731,6 +2731,21 @@ Type TypeResolver::resolveSILFunctionType(FunctionTypeRepr *repr,
27312731
}
27322732
}
27332733
} // restore generic type resolution
2734+
2735+
// Resolve substitutions if we have them.
2736+
SubstitutionMap subs;
2737+
if (!repr->getSubstitutions().empty()) {
2738+
auto sig = repr->getGenericEnvironment()->getGenericSignature()
2739+
->getCanonicalSignature();
2740+
TypeSubstitutionMap subsMap;
2741+
auto params = sig->getGenericParams();
2742+
for (unsigned i : indices(repr->getSubstitutions())) {
2743+
auto resolved = resolveType(repr->getSubstitutions()[i], options);
2744+
subsMap.insert({params[i], resolved->getCanonicalType()});
2745+
}
2746+
subs = SubstitutionMap::get(sig, QueryTypeSubstitutionMap{subsMap},
2747+
TypeChecker::LookUpConformance(DC));
2748+
}
27342749

27352750
if (hasError) {
27362751
return ErrorType::get(Context);
@@ -2803,7 +2818,8 @@ Type TypeResolver::resolveSILFunctionType(FunctionTypeRepr *repr,
28032818
callee,
28042819
interfaceParams, interfaceYields,
28052820
interfaceResults, interfaceErrorResult,
2806-
SubstitutionMap(), false,
2821+
subs,
2822+
repr->areGenericParamsImplied(),
28072823
Context, witnessMethodConformance);
28082824
}
28092825

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %target-swift-emit-silgen %s | %FileCheck %s
2+
3+
sil_stage raw
4+
5+
import Swift
6+
7+
// CHECK-LABEL: sil @test : $@convention(thin) (@guaranteed @callee_guaranteed <τ_0_0, τ_0_1> in (@in τ_0_0, @in τ_0_1) -> () for <Int, String>) -> ()
8+
sil @test : $@convention(thin) (@guaranteed @callee_guaranteed <A, B> in (@in A, @in B) -> () for <Int, String>) -> () {
9+
entry(%0 : $@callee_guaranteed <C, D> in (@in C, @in D) -> () for <Int, String>):
10+
return undef : $()
11+
}
12+
13+
// CHECK-LABEL: sil @test_generic_context : $@convention(thin) <X, Y> (@guaranteed @callee_guaranteed <τ_0_0, τ_0_1> in (@in τ_0_0, @in τ_0_1) -> () for <X, Y>) -> ()
14+
sil @test_generic_context : $@convention(thin) <X, Y> (@guaranteed @callee_guaranteed <A, B> in (@in A, @in B) -> () for <X, Y>) -> () {
15+
entry(%0 : $@callee_guaranteed <C, D> in (@in C, @in D) -> () for <X, Y>):
16+
return undef : $()
17+
}

0 commit comments

Comments
 (0)