Skip to content

Commit d3794e6

Browse files
committed
Merge remote-tracking branch 'origin/master' into master-next
2 parents 9c0a348 + 75a5496 commit d3794e6

File tree

9 files changed

+149
-24
lines changed

9 files changed

+149
-24
lines changed

include/swift/AST/AnyRequest.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#ifndef SWIFT_AST_ANYREQUEST_H
1818
#define SWIFT_AST_ANYREQUEST_H
1919

20+
#include "swift/Basic/SourceLoc.h"
2021
#include "swift/Basic/TypeID.h"
2122
#include "llvm/ADT/DenseMapInfo.h"
2223
#include "llvm/ADT/Hashing.h"
@@ -85,6 +86,9 @@ class AnyRequest {
8586

8687
/// Note that this request is part of a cycle.
8788
virtual void noteCycleStep(DiagnosticEngine &diags) const = 0;
89+
90+
/// Retrieve the nearest source location to which this request applies.
91+
virtual SourceLoc getNearestLoc() const = 0;
8892
};
8993

9094
/// Holds a value that can be used as a request input/output.
@@ -125,6 +129,11 @@ class AnyRequest {
125129
virtual void noteCycleStep(DiagnosticEngine &diags) const override {
126130
request.noteCycleStep(diags);
127131
}
132+
133+
/// Retrieve the nearest source location to which this request applies.
134+
virtual SourceLoc getNearestLoc() const override {
135+
return request.getNearestLoc();
136+
}
128137
};
129138

130139
/// FIXME: Inefficient. Use the low bits.
@@ -202,6 +211,11 @@ class AnyRequest {
202211
stored->noteCycleStep(diags);
203212
}
204213

214+
/// Retrieve the nearest source location to which this request applies.
215+
SourceLoc getNearestLoc() const {
216+
return stored->getNearestLoc();
217+
}
218+
205219
/// Compare two instances for equality.
206220
friend bool operator==(const AnyRequest &lhs, const AnyRequest &rhs) {
207221
if (lhs.storageKind != rhs.storageKind) {

include/swift/AST/DiagnosticEngine.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,10 +540,12 @@ namespace swift {
540540
/// Class responsible for formatting diagnostics and presenting them
541541
/// to the user.
542542
class DiagnosticEngine {
543+
public:
543544
/// The source manager used to interpret source locations and
544545
/// display diagnostics.
545546
SourceManager &SourceMgr;
546547

548+
private:
547549
/// The diagnostic consumer(s) that will be responsible for actually
548550
/// emitting diagnostics.
549551
SmallVector<DiagnosticConsumer *, 2> Consumers;

include/swift/AST/TypeCheckRequests.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,28 @@ class LazyStoragePropertyRequest :
689689
bool isCached() const { return true; }
690690
};
691691

692+
/// Request to type check the body of the given function.
693+
///
694+
/// Produces true if an error occurred, false otherwise.
695+
/// FIXME: it would be far better to return the type-checked body.
696+
class TypeCheckFunctionBodyRequest :
697+
public SimpleRequest<TypeCheckFunctionBodyRequest,
698+
bool(AbstractFunctionDecl *),
699+
CacheKind::Cached> {
700+
public:
701+
using SimpleRequest::SimpleRequest;
702+
703+
private:
704+
friend SimpleRequest;
705+
706+
// Evaluation.
707+
llvm::Expected<bool>
708+
evaluate(Evaluator &evaluator, AbstractFunctionDecl *func) const;
709+
710+
public:
711+
bool isCached() const { return true; }
712+
};
713+
692714
// Allow AnyValue to compare two Type values, even though Type doesn't
693715
// support ==.
694716
template<>

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,5 @@ SWIFT_TYPEID(SelfAccessKindRequest)
3939
SWIFT_TYPEID(IsGetterMutatingRequest)
4040
SWIFT_TYPEID(IsSetterMutatingRequest)
4141
SWIFT_TYPEID(OpaqueReadOwnershipRequest)
42-
SWIFT_TYPEID(LazyStoragePropertyRequest)
42+
SWIFT_TYPEID(LazyStoragePropertyRequest)
43+
SWIFT_TYPEID(TypeCheckFunctionBodyRequest)

lib/AST/Evaluator.cpp

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
//
1616
//===----------------------------------------------------------------------===//
1717
#include "swift/AST/Evaluator.h"
18+
#include "swift/AST/DiagnosticEngine.h"
1819
#include "swift/Basic/Range.h"
20+
#include "swift/Basic/SourceManager.h"
1921
#include "llvm/ADT/StringExtras.h"
2022
#include "llvm/Support/Debug.h"
2123
#include "llvm/Support/FileSystem.h"
@@ -248,17 +250,47 @@ void Evaluator::printDependenciesGraphviz(llvm::raw_ostream &out) const {
248250
out << "digraph Dependencies {\n";
249251

250252
// Emit the edges.
253+
llvm::DenseMap<AnyRequest, unsigned> inDegree;
251254
for (const auto &source : allRequests) {
252255
auto known = dependencies.find(source);
253256
assert(known != dependencies.end());
254257
for (const auto &target : known->second) {
255258
out << " " << getNodeName(source) << " -> " << getNodeName(target)
256259
<< ";\n";
260+
++inDegree[target];
257261
}
258262
}
259263

260264
out << "\n";
261265

266+
static const char *colorNames[] = {
267+
"aquamarine",
268+
"blueviolet",
269+
"brown",
270+
"burlywood",
271+
"cadetblue",
272+
"chartreuse",
273+
"chocolate",
274+
"coral",
275+
"cornflowerblue",
276+
"crimson"
277+
};
278+
const unsigned numColorNames = sizeof(colorNames) / sizeof(const char *);
279+
280+
llvm::DenseMap<unsigned, unsigned> knownBuffers;
281+
auto getColor = [&](const AnyRequest &request) -> Optional<const char *> {
282+
SourceLoc loc = request.getNearestLoc();
283+
if (loc.isInvalid())
284+
return None;
285+
286+
unsigned bufferID = diags.SourceMgr.findBufferContainingLoc(loc);
287+
auto knownId = knownBuffers.find(bufferID);
288+
if (knownId == knownBuffers.end()) {
289+
knownId = knownBuffers.insert({bufferID, knownBuffers.size()}).first;
290+
}
291+
return colorNames[knownId->second % numColorNames];
292+
};
293+
262294
// Emit the nodes.
263295
for (unsigned i : indices(allRequests)) {
264296
const auto &request = allRequests[i];
@@ -271,7 +303,48 @@ void Evaluator::printDependenciesGraphviz(llvm::raw_ostream &out) const {
271303
out << " -> ";
272304
printEscapedString(cachedValue->second.getAsString(), out);
273305
}
274-
out << "\"];\n";
306+
out << "\"";
307+
308+
if (auto color = getColor(request)) {
309+
out << ", fillcolor=\"" << *color << "\"";
310+
}
311+
312+
out << "];\n";
313+
}
314+
315+
// Emit "fake" nodes for each of the source buffers we encountered, so
316+
// we know which file we're working from.
317+
// FIXME: This approximates a "top level" request for, e.g., type checking
318+
// an entire source file.
319+
std::vector<unsigned> sourceBufferIDs;
320+
for (const auto &element : knownBuffers) {
321+
sourceBufferIDs.push_back(element.first);
322+
}
323+
std::sort(sourceBufferIDs.begin(), sourceBufferIDs.end());
324+
for (unsigned bufferID : sourceBufferIDs) {
325+
out << " buffer_" << bufferID << "[label=\"";
326+
printEscapedString(diags.SourceMgr.getIdentifierForBuffer(bufferID), out);
327+
out << "\"";
328+
329+
out << ", shape=\"box\"";
330+
out << ", fillcolor=\""
331+
<< colorNames[knownBuffers[bufferID] % numColorNames] << "\"";
332+
out << "];\n";
333+
}
334+
335+
// Emit "false" dependencies from source buffer IDs to any requests that (1)
336+
// have no other incomining edges and (2) can be associated with a source
337+
// buffer.
338+
for (const auto &request : allRequests) {
339+
if (inDegree[request] > 0)
340+
continue;
341+
342+
SourceLoc loc = request.getNearestLoc();
343+
if (loc.isInvalid())
344+
continue;
345+
346+
unsigned bufferID = diags.SourceMgr.findBufferContainingLoc(loc);
347+
out << " buffer_" << bufferID << " -> " << getNodeName(request) << ";\n";
275348
}
276349

277350
// Done!

lib/Sema/TypeCheckStmt.cpp

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "swift/AST/NameLookup.h"
3030
#include "swift/AST/ParameterList.h"
3131
#include "swift/AST/PrettyStackTrace.h"
32+
#include "swift/AST/TypeCheckRequests.h"
3233
#include "swift/Basic/Range.h"
3334
#include "swift/Basic/STLExtras.h"
3435
#include "swift/Basic/SourceManager.h"
@@ -1920,35 +1921,47 @@ bool TypeChecker::typeCheckAbstractFunctionBodyUntil(AbstractFunctionDecl *AFD,
19201921
}
19211922

19221923
bool TypeChecker::typeCheckAbstractFunctionBody(AbstractFunctionDecl *AFD) {
1923-
// HACK: don't type-check the same function body twice. This is
1924-
// supposed to be handled by just not enqueuing things twice,
1925-
// but that gets tricky with synthesized function bodies.
1926-
validateDecl(AFD);
1927-
(void) AFD->getBody();
1924+
return evaluateOrDefault(Context.evaluator,
1925+
TypeCheckFunctionBodyRequest{AFD},
1926+
true);
1927+
}
19281928

1929-
if (AFD->isBodyTypeChecked())
1929+
llvm::Expected<bool>
1930+
TypeCheckFunctionBodyRequest::evaluate(Evaluator &evaluator,
1931+
AbstractFunctionDecl *func) const {
1932+
ASTContext &ctx = func->getASTContext();
1933+
if (!func->hasInterfaceType()) {
1934+
TypeChecker &tc = *static_cast<TypeChecker *>(ctx.getLazyResolver());
1935+
tc.validateDecl(func);
1936+
}
1937+
1938+
// HACK: don't type-check the same function body twice. This will eventually
1939+
// be handled by the request-evaluator's caching mechanism.
1940+
(void)func->getBody();
1941+
if (func->isBodyTypeChecked())
19301942
return false;
19311943

1932-
FrontendStatsTracer StatsTracer(Context.Stats, "typecheck-fn", AFD);
1933-
PrettyStackTraceDecl StackEntry("type-checking", AFD);
1944+
FrontendStatsTracer StatsTracer(ctx.Stats, "typecheck-fn", func);
1945+
PrettyStackTraceDecl StackEntry("type-checking", func);
19341946

1935-
if (Context.Stats)
1936-
Context.Stats->getFrontendCounters().NumFunctionsTypechecked++;
1947+
if (ctx.Stats)
1948+
ctx.Stats->getFrontendCounters().NumFunctionsTypechecked++;
19371949

19381950
Optional<FunctionBodyTimer> timer;
1939-
if (DebugTimeFunctionBodies || WarnLongFunctionBodies)
1940-
timer.emplace(AFD, DebugTimeFunctionBodies, WarnLongFunctionBodies);
1951+
TypeChecker &tc = *static_cast<TypeChecker *>(ctx.getLazyResolver());
1952+
if (tc.DebugTimeFunctionBodies || tc.WarnLongFunctionBodies)
1953+
timer.emplace(func, tc.DebugTimeFunctionBodies, tc.WarnLongFunctionBodies);
19411954

1942-
requestRequiredNominalTypeLayoutForParameters(AFD->getParameters());
1955+
tc.requestRequiredNominalTypeLayoutForParameters(func->getParameters());
19431956

1944-
bool error = typeCheckAbstractFunctionBodyUntil(AFD, SourceLoc());
1945-
AFD->setBodyTypeCheckedIfPresent();
1957+
bool error = tc.typeCheckAbstractFunctionBodyUntil(func, SourceLoc());
1958+
func->setBodyTypeCheckedIfPresent();
19461959

19471960
if (error)
19481961
return true;
19491962

1950-
if (AFD->getBody())
1951-
performAbstractFuncDeclDiagnostics(*this, AFD);
1963+
if (func->getBody())
1964+
performAbstractFuncDeclDiagnostics(tc, func);
19521965

19531966
return false;
19541967
}

lib/Sema/TypeChecker.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -631,7 +631,8 @@ class TypeChecker final : public LazyResolver {
631631
TypeChecker(ASTContext &Ctx);
632632
friend class ASTContext;
633633
friend class constraints::ConstraintSystem;
634-
634+
friend class TypeCheckFunctionBodyRequest;
635+
635636
public:
636637
/// Create a new type checker instance for the given ASTContext, if it
637638
/// doesn't already have one.

test/SourceKit/CursorInfo/cursor_info_property_wrappers.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
@propertyWrapper
22
struct Wrapper<T> {
33
var wrappedValue: T
4-
init(initialValue: T) {
4+
init(wrappedValue initialValue: T) {
55
wrappedValue = initialValue
66
}
77
var projectedValue: Projection<T> {
@@ -26,7 +26,7 @@ struct Projection<T> {
2626

2727
// Split between custom attr and initializer
2828
extension Wrapper {
29-
init(initialValue: T, fieldNumber: Int, special: Bool = false) {
29+
init(wrappedValue initialValue: T, fieldNumber: Int, special: Bool = false) {
3030
wrappedValue = initialValue
3131
}
3232
}

unittests/AST/ArithmeticEvaluator.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,7 @@ struct EvaluationRule
117117
}
118118
}
119119

120-
void diagnoseCycle(DiagnosticEngine &diags) const { }
121-
void noteCycleStep(DiagnosticEngine &diags) const { }
120+
SourceLoc getNearestLoc() const { return SourceLoc(); }
122121
};
123122

124123
struct InternallyCachedEvaluationRule :

0 commit comments

Comments
 (0)