Fixes rdar://problem/53407949 | SR-11138. Previously, we'd only look at the outermost property wrapper to decide whether the wrapped property's getter and setter were `mutating` (or exist at all). In reality, this requires considering the semantics of the composed accesses of each wrapper layer's
`wrappedValue` property. Fixing this systematically addresses a number of issues:
- As SR-11138 reported, composing a nonmutating-get-set wrapper ought to produce a composed wrapper
that's nonmutating.
- We would previously allow a property wrapper with a mutating getter to be nested inside one with
only a getter, even though the resulting implementation was unsound (because there's no mutable
context for the inner wrapper to execute its get on.)
- Similarly, we would construct unsound setters in cases where the setter can't exist, such as when
the nested wrapper isn't settable but the outer wrapper is.
Fixes a regression where the compiler would reject something like:
@State var x: Int?
as not having an initializer, even though an Int? property ought to default to nil.
rdar://problem/53504653
This just moves the code from the parser into a request. Sema will
still overwrite the ImplInfo field for lazy properties and
property wrappers; refactoring that is next.
Previously we would copy this attribute from a superclass to the
subclass when validating a subclass. However, this is only correct
if the superclass is always guaranteed to have been validated
before the subclass.
Indeed, it appears this assumption is no longer true, so we would
sometimes lose track of the attribute, which would result in SILGen
failing to emit the ivar initializer entry point.
Instead, check for the attribute as part of the superclass walk
in checkAncestry(), ensuring the result is always up to date, correct,
and cached.
As a follow-up, we should also convert checkAncestry() into a
request, but I'm not doing that here to keep the fix short.
Fixes <rdar://problem/50845438>.
We want to compute the former independently of the latter.
It's only 16 bits so storing it inside the Decl is fine;
it also allows us to eliminate the 'compact' representation
where an AbstractStorageDecl without an accessor record is
assumed to be stored.
Add the request `ExistentialConformsToSelfRequest` to lazily determine
if an existential conforming to a protocol can be matched with a
generic type parameter constrained to that protocol.
Add the request `ProtocolRequiresClassRequest` to lazily determine if a
`ProtocolDecl` requires conforming types to be a class.
Note that using the request evaluator to compute `requiresClass` introduces
cycle errors for protocol declarations, where this computation didn't
previously emit diagnostics. For now, we'll allow duplicate diagnostics in this
case, with the eventual goal of removing explicitly checking for cycles
via `checkCircularity` (instead letting the request evaluator handle cycle
diagnostics).
This improves on the previous situation:
- The request ensures that the backing storage for lazy properties
and property wrappers gets synthesized first; previously it was
only somewhat guaranteed by callers.
- Instead of returning a range this just returns an ArrayRef,
which simplifies clients.
- Indexing into the ArrayRef is O(1), which addresses some FIXMEs
in the SIL optimizer.
Instead of requiring that function body synthesizers will always call
setBody(), which is annoyingly stateful, have function body synthesizers
always return the synthesized brace statement along with a bit that
indicates whether the body was already type-checked. This takes us a
step closer to centralizing the mutation of the body of a function.
A number of callers to AbstractFunctionDecl::getBody() were only
extracting the source range of the body... which can be retrieved more
efficiently with getBodySourceRange().
finalizeDecl() would kick off certain requests. This was necessary
before we had the long-lived type checker to ensure that requests
that required a type checker could be completed in time for SILGen.
It was also necessary to always emit diagnostics for declarations in
primary files.
Since we now have a long lived type checker, the first reason is no
longer valid, so we can move this work from finalizeDecl() to
typeCheckDecl(), where it will run for declarations in primary files
only.
To ensure that @objc selector conflict diagnostics still get emitted,
we also walk the superclass chain and force isObjC() to be computed
for each declaration in each superclass.
The mangling unfortunately doesn't take the constraints into account, leading to
SR-10725 | rdar://problem/50987172. Changing the mangling at this point is hazardous, so it's probably best
to disallow this for now.
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.
Currently only works for types that are /just/ a 'some' type, not in a
nested position. Also won't show them for opaque types with different
requirements, to avoid noise when it's not strictly necessary. This
does mean that 'some P' vs. 'some P & Q' won't get the origin part.
Part of rdar://problem/50346954
Apart from mildly speeding up indexing, this also keeps the compiler
from running into issues with implementation-only imports that may not
be present while we're trying to index.
rdar://problem/52083709
A protocol's generic signature is trivial; the generic environment is
simple but not free to compute. Avoid the costs of the previous commit
by /not/ computing it if it's never asked for.
This calculates a result directly from the function's result type
instead of checking a bit that was previously set by the type
checker. Also, always returns true for constructors to simplify
some callers.