This doesn't really fit the request evaluator model since the
result of evaluating the request is the new insertion point,
but we don't have a way to get the insertion point of an
already-expanded scope.
Instead, let's change the callers of the now-removed
expandAndBeCurrentDetectingRecursion() to instead call
expandAndBeCurrent(), while checking first if the scope was
already expanded.
Also, set the expanded flag before calling expandSpecifically()
from inside expandAndBeCurrent(), to ensure that re-entrant
calls to expandAndBeCurrent() are flagged by the existing
assertion there.
Finally, replace a couple of existing counters, and the
now-gone request counter with a single ASTScopeExpansions
counter to track expansions.
This attribute allows to define a pre-specialized entry point of a
generic function in a library.
The following definition provides a pre-specialized entry point for
`genericFunc(_:)` for the parameter type `Int` that clients of the
library can call.
```
@_specialize(exported: true, where T == Int)
public func genericFunc<T>(_ t: T) { ... }
```
Pre-specializations of internal `@inlinable` functions are allowed.
```
@usableFromInline
internal struct GenericThing<T> {
@_specialize(exported: true, where T == Int)
@inlinable
internal func genericMethod(_ t: T) {
}
}
```
There is syntax to pre-specialize a method from a different module.
```
import ModuleDefiningGenericFunc
@_specialize(exported: true, target: genericFunc(_:), where T == Double)
func prespecialize_genericFunc(_ t: T) { fatalError("dont call") }
```
Specially marked extensions allow for pre-specialization of internal
methods accross module boundries (respecting `@inlinable` and
`@usableFromInline`).
```
import ModuleDefiningGenericThing
public struct Something {}
@_specializeExtension
extension GenericThing {
@_specialize(exported: true, target: genericMethod(_:), where T == Something)
func prespecialize_genericMethod(_ t: T) { fatalError("dont call") }
}
```
rdar://64993425
Rather than relying on clients to cope with the potential for circular
inheritance of superclass declarations, teach SuperclassDeclRequest to
establish whether circular inheritance has occurred and produce "null"
in such cases. This allows other clients to avoid having to think about
To benefit from this, have SuperclassTypeRequest evaluate
SuperclassDeclRequest first and, if null, produce a Type(). This
ensures that we don't get into an inconsistent situation where there
is a superclass type but no superclass declaration.
It wasn't one in the past because the referenced name tracker was written into by unqualified lookup, which would delegate to this request. Now that it's no longer doing that, we have to capture this edge here for private dependencies.
Split off the notion of "recording" dependencies from the notion of
"collecting" dependencies. This corrects an oversight in the previous
design where dependency replay and recording were actually not "free" in
WMO where we actually never track dependencies. This architecture also
lays the groundwork for the removal of the referenced name trackers.
The algorithm builds upon the infrastructure for dependency sources and
sinks laid down during the cut over to request-based dependency tracking
in #30723.
The idea of the naive algorithm is this:
For a chain of requests A -> B* -> C -> D* -> ... -> L where L is a lookup
request and all starred requests are cached, once L writes into the
dependency collector, the active stack is walked and at each cache-point
the results of dependency collection are associated with the request
itself (in this example, B* and D* have all the names L found associated
with them). Subsequent evaluations of these cached requests (B* and D*
et al) will then *replay* the previous lookup results from L into the
active referenced name tracker. One complication is, suppose the
evaluation of a cached request involves multiple downstream name
lookups. More concretely, suppose we have the following request trace:
A* -> B -> L
|
-> C -> L
|
-> D -> L
|
-> ...
Then A* must see the union of the results of each L. If this reminds
anyone of a union-find, that is no accident! A persistent union-find
a la Conchon and Filliatre is probably in order to help bring down peak
heap usage...
Re-implement operator and precedencegroup decl
lookup to use `namelookup::getAllImports` and
existing decl shadowing logic. This allows us to
find operator decls through `@_exported` imports,
prefer operator decls defined in the same module
over imported decls, and fixes a couple of other
subtle issues.
Because this new implementation is technically
source breaking, as we can find multiple results
where we used to only find one result, it's placed
behind the new Frontend flag
`-enable-new-operator-lookup` (with the aim of
enabling it by default when we get a new language
mode).
However the new logic will always be used if the
result is unambiguous. This means that e.g
`@_exported` operators will be instantly available
as long as there's only one candidate. If multiple
candidates are found, we fall back to the old
logic.
Resolves SR-12132.
Resolves rdar://59198796.
Make sure a dependency gets registered when a
direct lookup is fired off. This is necessary in
order to ensure that operator redeclaration
checking records the right dependencies (and any
future logic that might want to perform direct
operator lookups).
In doing so, this commit also removes the
compatibility logic for the old referenced name
tracker that would skip recording dependencies in
certain cases. This should be safe as the new
logic will record strictly more dependencies than
the old logic.
Define a new type DependencyCollector that abstracts over the
incremental dependency gathering logic. This will insulate the
request-based name tracking code from future work on private,
intransitive dependencies.
Convert most of the name lookup requests and a few other ancillary typechecking requests into dependency sinks.
Some requests are also combined sinks and sources in order to emulate the current scheme, which performs scope changes based on lookup flags. This is generally undesirable, since it means those requests cannot immediately be generalized to a purely context-based scheme because they depend on some client-provided entropy source. In particular, the few callers that are providing the "known private" name lookup flag need to be converted to perform lookups in the appropriate private context.
Clients that are passing "no known dependency" are currently considered universally incorrect and are outside the scope of the compatibility guarantees. This means that request-based dependency tracking registers strictly more edges than manual dependency tracking. It also means that once we fixup the clients that are passing "known private", we can completely remove these name lookup flags.
Finally, some tests had to change to accomodate the new scheme. Currently, we go out of our way to register a dependency edge for extensions that declare protocol conformances. However, we were also asserting in at least one test that extensions without protocol conformances weren't registering dependency edges. This is blatantly incorrect and has been undone now that the request-based scheme is automatically registering this edge.
Switch the direct operator lookup logic over to
querying the SourceLookupCache, then switch the
main operator lookup logic over to calling the
direct lookup logic rather than querying the
operator maps on the SourceFile.
This then allows us to remove the SourceFile
operator maps, in addition to the logic from
NameBinding that populated them. This requires
redeclaration checking to be implemented
separately.
Finally, to compensate for the caching that the old
operator maps were providing for imported results,
turn the operator lookup requests into cached
requests.
A request is intended to be a pure function of its inputs. That function could, in theory, fail. In practice, there were basically no requests taking advantage of this ability - the few that were using it to explicitly detect cycles can just return reasonable defaults instead of forwarding the error on up the stack.
This is because cycles are checked by *the Evaluator*, and are unwound by the Evaluator.
Therefore, restore the idea that the evaluate functions are themselves pure, but keep the idea that *evaluation* of those requests may fail. This model enables the best of both worlds: we not only keep the evaluator flexible enough to handle future use cases like cancellation and diagnostic invalidation, but also request-based dependencies using the values computed at the evaluation points. These aforementioned use cases would use the llvm::Expected interface and the regular evaluation-point interface respectively.
Factor out the lookup side of TypeChecker::conformsToProtocol so we have
a dependency registration point available for evaluator-based
dependencies that doesn't have re-entrancy problems.
Introduce DirectOperatorLookupRequest &
DirectPrecedenceGroupLookupRequest that lookup
operator and precedence groups within a given
file or module without looking through imports.
These will eventually be used as the basis for the
new operator lookup implementation, but for now
just use them when querying lookup results from
serialized module files.
Turn macro metaprogramming into template metaprogramming by defining a new kind of request that runs operator lookups.
This is the final piece of the puzzle for requestification of the current referenced name tracker system.
Soft revert a09382c. It should now be safe to add this flag back as an optimization to specifically disable lazy member loading instead of all extension loading.
Push the flag back everywhere it was needed, but also push it into lookup for associated type members which will never appear in extensions.
We’re going to start serializing this for public types that have non-public-or-@usableFromInline initializers, so turn it into a request that we can query and cache it in the existing bit.
This allows us use an OptionSet parameter for
the request (as currently we can't directly use it
as a parameter due to not having an == definition
for it). It also allows us to regain default
arguments for the source loc and flag parameters.
Use the request evaluator to get the easier in-module precedence group cycles. Unfortunately, cross-module precedence group cycles are still a possibility, and do not actually cause cyclic request evaluation, so we cannot completely erase the old diagnostics machinery.
Move the machinery itself into the type checker and shift the request into that zone as well to appease the linker.
Define the LookupPrecedenceGroupRequest and OperatorPrecedenceGroupRequest for looking up an unvalidated precedence group declaration and retrieving then validating the precedence group associated with an operator.
This allows us to drop both validateDecl overloads for these types out of the TypeChechecker
Introduce some template metaprogramming infrastructure to retrieve the
"nearest" source location to the inputs of a request, and use that to
provide default diagnoseCycle and noteCycleStep implementations. This
will help remove a bunch of boilerplate from new requests.
Encode the input and output parameters for a SimpleRequest instance in a
function type and move the CacheKind to the end, making it easier to
sort out inputs from outputs:
```
class DefaultTypeRequest
: public SimpleRequest<DefaultTypeRequest,
Type(KnownProtocolKind, const DeclContext *),
CacheKind::SeparatelyCached>
```
When building with Visual Studio, the following error is identified:
'SimpleRequest': non-class template has already been declared as a class template
note: see declaration of 'SimpleRequest'
Change the friend declarations to friend the type without the `class` specifier.
Our walk over the requirement interface types meant that
computing the access level of an extension member depended
on type resolution and the GSB.
Fix this by adding a new request that simply collects all
TypeDecls referenced from a TypeRepr, and compute the
extension's maximum access level using that.
If we use Structural rather than Interface type resolution when
walking the extension's requirements, we don't have to build its
generic signature first.