Skip to content

Async await prototype #11501

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 8 commits into from
Closed
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
3 changes: 2 additions & 1 deletion docs/ABI/Mangling.rst
Original file line number Diff line number Diff line change
Expand Up @@ -316,12 +316,13 @@ Types
FUNCTION-KIND ::= 'B' // objc block function type
FUNCTION-KIND ::= 'C' // C function pointer type

function-signature ::= params-type params-type throws? // results and parameters
function-signature ::= params-type params-type throws? async? // results and parameters

params-type := type // tuple in case of multiple parameters
params-type := empty-list // shortcut for no parameters

throws ::= 'K' // 'throws' annotation on function types
async ::= 'Y' // 'async' annotation on function types

type-list ::= list-type '_' list-type* // list of types
type-list ::= empty-list
Expand Down
10 changes: 10 additions & 0 deletions include/swift/ABI/MetadataValues.h
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,7 @@ class TargetFunctionTypeFlags {
ConventionMask = 0x0F000000U,
ConventionShift = 24U,
ThrowsMask = 0x10000000U,
AsyncMask = 0x20000000U,
};
int_type Data;

Expand All @@ -504,6 +505,12 @@ class TargetFunctionTypeFlags {
(throws ? ThrowsMask : 0));
}

constexpr TargetFunctionTypeFlags<int_type>
withAsync(bool async) const {
return TargetFunctionTypeFlags<int_type>((Data & AsyncMask) |
(async ? AsyncMask : 0));
}

unsigned getNumArguments() const {
return Data & NumArgumentsMask;
}
Expand All @@ -515,6 +522,9 @@ class TargetFunctionTypeFlags {
bool throws() const {
return bool(Data & ThrowsMask);
}
bool isAsync() const {
return bool(Data & AsyncMask);
}

int_type getIntValue() const {
return Data;
Expand Down
31 changes: 23 additions & 8 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ bool conflicting(const OverloadSignature& sig1, const OverloadSignature& sig2);
class alignas(1 << DeclAlignInBits) Decl {
class DeclBitfields {
friend class Decl;
unsigned Kind : 6;
unsigned Kind : 5;

/// \brief Whether this declaration is invalid.
unsigned Invalid : 1;
Expand Down Expand Up @@ -262,7 +262,7 @@ class alignas(1 << DeclAlignInBits) Decl {
/// DeclContext of an active #if config clause.
unsigned EscapedFromIfConfig : 1;
};
enum { NumDeclBits = 13 };
enum { NumDeclBits = 12 };
static_assert(NumDeclBits <= 32, "fits in an unsigned");

class PatternBindingDeclBitfields {
Expand Down Expand Up @@ -334,7 +334,6 @@ class alignas(1 << DeclAlignInBits) Decl {
/// \brief Whether this is a property used in expressions in the debugger.
/// It is up to the debugger to instruct SIL how to access this variable.
unsigned IsDebuggerVar : 1;

};
enum { NumVarDeclBits = NumAbstractStorageDeclBits + 6 };
static_assert(NumVarDeclBits <= 32, "fits in an unsigned");
Expand Down Expand Up @@ -369,13 +368,16 @@ class alignas(1 << DeclAlignInBits) Decl {
/// Whether the function body throws.
unsigned Throws : 1;

/// Whether the function body is async.
unsigned IsAsync : 1;

/// Whether this function requires a new vtable entry.
unsigned NeedsNewVTableEntry : 1;

/// Whether NeedsNewVTableEntry is valid.
unsigned HasComputedNeedsNewVTableEntry : 1;
};
enum { NumAbstractFunctionDeclBits = NumValueDeclBits + 13 };
enum { NumAbstractFunctionDeclBits = NumValueDeclBits + 14 };
static_assert(NumAbstractFunctionDeclBits <= 32, "fits in an unsigned");

class FuncDeclBitfields {
Expand Down Expand Up @@ -659,6 +661,7 @@ class alignas(1 << DeclAlignInBits) Decl {
Decl(DeclKind kind, llvm::PointerUnion<DeclContext *, ASTContext *> context)
: OpaqueBits(0), Context(context) {
DeclBits.Kind = unsigned(kind);
assert(DeclBits.Kind == unsigned(kind) && "Too few bits for kind");
DeclBits.Invalid = false;
DeclBits.Implicit = false;
DeclBits.FromClang = false;
Expand Down Expand Up @@ -4838,23 +4841,25 @@ class AbstractFunctionDecl : public ValueDecl, public GenericContext {

CaptureInfo Captures;

/// Location of the 'throws' token.
SourceLoc ThrowsLoc;
/// Location of the 'throws' and 'async' tokens (if present).
SourceLoc ThrowsLoc, AsyncLoc;

ImportAsMemberStatus IAMStatus;

AbstractFunctionDecl(DeclKind Kind, DeclContext *Parent, DeclName Name,
SourceLoc NameLoc, bool Throws, SourceLoc ThrowsLoc,
bool isAsync, SourceLoc AsyncLoc,
unsigned NumParameterLists,
GenericParamList *GenericParams)
: ValueDecl(Kind, Parent, Name, NameLoc),
GenericContext(DeclContextKind::AbstractFunctionDecl, Parent),
Body(nullptr), ThrowsLoc(ThrowsLoc) {
Body(nullptr), ThrowsLoc(ThrowsLoc), AsyncLoc(AsyncLoc) {
setBodyKind(BodyKind::None);
setGenericParams(GenericParams);
AbstractFunctionDeclBits.NumParameterLists = NumParameterLists;
AbstractFunctionDeclBits.Overridden = false;
AbstractFunctionDeclBits.Throws = Throws;
AbstractFunctionDeclBits.IsAsync = isAsync;
AbstractFunctionDeclBits.NeedsNewVTableEntry = false;
AbstractFunctionDeclBits.HasComputedNeedsNewVTableEntry = false;

Expand Down Expand Up @@ -4890,10 +4895,15 @@ class AbstractFunctionDecl : public ValueDecl, public GenericContext {
public:
/// Retrieve the location of the 'throws' keyword, if present.
SourceLoc getThrowsLoc() const { return ThrowsLoc; }
/// Retrieve the location of the 'async' keyword, if present.
SourceLoc getAsyncLoc() const { return AsyncLoc; }

/// Returns true if the function body throws.
bool hasThrows() const { return AbstractFunctionDeclBits.Throws; }

/// Returns true if the function body is async.
bool isAsync() const { return AbstractFunctionDeclBits.IsAsync; }

// FIXME: Hack that provides names with keyword arguments for accessors.
DeclName getEffectiveFullName() const;

Expand Down Expand Up @@ -5144,12 +5154,13 @@ class FuncDecl final : public AbstractFunctionDecl,
SourceLoc FuncLoc,
DeclName Name, SourceLoc NameLoc,
bool Throws, SourceLoc ThrowsLoc,
bool IsAsync, SourceLoc AsyncLoc,
SourceLoc AccessorKeywordLoc,
unsigned NumParameterLists,
GenericParamList *GenericParams, DeclContext *Parent)
: AbstractFunctionDecl(DeclKind::Func, Parent,
Name, NameLoc,
Throws, ThrowsLoc,
Throws, ThrowsLoc, IsAsync, AsyncLoc,
NumParameterLists, GenericParams),
StaticLoc(StaticLoc), FuncLoc(FuncLoc),
AccessorKeywordLoc(AccessorKeywordLoc),
Expand All @@ -5170,6 +5181,7 @@ class FuncDecl final : public AbstractFunctionDecl,
SourceLoc FuncLoc,
DeclName Name, SourceLoc NameLoc,
bool Throws, SourceLoc ThrowsLoc,
bool IsAsync, SourceLoc AsyncLoc,
SourceLoc AccessorKeywordLoc,
GenericParamList *GenericParams,
unsigned NumParameterLists,
Expand All @@ -5183,6 +5195,7 @@ class FuncDecl final : public AbstractFunctionDecl,
SourceLoc FuncLoc,
DeclName Name, SourceLoc NameLoc,
bool Throws, SourceLoc ThrowsLoc,
bool IsAsync, SourceLoc AsyncLoc,
SourceLoc AccessorKeywordLoc,
GenericParamList *GenericParams,
unsigned NumParameterLists,
Expand All @@ -5193,6 +5206,7 @@ class FuncDecl final : public AbstractFunctionDecl,
SourceLoc FuncLoc,
DeclName Name, SourceLoc NameLoc,
bool Throws, SourceLoc ThrowsLoc,
bool IsAsync, SourceLoc AsyncLoc,
SourceLoc AccessorKeywordLoc,
GenericParamList *GenericParams,
ArrayRef<ParameterList *> ParameterLists,
Expand Down Expand Up @@ -5649,6 +5663,7 @@ class ConstructorDecl : public AbstractFunctionDecl {
ConstructorDecl(DeclName Name, SourceLoc ConstructorLoc,
OptionalTypeKind Failability, SourceLoc FailabilityLoc,
bool Throws, SourceLoc ThrowsLoc,
bool IsAsync, SourceLoc AsyncLoc,
ParamDecl *SelfParam, ParameterList *BodyParams,
GenericParamList *GenericParams,
DeclContext *Parent);
Expand Down
10 changes: 8 additions & 2 deletions include/swift/AST/DiagnosticsParse.def
Original file line number Diff line number Diff line change
Expand Up @@ -697,8 +697,10 @@ ERROR(generic_non_function,PointsToFirstBadToken,
ERROR(rethrowing_function_type,none,
"only function declarations may be marked 'rethrows'; "
"did you mean 'throws'?", ())
ERROR(throws_in_wrong_position,none,
"'throws' may only occur before '->'", ())
ERROR(func_type_specifier_redundant,none,
"redundant function type specifier", ())
ERROR(throwsasync_in_wrong_position,none,
"'%select{async|throws}0' may only occur before '->'", (bool))
ERROR(rethrows_in_wrong_position,none,
"'rethrows' may only occur before '->'", ())
ERROR(throw_in_function_type,none,
Expand Down Expand Up @@ -1181,6 +1183,10 @@ ERROR(expected_colon_after_if_question,none,
"expected ':' after '? ...' in ternary expression", ())
ERROR(expected_expr_after_if_colon,none,
"expected expression after '? ... :' in ternary expression", ())
ERROR(expected_expr_after_try, none,
"expected expression after 'try'", ())
ERROR(expected_expr_after_await, none,
"expected expression after 'await'", ())

// Cast expressions
ERROR(expected_type_after_is,none,
Expand Down
27 changes: 26 additions & 1 deletion include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,12 @@ ERROR(cannot_convert_assign_nil,none,
ERROR(throws_functiontype_mismatch,none,
"invalid conversion from throwing function of type %0 to "
"non-throwing function type %1", (Type, Type))
ERROR(async_functiontype_removal,none,
"invalid removal of 'async' when converting function of type %0 to %1",
(Type, Type))
ERROR(async_functiontype_addition,none,
"invalid addition of 'async' when converting function of type %0 to %1",
(Type, Type))
ERROR(noescape_functiontype_mismatch,none,
"invalid conversion from non-escaping function of type %0 to "
"potentially escaping function type %1", (Type, Type))
Expand Down Expand Up @@ -1580,6 +1586,8 @@ NOTE(protocol_witness_rethrows_conflict,none,
"candidate is not 'rethrows', but protocol requires it", ())
NOTE(protocol_witness_throws_conflict,none,
"candidate throws, but protocol does not allow it", ())
NOTE(protocol_witness_async_conflict,none,
"candidate and protocol requirement are not both 'async'", ())
NOTE(protocol_witness_not_objc,none,
"candidate is explicitly '@nonobjc'", ())

Expand Down Expand Up @@ -1871,6 +1879,9 @@ ERROR(override_class_declaration_in_extension,none,
WARNING(override_class_declaration_in_extension_warning,none,
"cannot override a non-dynamic class declaration from an extension",
())
ERROR(override_async,none,
"cannot override %1async %select{method|initializer}0 with "
"%2async %select{method|initializer}0", (bool, StringRef, StringRef))
ERROR(override_throws,none,
"cannot override non-throwing %select{method|initializer}0 with "
"throwing %select{method|initializer}0", (bool))
Expand Down Expand Up @@ -2412,7 +2423,7 @@ ERROR(missing_builtin_precedence_group,none,
(Identifier))

// If you change this, also change enum TryKindForDiagnostics.
#define TRY_KIND_SELECT(SUB) "%select{try|try!|try?}" #SUB
#define TRY_KIND_SELECT(SUB) "%select{try|try!|try?|await}" #SUB

ERROR(try_rhs,none,
"'" TRY_KIND_SELECT(0) "' cannot appear to the right of a "
Expand Down Expand Up @@ -3021,6 +3032,14 @@ NOTE(note_error_to_optional,none,
"did you mean to handle error as optional value?", ())
NOTE(note_disable_error_propagation,none,
"did you mean to disable error propagation?", ())
ERROR(async_call_without_await,none,
"call is 'async' but is not marked with 'await'", ())
WARNING(no_async_in_await,none,
"no calls to 'async' functions occur within 'await' expression", ())
ERROR(async_call_in_illegal_context,none,
"async expression is not allowed in %0",
(StringRef))


WARNING(no_throw_in_try,none,
"no calls to throwing functions occur within 'try' expression", ())
Expand Down Expand Up @@ -3298,6 +3317,9 @@ NOTE(not_objc_function_type_param,none,
"parameters and returns can be", ())
NOTE(not_objc_function_type_throwing,none,
"throwing function types cannot be represented in Objective-C", ())
NOTE(not_objc_function_type_async,none,
"async function types cannot be represented in Objective-C", ())

NOTE(objc_inferring_on_objc_protocol_member,none,
"inferring '@objc' because the declaration is a member of "
"an '@objc' protocol", ())
Expand Down Expand Up @@ -3332,6 +3354,9 @@ ERROR(objc_invalid_on_func_single_param_type,none,
ERROR(objc_invalid_on_func_result_type,none,
"method cannot be %" OBJC_ATTR_SELECT "0 because its result type "
"cannot be represented in Objective-C", (unsigned))
ERROR(objc_invalid_on_async_func,none,
"method cannot be %" OBJC_ATTR_SELECT "0 because it is async",
(unsigned))
ERROR(objc_invalid_on_foreign_class,none,
"method cannot be %" OBJC_ATTR_SELECT "0 because Core Foundation "
"types are not classes in Objective-C", (unsigned))
Expand Down
Loading