Handle PatternBindingDecls with missing var locations, which can
happen for loop iterator vars, and FuncDecls with missing name and
func locations, which can happen for `defer`. Also while here make
sure we set the source location of a parser-produced ErrorExpr.
Keep track of all of the type parameters and archetypes that are captured
by a local function or closure. Use that information to diagnose cases
where a non-Sendable metatype crosses an isolation boundary.
This PR refactors the ASTDumper to make it more structured, less mistake-prone, and more amenable to future changes. For example:
```cpp
// Before:
void visitUnresolvedDotExpr(UnresolvedDotExpr *E) {
printCommon(E, "unresolved_dot_expr")
<< " field '" << E->getName() << "'";
PrintWithColorRAII(OS, ExprModifierColor)
<< " function_ref=" << getFunctionRefKindStr(E->getFunctionRefKind());
if (E->getBase()) {
OS << '\n';
printRec(E->getBase());
}
PrintWithColorRAII(OS, ParenthesisColor) << ')';
}
// After:
void visitUnresolvedDotExpr(UnresolvedDotExpr *E, StringRef label) {
printCommon(E, "unresolved_dot_expr", label);
printFieldQuoted(E->getName(), "field");
printField(E->getFunctionRefKind(), "function_ref", ExprModifierColor);
if (E->getBase()) {
printRec(E->getBase());
}
printFoot();
}
```
* Values are printed through calls to base class methods, rather than direct access to the underlying `raw_ostream`.
* These methods tend to reduce the chances of bugs like missing/extra spaces or newlines, too much/too little indentation, etc.
* More values are quoted, and unprintable/non-ASCII characters in quoted values are escaped before printing.
* Infrastructure to label child nodes now exists.
* Some weird breaks from the normal "style", like `PatternBindingDecl`'s original and processed initializers, have been brought into line.
* Some types that previously used ad-hoc dumping functions, like conformances and substitution maps, are now structured similarly to the dumper classes.
* I've fixed the odd dumping bug along the way. For example, distributed actors were only marked `actor`, not `distributed actor`.
This PR doesn't change the overall style of AST dumps; they're still pseudo-S-expressions. But the logic that implements this style is now isolated into a relatively small base class, making it feasible to introduce e.g. JSON dumping in the future.
AutoClosureExprs created by the constraint system used to be constructed
with the decl context of the constraint system itself. This meant that
autoclosures in expressions nested in closures would initially be
parented onto any enclosing functions rather than the deepest closure
context. When we ran capture analysis and lookup from inside of the body
of these nascent values, we would fail to find declarations brought into
scope by those parent closures. This is especially relevant when
pre-typechecked code is involved since captures for those declarations
will be forced before their bodies have been recontextualized. See
issue #34230 for why we need to force things so early.
The attached test case demonstrates both bugs: The former a bogus lookup
through the parent context that would incorrectly reject this otherwise
well-formed code. The latter is a crash in SILGen when the capture
computation would fail to note $0.
Use the decl context of the solution application target, which is always
going to be the deepest user-written closure expression available to us,
and therefore the deepest scope that can introduce capturable variables.
rdar://79248469
A TopLevelCodeDecl is a local context and any declarations inside
of one must be treated as captures. Furthermore, all the
TopLevelCodeDecl children of a source file are peers, and can
see each other's bindings, so don't perform an exact match on the
DeclContext.
Part of <rdar://problem/23051362> / <https://bugs.swift.org/browse/SR-3528>.
Sema does not have enough information to diagnose these problems correctly.
Also, there was an unimplemented case in the analysis; if a closure did not
yet have computed captures, we'd add it to the ForwardCapturedFuncs list,
but nothing ever looked at that list.
- Many tests got broken because of two things:
- AST dump now outputs to stdout, but many tests expected stderr. This was a straightforward fix.
- Many tests call swift with specific parameters; specifically, many call `swift frontend` directly. This makes them go through the compiler in unexpected ways, and specifically it makes them not have primary files, which breaks the new AST dump implementation. This commit adds the old implementation as a fallback for those cases, except it dumps to `stdout` to maintain some consistence.
Finally, the `/test/Driver/filelists.swift` failed for unknown reasons. It seems its output now had some lines out of order, and fixing the order made the test pass. However, as the reasons why it failed are unknown, this fix might not have been a good idea. Corrections are welcome.
The diagnostic when a user attempts to pass an argument requiring an implicit conversion (e.g. declared as a subclass, type conforming to protocol, etc.) to an inout parameter seems to be confusing for users—see e.g. SR-8155, SR-8148. This change replaces it with a more specific diagnostic which clearly suggests a solution. It also includes a fix-it suggesting the user change the type of the original variable if it’s a local with a simple type signature.
The storage kind has been replaced with three separate "impl kinds",
one for each of the basic access kinds (read, write, and read/write).
This makes it far easier to mix-and-match implementations of different
accessors, as well as subtleties like implementing both a setter
and an independent read/write operation.
AccessStrategy has become a bit more explicit about how exactly the
access should be implemented. For example, the accessor-based kinds
now carry the exact accessor intended to be used. Also, I've shifted
responsibilities slightly between AccessStrategy and AccessSemantics
so that AccessSemantics::Ordinary can be used except in the sorts of
semantic-bypasses that accessor synthesis wants. This requires
knowing the correct DC of the access when computing the access strategy;
the upshot is that SILGenFunction now needs a DC.
Accessor synthesis has been reworked so that only the declarations are
built immediately; body synthesis can be safely delayed out of the main
decl-checking path. This caused a large number of ramifications,
especially for lazy properties, and greatly inflated the size of this
patch. That is... really regrettable. The impetus for changing this
was necessity: I needed to rework accessor synthesis to end its reliance
on distinctions like Stored vs. StoredWithTrivialAccessors, and those
fixes were exposing serious re-entrancy problems, and fixing that... well.
Breaking the fixes apart at this point would be a serious endeavor.
Rather than relying on the NameAliasType we get by default for references
to non-generic typealiases, use BoundNameAliasType consistently to handle
references to typealiases that are formed by the type checker.
Using `-dump-parse` on `func foo<T>(bar: T) {}` results in:
```
(source_file
(func_decl "foo(bar:)"<T>
(parameter_list
(parameter "bar" apiName=bar))
(brace_stmt)))
```
Notice there is no space between "foo(bar:)" and <T>.
Add a space to correct the formatting error.
- TypeAliasDecl::getAliasType() is gone. Now, getDeclaredInterfaceType()
always returns the NameAliasType.
- NameAliasTypes now always desugar to the underlying type as an
interface type.
- The NameAliasType of a generic type alias no longer desugars to an
UnboundGenericType; call TypeAliasDecl::getUnboundGenericType() if you
want that.
- The "lazy mapTypeOutOfContext()" hack for deserialized TypeAliasDecls
is gone.
- The process of constructing a synthesized TypeAliasDecl is much simpler
now; instead of calling computeType(), setInterfaceType() and then
setting the recursive properties in the right order, just call
setUnderlyingType(), passing it either an interface type or a
contextual type.
In particular, many places weren't setting the recursive properties,
such as the ClangImporter and deserialization. This meant that queries
such as hasArchetype() or hasTypeParameter() would return incorrect
results on NameAliasTypes, which caused various subtle problems.
- Finally, add some more tests for generic typealiases, most of which
fail because they're still pretty broken.
This was causing us to emit diagnostics talking about τ_m_n, which is
not helpful.
Now that generic function types print sanely, print them in a few
places where we were previously printing PolymorphicFunctionTypes.
Until the point where ASTScope-based unqualified name lookup is the
default, unqualified name lookup can still find names declared *after*
the source location. The 'hasType' check no longer makes sense, so actually
check the source location of the entity we found.
Implements part of SE-0110. Single argument in closures will not be accepted if
there exists explicit type with a number of arguments that's not 1.
```swift
let f: (Int, Int) -> Void = { x in } // this is now an error
```
Note there's a second part of SE-0110 which could be considered additive,
which says one must add an extra pair of parens to specify a single arugment
type that is a tuple:
```swift
let g ((Int, Int)) -> Void = { y in } // y should have type (Int, Int)
```
This patch does not implement that part.
Parameters are normally given 'private' access, because they can only
be referred to within the body of the owning function. However,
single-expression closures allow a parameter to appear in a constraint
system in the containing context. Mark closure parameters as
'fileprivate' instead.
Similarly, 'private' at the top level is normally equivalent to
'fileprivate', but not for a decl that appears within top-level
imperative code, which has a TopLevelCodeDecl context. This currently
only happens for bindings in a top-level 'guard' statement; mark
these variables and constants as 'fileprivate' as well.
More progress on SE-0025 ('private' and 'fileprivate').
This also adds some tests for the existing generic parameter
capture logic, which was only tested as part of SILGen tests
until now.
Also, move capture analysis into a new TypeCheckCaptures.cpp file.
Make the following patterns illegal:
if var x = ... {
...
}
guard var x = ... else {
...
}
while var x = ... {
...
}
And provide a replacement fixit 'var' -> 'let'.
rdar://problem/23172698
Swift SVN r32855
Otherwise, we'll fail to capture "locals" declared in top-level guard
statements. This led to an assertion failure in SILGen.
Depends on previous commit.
rdar://problem/21997265
Swift SVN r30812
init()'s implicitly evaluate the initial values for properties, and we aren't modeling
that correctly in the AST. This prevented the closure checker from noticing these
accesses, leading to SILGen crashing later. In the absence of proper AST modeling of
this, add special case handling for them.
Swift SVN r29508
Special-casing these as MemberRefExprs created an asymmetry
where unbound archetype instance methods (<T : P> T.f) could
not be represented. Treating class and protocol methods
uniformly also eliminates a handful of special cases around
MemberRefExpr.
SILGen's RValue and call emission peepholes now have to know
about DeclRefExprs that point to protocol methods.
Finally, generalize the diagnostic for partially applied
mutating methods to any partially applied function with an
inout parameter, since this is not supported.
Fixes <rdar://problem/20564672>.
Swift SVN r29298