Skip to content

Commit f6ff6f7

Browse files
committed
---
yaml --- r: 323543 b: refs/heads/tensorflow-next c: 7a97cd8 h: refs/heads/master i: 323541: 492bff3 323539: 7fb4406 323535: abb8172
1 parent 2846d6a commit f6ff6f7

File tree

14 files changed

+182
-572
lines changed

14 files changed

+182
-572
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1461,4 +1461,4 @@ refs/heads/master-rebranch: 86e95c23aa0d37f24ec138b7853146c1cead2e40
14611461
refs/heads/rdar-53901732: 9bd06af3284e18a109cdbf9aa59d833b24eeca7b
14621462
refs/heads/revert-26776-subst-always-returns-a-type: 1b8e18fdd391903a348970a4c848995d4cdd789c
14631463
refs/heads/tensorflow-merge: 8b854f62f80d4476cb383d43c4aac2001dde3cec
1464-
refs/heads/tensorflow-next: ab7dca2933ed265fff7347be68e9b9fdeade85a7
1464+
refs/heads/tensorflow-next: 7a97cd8314c1b6d5de114b5c2a75c91c8274a9ad

branches/tensorflow-next/docs/RequestEvaluator.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,7 @@ The request-evaluator is relatively new to the Swift compiler, having been intro
5858

5959
* The evaluator uses a `DenseMap<AnyRequest, AnyValue>` as its cache: we can almost certainly do better with per-request-kind caches that don't depend on so much type erasure.
6060
* The stack of active requests uses a `SetVector<AnyRequest>`: we can almost certainly do better with some kind of heterogeneous on-stack representation that only realizes `AnyRequest` instances in the failure cases (e.g., to diagnose a cycle).
61-
* Add API to the evaluator to add a specific (request, result) pair to the cache, and make it "stick" even if the cache is cleared. This API should be usable from places in the compiler that inject specific known state, such as when the Clang importer synthesizes ASTs.
6261
* Explore how best to cache data structures in the evaluator. For example, caching `std::vector<T>` or `std::string` implies that we'll make copies of the underlying data structure each time we access the data. Could we automatically intern the data into an allocation arena owned by the evaluator, and vend `ArrayRef<T>` and `StringRef` to clients instead?
63-
* Sometimes the compiler crashes or otherwise fails due to a cycle detected by the evaluator but (currently) not diagnosed. Add some logic to record cycles encountered during compilation, and if the compiler crashes (or otherwise fails), dump the cycles at the end of execution to help with debugging.
6462
* Cycle diagnostics are far too complicated and produce very poor results. Consider replacing the current `diagnoseCycle`/`noteCycleStep` scheme with a single method that produces summary information (e.g., a short summary string + source location information) and provides richer diagnostics from that string.
6563
* The `isCached()` check to determine whether a specific instance of a request is worth caching may be at the wrong level, because one generally has to duplicate effort (or worse, code!) to make the decision in `isCached()`. Consider whether the `evaluator()` function could return something special to say "produce this value without caching" vs. the normal "produce this value with caching".
6664
* Try to eliminate more boilerplate from subclasses of [`SimpleRequest`](https://github.com/apple/swift/blob/master/include/swift/AST/SimpleRequest.h). We are going to have a *lot* of requests.

branches/tensorflow-next/include/swift/AST/AccessRequests.h

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,6 @@ class AccessLevelRequest :
4545
ValueDecl *decl) const;
4646

4747
public:
48-
// Cycle handling
49-
void diagnoseCycle(DiagnosticEngine &diags) const;
50-
void noteCycleStep(DiagnosticEngine &diags) const;
51-
5248
// Separate caching.
5349
bool isCached() const { return true; }
5450
Optional<AccessLevel> getCachedResult() const;
@@ -73,10 +69,6 @@ class SetterAccessLevelRequest :
7369
evaluate(Evaluator &evaluator, AbstractStorageDecl *decl) const;
7470

7571
public:
76-
// Cycle handling
77-
void diagnoseCycle(DiagnosticEngine &diags) const;
78-
void noteCycleStep(DiagnosticEngine &diags) const;
79-
8072
// Separate caching.
8173
bool isCached() const { return true; }
8274
Optional<AccessLevel> getCachedResult() const;
@@ -99,10 +91,6 @@ class DefaultAndMaxAccessLevelRequest :
9991
evaluate(Evaluator &evaluator, ExtensionDecl *decl) const;
10092

10193
public:
102-
// Cycle handling
103-
void diagnoseCycle(DiagnosticEngine &diags) const;
104-
void noteCycleStep(DiagnosticEngine &diags) const;
105-
10694
// Separate caching.
10795
bool isCached() const { return true; }
10896
Optional<DefaultAndMax> getCachedResult() const;

branches/tensorflow-next/include/swift/AST/Attr.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1680,6 +1680,10 @@ class DeclAttributes {
16801680

16811681
void simple_display(llvm::raw_ostream &out, const DeclAttribute *attr);
16821682

1683+
inline SourceLoc extractNearestSourceLoc(const DeclAttribute *attr) {
1684+
return attr->getLocation();
1685+
}
1686+
16831687
} // end namespace swift
16841688

16851689
#endif

branches/tensorflow-next/include/swift/AST/Decl.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7345,6 +7345,24 @@ void simple_display(llvm::raw_ostream &out, const Decl *decl);
73457345
/// Display ValueDecl subclasses.
73467346
void simple_display(llvm::raw_ostream &out, const ValueDecl *decl);
73477347

7348+
/// Extract the source location from the given declaration.
7349+
SourceLoc extractNearestSourceLoc(const Decl *decl);
7350+
7351+
/// Extract the source location from the given declaration.
7352+
inline SourceLoc extractNearestSourceLoc(const ExtensionDecl *ext) {
7353+
return extractNearestSourceLoc(static_cast<const Decl *>(ext));
7354+
}
7355+
7356+
/// Extract the source location from the given declaration.
7357+
inline SourceLoc extractNearestSourceLoc(const GenericTypeDecl *type) {
7358+
return extractNearestSourceLoc(static_cast<const Decl *>(type));
7359+
}
7360+
7361+
/// Extract the source location from the given declaration.
7362+
inline SourceLoc extractNearestSourceLoc(const AbstractFunctionDecl *func) {
7363+
return extractNearestSourceLoc(static_cast<const Decl *>(func));
7364+
}
7365+
73487366
} // end namespace swift
73497367

73507368
#endif

branches/tensorflow-next/include/swift/AST/DeclContext.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -787,6 +787,9 @@ void simple_display(llvm::raw_ostream &out, const ParamT *dc) {
787787
out << "(null)";
788788
}
789789

790+
/// Extract the source location from the given declaration context.
791+
SourceLoc extractNearestSourceLoc(const DeclContext *dc);
792+
790793
} // end namespace swift
791794

792795
namespace llvm {

branches/tensorflow-next/include/swift/AST/NameLookupRequests.h

Lines changed: 3 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,8 @@ class InheritedDeclsReferencedRequest :
8181
// Caching
8282
bool isCached() const { return true; }
8383

84-
// Cycle handling
85-
void diagnoseCycle(DiagnosticEngine &diags) const;
86-
void noteCycleStep(DiagnosticEngine &diags) const;
84+
// Source location information.
85+
SourceLoc getNearestLoc() const;
8786
};
8887

8988
/// Request the set of declarations directly referenced by the underlying
@@ -124,10 +123,6 @@ class UnderlyingTypeDeclsReferencedRequest :
124123
public:
125124
// Caching
126125
bool isCached() const { return true; }
127-
128-
// Cycle handling
129-
void diagnoseCycle(DiagnosticEngine &diags) const;
130-
void noteCycleStep(DiagnosticEngine &diags) const;
131126
};
132127

133128
/// Request the superclass declaration for the given class.
@@ -150,10 +145,6 @@ class SuperclassDeclRequest :
150145
bool isCached() const { return true; }
151146
Optional<ClassDecl *> getCachedResult() const;
152147
void cacheResult(ClassDecl *value) const;
153-
154-
// Cycle handling
155-
void diagnoseCycle(DiagnosticEngine &diags) const;
156-
void noteCycleStep(DiagnosticEngine &diags) const;
157148
};
158149

159150
/// Request the nominal declaration extended by a given extension declaration.
@@ -176,10 +167,6 @@ class ExtendedNominalRequest :
176167
bool isCached() const { return true; }
177168
Optional<NominalTypeDecl *> getCachedResult() const;
178169
void cacheResult(NominalTypeDecl *value) const;
179-
180-
// Cycle handling
181-
void diagnoseCycle(DiagnosticEngine &diags) const;
182-
void noteCycleStep(DiagnosticEngine &diags) const;
183170
};
184171

185172
struct SelfBounds {
@@ -192,7 +179,7 @@ struct SelfBounds {
192179
class SelfBoundsFromWhereClauseRequest :
193180
public SimpleRequest<SelfBoundsFromWhereClauseRequest,
194181
SelfBounds(llvm::PointerUnion<TypeDecl *,
195-
ExtensionDecl *>),
182+
ExtensionDecl *>),
196183
CacheKind::Uncached> {
197184
public:
198185
using SimpleRequest::SimpleRequest;
@@ -203,12 +190,6 @@ class SelfBoundsFromWhereClauseRequest :
203190
// Evaluation.
204191
SelfBounds evaluate(Evaluator &evaluator,
205192
llvm::PointerUnion<TypeDecl *, ExtensionDecl *>) const;
206-
207-
public:
208-
// Cycle handling
209-
SelfBounds breakCycle() const { return { }; }
210-
void diagnoseCycle(DiagnosticEngine &diags) const;
211-
void noteCycleStep(DiagnosticEngine &diags) const;
212193
};
213194

214195

@@ -227,12 +208,6 @@ class TypeDeclsFromWhereClauseRequest :
227208
// Evaluation.
228209
DirectlyReferencedTypeDecls evaluate(Evaluator &evaluator,
229210
ExtensionDecl *ext) const;
230-
231-
public:
232-
// Cycle handling
233-
DirectlyReferencedTypeDecls breakCycle() const { return { }; }
234-
void diagnoseCycle(DiagnosticEngine &diags) const;
235-
void noteCycleStep(DiagnosticEngine &diags) const;
236211
};
237212

238213
/// Request the nominal type declaration to which the given custom attribute
@@ -254,10 +229,6 @@ class CustomAttrNominalRequest :
254229
public:
255230
// Caching
256231
bool isCached() const { return true; }
257-
258-
// Cycle handling
259-
void diagnoseCycle(DiagnosticEngine &diags) const;
260-
void noteCycleStep(DiagnosticEngine &diags) const;
261232
};
262233

263234
/// The zone number for name-lookup requests.

branches/tensorflow-next/include/swift/AST/SimpleRequest.h

Lines changed: 108 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "llvm/ADT/Hashing.h"
2626
#include "llvm/ADT/STLExtras.h"
2727
#include <tuple>
28+
#include <type_traits>
2829

2930
namespace swift {
3031

@@ -42,6 +43,99 @@ enum class CacheKind {
4243
SeparatelyCached,
4344
};
4445

46+
/// -------------------------------------------------------------------------
47+
/// Extracting the source location "nearest" a request.
48+
/// -------------------------------------------------------------------------
49+
50+
namespace detail {
51+
/// Dummy extract function used to detect when we can call
52+
/// extractNearestSourceLoc() safely.
53+
inline void extractNearestSourceLoc(...) { }
54+
55+
/// Metaprogram to determine whether any input is true.
56+
constexpr bool anyTrue() { return false; }
57+
58+
template<typename ...Rest>
59+
constexpr bool anyTrue(bool current, Rest... rest) {
60+
return current || anyTrue(rest...);
61+
}
62+
}
63+
64+
/// Determine whether we can extract a nearest source location from a value of
65+
/// the given type.
66+
template<typename T>
67+
constexpr bool canExtractNearestSourceLoc() {
68+
using detail::extractNearestSourceLoc;
69+
return !std::is_void<decltype(extractNearestSourceLoc(*(T*)nullptr))>::value;
70+
}
71+
72+
/// Extract source locations when possible, or return an invalid source
73+
/// location if not possible.
74+
template<typename T,
75+
typename = typename std::enable_if<
76+
canExtractNearestSourceLoc<T>()>::type>
77+
SourceLoc maybeExtractNearestSourceLoc(const T& value) {
78+
return extractNearestSourceLoc(value);
79+
}
80+
81+
template<typename T,
82+
typename = void,
83+
typename = typename std::enable_if<
84+
!canExtractNearestSourceLoc<T>()>::type>
85+
SourceLoc maybeExtractNearestSourceLoc(const T& value) {
86+
return SourceLoc();
87+
}
88+
89+
/// Extract the nearest source location from a pointer union.
90+
template<typename T, typename U,
91+
typename = typename std::enable_if<
92+
canExtractNearestSourceLoc<T>() &&
93+
canExtractNearestSourceLoc<U>()>::type>
94+
SourceLoc extractNearestSourceLoc(const llvm::PointerUnion<T, U> &value) {
95+
if (auto first = value.template dyn_cast<T>()) {
96+
return extractNearestSourceLoc(first);
97+
}
98+
if (auto second = value.template dyn_cast<U>()) {
99+
return extractNearestSourceLoc(second);
100+
}
101+
return SourceLoc();
102+
}
103+
104+
namespace detail {
105+
/// Basis case for extracting the nearest source location from a tuple.
106+
template<unsigned Index, typename ...Types,
107+
typename = void,
108+
typename = typename std::enable_if<
109+
(Index >= sizeof...(Types))>::type>
110+
SourceLoc extractNearestSourceLocTuple(const std::tuple<Types...> &) {
111+
return SourceLoc();
112+
}
113+
114+
/// Extract the first, nearest source location from a tuple.
115+
template<unsigned Index, typename ...Types,
116+
typename = typename std::enable_if<Index < sizeof...(Types)>::type>
117+
SourceLoc extractNearestSourceLocTuple(const std::tuple<Types...> &value) {
118+
SourceLoc loc = maybeExtractNearestSourceLoc(std::get<Index>(value));
119+
if (loc.isValid())
120+
return loc;
121+
122+
return extractNearestSourceLocTuple<Index + 1>(value);
123+
}
124+
}
125+
126+
/// Extract the first, nearest source location from a tuple.
127+
template<typename First, typename ...Rest,
128+
typename = typename std::enable_if<
129+
detail::anyTrue(canExtractNearestSourceLoc<First>(),
130+
canExtractNearestSourceLoc<Rest>()...)>::type>
131+
SourceLoc extractNearestSourceLoc(const std::tuple<First, Rest...> &value) {
132+
return detail::extractNearestSourceLocTuple<0>(value);
133+
}
134+
135+
/// -------------------------------------------------------------------------
136+
/// Simple Requests
137+
/// -------------------------------------------------------------------------
138+
45139
/// CRTP base class that describes a request operation that takes values
46140
/// with the given input types (\c Inputs...) and produces an output of
47141
/// the given type.
@@ -66,14 +160,14 @@ enum class CacheKind {
66160
/// void noteCycleStep(DiagnosticEngine &diags) const;
67161
/// \endcode
68162
///
69-
/// Or the \c Derived class can provide a "diagnostic location" operation and
70-
/// diagnostic values for the main cycle diagnostic and a "note" describing a
71-
/// step within the chain of diagnostics:
163+
/// Or the implementation will use the default "circular reference" diagnostics
164+
/// based on the "nearest" source location, which can be provided explicitly by
165+
/// implementing the following in the subclass:
72166
/// \code
73-
/// T getCycleDiagnosticLoc(Inputs...) const;
74-
/// static constexpr Diag<Inputs...> cycleDiagnostic = ...;
75-
/// static constexpr Diag<Inputs...> cycleStepDiagnostic = ...;
167+
/// SourceLoc getNearestLoc() const;
76168
/// \endcode
169+
/// If not provided, a default implementation for \c getNearestLoc() will pick
170+
/// the source location from the first input that provides one.
77171
///
78172
/// Value caching is determined by the \c Caching parameter. When
79173
/// \c Caching == CacheKind::SeparatelyCached, the \c Derived class is
@@ -106,14 +200,6 @@ class SimpleRequest<Derived, Output(Inputs...), Caching> {
106200
return asDerived().evaluate(evaluator, std::get<Indices>(storage)...);
107201
}
108202

109-
template<size_t ...Indices>
110-
void diagnoseImpl(DiagnosticEngine &diags, Diag<Inputs...> diag,
111-
llvm::index_sequence<Indices...>) const {
112-
diags.diagnose(
113-
asDerived().getCycleDiagnosticLoc(std::get<Indices>(storage)...),
114-
diag, std::get<Indices>(storage)...);
115-
}
116-
117203
protected:
118204
/// Retrieve the storage value directly.
119205
const std::tuple<Inputs...> &getStorage() const { return storage; }
@@ -134,14 +220,18 @@ class SimpleRequest<Derived, Output(Inputs...), Caching> {
134220
llvm::index_sequence_for<Inputs...>());
135221
}
136222

223+
/// Retrieve the nearest source location to which this request applies.
224+
SourceLoc getNearestLoc() const {
225+
return extractNearestSourceLoc(storage);
226+
}
227+
137228
void diagnoseCycle(DiagnosticEngine &diags) const {
138-
diagnoseImpl(diags, Derived::cycleDiagnostic,
139-
llvm::index_sequence_for<Inputs...>());
229+
diags.diagnose(asDerived().getNearestLoc(), diag::circular_reference);
140230
}
141231

142232
void noteCycleStep(DiagnosticEngine &diags) const {
143-
diagnoseImpl(diags, Derived::cycleStepDiagnostic,
144-
llvm::index_sequence_for<Inputs...>());
233+
diags.diagnose(asDerived().getNearestLoc(),
234+
diag::circular_reference_through);
145235
}
146236

147237
friend bool operator==(const SimpleRequest &lhs, const SimpleRequest &rhs) {

0 commit comments

Comments
 (0)