Skip to content

Commit 77ece20

Browse files
committed
[Concurrency] Move concurrency-specific code into its own file.
1 parent dabccf6 commit 77ece20

File tree

3 files changed

+161
-140
lines changed

3 files changed

+161
-140
lines changed

lib/Sema/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ add_swift_host_library(swiftSema STATIC
4141
TypeCheckCaptures.cpp
4242
TypeCheckCircularity.cpp
4343
TypeCheckCodeCompletion.cpp
44+
TypeCheckConcurrency.cpp
4445
TypeCheckConstraints.cpp
4546
TypeCheckDecl.cpp
4647
TypeCheckDeclObjC.cpp

lib/Sema/TypeCheckAttr.cpp

Lines changed: 0 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
#include "swift/AST/NameLookupRequests.h"
3030
#include "swift/AST/ParameterList.h"
3131
#include "swift/AST/PropertyWrappers.h"
32-
#include "swift/AST/ProtocolConformance.h"
3332
#include "swift/AST/SourceFile.h"
3433
#include "swift/AST/StorageImpl.h"
3534
#include "swift/AST/TypeCheckRequests.h"
@@ -42,66 +41,6 @@
4241

4342
using namespace swift;
4443

45-
/// Check whether the @asyncHandler attribute can be applied to the given
46-
/// function declaration.
47-
///
48-
/// \param diagnose Whether to emit a diagnostic when a problem is encountered.
49-
///
50-
/// \returns \c true if there was a problem with adding the attribute, \c false
51-
/// otherwise.
52-
static bool checkAsyncHandler(FuncDecl *func, bool diagnose) {
53-
if (!func->getResultInterfaceType()->isVoid()) {
54-
if (diagnose) {
55-
func->diagnose(diag::asynchandler_returns_value)
56-
.highlight(func->getBodyResultTypeLoc().getSourceRange());
57-
}
58-
59-
return true;
60-
}
61-
62-
if (func->hasThrows()) {
63-
if (diagnose) {
64-
func->diagnose(diag::asynchandler_throws)
65-
.fixItRemove(func->getThrowsLoc());
66-
}
67-
68-
return true;
69-
}
70-
71-
if (func->hasAsync()) {
72-
if (diagnose) {
73-
func->diagnose(diag::asynchandler_async)
74-
.fixItRemove(func->getAsyncLoc());
75-
}
76-
77-
return true;
78-
}
79-
80-
for (auto param : *func->getParameters()) {
81-
if (param->isInOut()) {
82-
if (diagnose) {
83-
param->diagnose(diag::asynchandler_inout_parameter)
84-
.fixItRemove(param->getSpecifierLoc());
85-
}
86-
87-
return true;
88-
}
89-
}
90-
91-
if (func->isMutating()) {
92-
if (diagnose) {
93-
auto diag = func->diagnose(diag::asynchandler_mutating);
94-
if (auto mutatingAttr = func->getAttrs().getAttribute<MutatingAttr>()) {
95-
diag.fixItRemove(mutatingAttr->getRange());
96-
}
97-
}
98-
99-
return true;
100-
}
101-
102-
return false;
103-
}
104-
10544
namespace {
10645
/// This emits a diagnostic with a fixit to remove the attribute.
10746
template<typename ...ArgTypes>
@@ -5225,82 +5164,3 @@ void AttributeChecker::visitTransposeAttr(TransposeAttr *attr) {
52255164
// Set the resolved linearity parameter indices in the attribute.
52265165
attr->setParameterIndices(linearParamIndices);
52275166
}
5228-
5229-
void swift::addAsyncNotes(FuncDecl *func) {
5230-
func->diagnose(diag::note_add_async_to_function, func->getName());
5231-
5232-
if (!checkAsyncHandler(func, /*diagnose=*/false)) {
5233-
func->diagnose(
5234-
diag::note_add_asynchandler_to_function, func->getName())
5235-
.fixItInsert(func->getAttributeInsertionLoc(false), "@asyncHandler ");
5236-
}
5237-
}
5238-
5239-
bool IsAsyncHandlerRequest::evaluate(
5240-
Evaluator &evaluator, FuncDecl *func) const {
5241-
// Check whether the attribute was explicitly specified.
5242-
if (auto attr = func->getAttrs().getAttribute<AsyncHandlerAttr>()) {
5243-
// Check for well-formedness.
5244-
if (checkAsyncHandler(func, /*diagnose=*/true)) {
5245-
attr->setInvalid();
5246-
return false;
5247-
}
5248-
5249-
return true;
5250-
}
5251-
5252-
// Are we in a context where inference is possible?
5253-
auto dc = func->getDeclContext();
5254-
if (!dc->isTypeContext() || !dc->getParentSourceFile() ||
5255-
isa<ProtocolDecl>(dc) || !func->hasBody())
5256-
return false;
5257-
5258-
// Is it possible to infer @asyncHandler for this function at all?
5259-
if (checkAsyncHandler(func, /*diagnose=*/false))
5260-
return false;
5261-
5262-
// Add an implicit @asyncHandler attribute and return true. We're done.
5263-
auto addImplicitAsyncHandlerAttr = [&] {
5264-
func->getAttrs().add(new (func->getASTContext()) AsyncHandlerAttr(true));
5265-
return true;
5266-
};
5267-
5268-
// Check whether any of the conformances in the context of the function
5269-
// implies @asyncHandler.
5270-
{
5271-
auto idc = cast<IterableDeclContext>(dc->getAsDecl());
5272-
auto conformances = evaluateOrDefault(
5273-
dc->getASTContext().evaluator,
5274-
LookupAllConformancesInContextRequest{idc}, { });
5275-
5276-
for (auto conformance : conformances) {
5277-
auto protocol = conformance->getProtocol();
5278-
for (auto found : protocol->lookupDirect(func->getName())) {
5279-
if (!isa<ProtocolDecl>(found->getDeclContext()))
5280-
continue;
5281-
5282-
auto requirement = dyn_cast<FuncDecl>(found);
5283-
if (!requirement)
5284-
continue;
5285-
5286-
if (!requirement->isAsyncHandler())
5287-
continue;
5288-
5289-
auto witness = conformance->getWitnessDecl(requirement);
5290-
if (witness != func)
5291-
continue;
5292-
5293-
return addImplicitAsyncHandlerAttr();
5294-
}
5295-
}
5296-
}
5297-
5298-
// Look through dynamic replacements.
5299-
if (auto replaced = func->getDynamicallyReplacedDecl()) {
5300-
if (auto replacedFunc = dyn_cast<FuncDecl>(replaced))
5301-
if (replacedFunc->isAsyncHandler())
5302-
return addImplicitAsyncHandlerAttr();
5303-
}
5304-
5305-
return false;
5306-
}

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
//===--- TypeCheckConcurrency.cpp - Concurrency ---------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file implements type checking support for Swift's concurrency model.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
#include "TypeChecker.h"
17+
#include "swift/AST/ParameterList.h"
18+
#include "swift/AST/ProtocolConformance.h"
19+
#include "swift/AST/TypeCheckRequests.h"
20+
21+
using namespace swift;
22+
23+
/// Check whether the @asyncHandler attribute can be applied to the given
24+
/// function declaration.
25+
///
26+
/// \param diagnose Whether to emit a diagnostic when a problem is encountered.
27+
///
28+
/// \returns \c true if there was a problem with adding the attribute, \c false
29+
/// otherwise.
30+
static bool checkAsyncHandler(FuncDecl *func, bool diagnose) {
31+
if (!func->getResultInterfaceType()->isVoid()) {
32+
if (diagnose) {
33+
func->diagnose(diag::asynchandler_returns_value)
34+
.highlight(func->getBodyResultTypeLoc().getSourceRange());
35+
}
36+
37+
return true;
38+
}
39+
40+
if (func->hasThrows()) {
41+
if (diagnose) {
42+
func->diagnose(diag::asynchandler_throws)
43+
.fixItRemove(func->getThrowsLoc());
44+
}
45+
46+
return true;
47+
}
48+
49+
if (func->hasAsync()) {
50+
if (diagnose) {
51+
func->diagnose(diag::asynchandler_async)
52+
.fixItRemove(func->getAsyncLoc());
53+
}
54+
55+
return true;
56+
}
57+
58+
for (auto param : *func->getParameters()) {
59+
if (param->isInOut()) {
60+
if (diagnose) {
61+
param->diagnose(diag::asynchandler_inout_parameter)
62+
.fixItRemove(param->getSpecifierLoc());
63+
}
64+
65+
return true;
66+
}
67+
}
68+
69+
if (func->isMutating()) {
70+
if (diagnose) {
71+
auto diag = func->diagnose(diag::asynchandler_mutating);
72+
if (auto mutatingAttr = func->getAttrs().getAttribute<MutatingAttr>()) {
73+
diag.fixItRemove(mutatingAttr->getRange());
74+
}
75+
}
76+
77+
return true;
78+
}
79+
80+
return false;
81+
}
82+
83+
void swift::addAsyncNotes(FuncDecl *func) {
84+
func->diagnose(diag::note_add_async_to_function, func->getName());
85+
86+
if (!checkAsyncHandler(func, /*diagnose=*/false)) {
87+
func->diagnose(
88+
diag::note_add_asynchandler_to_function, func->getName())
89+
.fixItInsert(func->getAttributeInsertionLoc(false), "@asyncHandler ");
90+
}
91+
}
92+
93+
bool IsAsyncHandlerRequest::evaluate(
94+
Evaluator &evaluator, FuncDecl *func) const {
95+
// Check whether the attribute was explicitly specified.
96+
if (auto attr = func->getAttrs().getAttribute<AsyncHandlerAttr>()) {
97+
// Check for well-formedness.
98+
if (checkAsyncHandler(func, /*diagnose=*/true)) {
99+
attr->setInvalid();
100+
return false;
101+
}
102+
103+
return true;
104+
}
105+
106+
// Are we in a context where inference is possible?
107+
auto dc = func->getDeclContext();
108+
if (!dc->isTypeContext() || !dc->getParentSourceFile() ||
109+
isa<ProtocolDecl>(dc) || !func->hasBody())
110+
return false;
111+
112+
// Is it possible to infer @asyncHandler for this function at all?
113+
if (checkAsyncHandler(func, /*diagnose=*/false))
114+
return false;
115+
116+
// Add an implicit @asyncHandler attribute and return true. We're done.
117+
auto addImplicitAsyncHandlerAttr = [&] {
118+
func->getAttrs().add(new (func->getASTContext()) AsyncHandlerAttr(true));
119+
return true;
120+
};
121+
122+
// Check whether any of the conformances in the context of the function
123+
// implies @asyncHandler.
124+
{
125+
auto idc = cast<IterableDeclContext>(dc->getAsDecl());
126+
auto conformances = evaluateOrDefault(
127+
dc->getASTContext().evaluator,
128+
LookupAllConformancesInContextRequest{idc}, { });
129+
130+
for (auto conformance : conformances) {
131+
auto protocol = conformance->getProtocol();
132+
for (auto found : protocol->lookupDirect(func->getName())) {
133+
if (!isa<ProtocolDecl>(found->getDeclContext()))
134+
continue;
135+
136+
auto requirement = dyn_cast<FuncDecl>(found);
137+
if (!requirement)
138+
continue;
139+
140+
if (!requirement->isAsyncHandler())
141+
continue;
142+
143+
auto witness = conformance->getWitnessDecl(requirement);
144+
if (witness != func)
145+
continue;
146+
147+
return addImplicitAsyncHandlerAttr();
148+
}
149+
}
150+
}
151+
152+
// Look through dynamic replacements.
153+
if (auto replaced = func->getDynamicallyReplacedDecl()) {
154+
if (auto replacedFunc = dyn_cast<FuncDecl>(replaced))
155+
if (replacedFunc->isAsyncHandler())
156+
return addImplicitAsyncHandlerAttr();
157+
}
158+
159+
return false;
160+
}

0 commit comments

Comments
 (0)