Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions docs/ABI/Mangling.rst
Original file line number Diff line number Diff line change
Expand Up @@ -583,10 +583,12 @@ mangled in to disambiguate.
::

impl-function-type ::= type* 'I' FUNC-ATTRIBUTES '_'
impl-function-type ::= type* generic-signature 'I' PSEUDO-GENERIC? FUNC-ATTRIBUTES '_'
impl-function-type ::= type* generic-signature 'I' FUNC-ATTRIBUTES '_'

FUNC-ATTRIBUTES ::= CALLEE-ESCAPE? CALLEE-CONVENTION FUNC-REPRESENTATION? COROUTINE-KIND? PARAM-CONVENTION* RESULT-CONVENTION* ('Y' PARAM-CONVENTION)* ('z' RESULT-CONVENTION)?
FUNC-ATTRIBUTES ::= PATTERN-SUBS? INVOCATION-SUBS? PSEUDO-GENERIC? CALLEE-ESCAPE? CALLEE-CONVENTION FUNC-REPRESENTATION? COROUTINE-KIND? PARAM-CONVENTION* RESULT-CONVENTION* ('Y' PARAM-CONVENTION)* ('z' RESULT-CONVENTION)?

PATTERN-SUBS ::= 's' // has pattern substitutions
INVOCATION-SUB ::= 'I' // has invocation substitutions
PSEUDO-GENERIC ::= 'P'

CALLEE-ESCAPE ::= 'e' // @escaping (inverse of SIL @noescape)
Expand Down
40 changes: 40 additions & 0 deletions docs/SIL.rst
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,46 @@ autorelease in the callee.
importer only imports non-native methods and types as ``throws``
when it is possible to do this automatically.

- SIL function types may provide a pattern signature and substitutions
to express that values of the type use a particular generic abstraction
pattern. Both must be provided together. If a pattern signature is
present, the component types (parameters, yields, and results) must be
expressed in terms of the generic parameters of that signature.
The pattern substitutions should be expressed in terms of the generic
parameters of the overall generic signature, if any, or else
the enclosing generic context, if any.

A pattern signature follows the ``@substituted`` attribute, which
must be the final attribute preceding the function type. Pattern
substitutions follow the function type, preceded by the ``for``
keyword. For example::

@substituted <T: Collection> (@in T) -> @out T.Element for Array<Int>

The low-level representation of a value of this type may not match
the representation of a value of the substituted-through version of it::

(@in Array<Int>) -> @out Int

Substitution differences at the outermost level of a function value
may be adjusted using the ``convert_function`` instruction. Note that
this only works at the outermost level and not in nested positions.
For example, a function which takes a parameter of the first type above
cannot be converted by ``convert_function`` to a function which takes
a parameter of the second type; such a conversion must be done with a
thunk.

Type substitution on a function type with a pattern signature and
substitutions only substitutes into the substitutions; the component
types are preserved with their exact original structure.

- In the implementation, a SIL function type may also carry substitutions
for its generic signature. This is a convenience for working with
applied generic types and is not generally a formal part of the SIL
language; in particular, values should not have such types. Such a
type behaves like a non-generic type, as if the substitutions were
actually applied to the underlying function type.

Coroutine Types
```````````````

Expand Down
8 changes: 8 additions & 0 deletions include/swift/AST/DiagnosticsParse.def
Original file line number Diff line number Diff line change
Expand Up @@ -828,6 +828,14 @@ ERROR(sil_function_subst_expected_l_angle,none,
"expected '<' to begin SIL function type substitution list after 'for'", ())
ERROR(sil_function_subst_expected_r_angle,none,
"expected '>' to end SIL function type substitution list after 'for <...'", ())
ERROR(sil_function_subst_expected_generics,none,
"expected '<' to begin substituted parameter list after '@substituted'", ())
ERROR(sil_function_subst_expected_function,none,
"expected function type after '@substituted'", ())
ERROR(sil_function_subst_expected_subs,none,
"expected 'for' to begin substitutions after '@substituted' function type", ())
ERROR(sil_function_subs_without_generics,none,
"unexpected 'for' to begin substitutions after non-generic function type", ())

// Opaque types
ERROR(opaque_mid_composition,none,
Expand Down
2 changes: 2 additions & 0 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -4019,6 +4019,8 @@ ERROR(sil_non_coro_yields,PointsToFirstBadToken,
ERROR(sil_function_repeat_convention,PointsToFirstBadToken,
"repeated %select{parameter|result|callee}0 convention attribute",
(unsigned))
ERROR(ast_subst_function_type,none,
"substitutions cannot be provided on a formal function type", ())
ERROR(sil_function_multiple_error_results,PointsToFirstBadToken,
"SIL function types cannot have multiple @error results", ())
ERROR(unsupported_sil_convention,none,
Expand Down
43 changes: 31 additions & 12 deletions include/swift/AST/TypeRepr.h
Original file line number Diff line number Diff line change
Expand Up @@ -472,12 +472,15 @@ inline IdentTypeRepr::ComponentRange IdentTypeRepr::getComponentRange() {
/// (x: Foo, y: Bar) -> Baz
/// \endcode
class FunctionTypeRepr : public TypeRepr {
// These fields are only used in SIL mode, which is the only time
// we can have polymorphic and substituted function values.
// The generic params / environment / substitutions fields are only used
// in SIL mode, which is the only time we can have polymorphic and
// substituted function values.
GenericParamList *GenericParams;
GenericEnvironment *GenericEnv;
bool GenericParamsAreImplied;
ArrayRef<TypeRepr *> GenericSubs;
ArrayRef<TypeRepr *> InvocationSubs;
GenericParamList *PatternGenericParams;
GenericEnvironment *PatternGenericEnv;
ArrayRef<TypeRepr *> PatternSubs;

TupleTypeRepr *ArgsTy;
TypeRepr *RetTy;
Expand All @@ -487,21 +490,37 @@ class FunctionTypeRepr : public TypeRepr {
public:
FunctionTypeRepr(GenericParamList *genericParams, TupleTypeRepr *argsTy,
SourceLoc throwsLoc, SourceLoc arrowLoc, TypeRepr *retTy,
bool GenericParamsAreImplied = false,
ArrayRef<TypeRepr *> GenericSubs = {})
GenericParamList *patternGenericParams = nullptr,
ArrayRef<TypeRepr *> patternSubs = {},
ArrayRef<TypeRepr *> invocationSubs = {})
: TypeRepr(TypeReprKind::Function),
GenericParams(genericParams),
GenericEnv(nullptr),
GenericParamsAreImplied(GenericParamsAreImplied),
GenericSubs(GenericSubs),
GenericParams(genericParams), GenericEnv(nullptr),
InvocationSubs(invocationSubs),
PatternGenericParams(patternGenericParams), PatternGenericEnv(nullptr),
PatternSubs(patternSubs),
ArgsTy(argsTy), RetTy(retTy),
ArrowLoc(arrowLoc), ThrowsLoc(throwsLoc) {
}

GenericParamList *getGenericParams() const { return GenericParams; }
GenericEnvironment *getGenericEnvironment() const { return GenericEnv; }
bool areGenericParamsImplied() const { return GenericParamsAreImplied; }
ArrayRef<TypeRepr*> getSubstitutions() const { return GenericSubs; }

GenericParamList *getPatternGenericParams() const {
return PatternGenericParams;
}
GenericEnvironment *getPatternGenericEnvironment() const {
return PatternGenericEnv;
}

ArrayRef<TypeRepr*> getPatternSubstitutions() const { return PatternSubs; }
ArrayRef<TypeRepr*> getInvocationSubstitutions() const {
return InvocationSubs;
}

void setPatternGenericEnvironment(GenericEnvironment *genericEnv) {
assert(PatternGenericEnv == nullptr);
PatternGenericEnv = genericEnv;
}

void setGenericEnvironment(GenericEnvironment *genericEnv) {
assert(GenericEnv == nullptr);
Expand Down
Loading