One last bit of SE-0072. We shouldn't fall back to bridged classes in the absence of type context for literals anymore. By itself, this kind of hoses the use of literals with NS types, but I think we can get most of the QoI back with overlay changes I plan to propose following this.
Rather than parsing the call arguments (or similar, e.g., subscript)
as a parenthesized expression or tuple, then later reworking that
ParenExpr/TupleExpr if a trailing closure comes along, then digging
through that ParenExpr/TupleExpr to pull out the arguments and
trailing closure... just parse the expression list and trailing
closure together, then directly form the appropriate AST node with
arguments/labels/label locations/trailing closure.
Fixes rdar://problem/19804707, which is an issue where trailing
closures weren't working with unresolved member expressions (e.g.,
".foo {... }"), and is a stepping-stone to SE-0111.
and provide a fix-it to move it to the new location as referenced
in SE-0081.
Fix up a few stray places in the standard library that is still using
the old syntax.
Update any ./test files that aren't expecting the new warning/fix-it
in -verify mode.
While investigating what I thought was a new crash due to this new
diagnostic, I discovered two sources of quite a few compiler crashers
related to unterminated generic parameter lists, where the right
angle bracket source location was getting unconditionally set to
the current token, even though it wasn't actually a '>'.
It looks like migration fixits are done, and this doesn't
expose any new bugs that were not possible before, because
you could already define typealiases inside protocol
extensions.
To prevent some compiler_crasher regressions, add a simple
circularity-breaking hack. I'll need to do a sweep to clean
these up some day soon.
The IterativeTypeChecker now use loops instead of recursion to help keep the stack size low
We diagnose circular dependencies for protocols in a more efficient manner and also prevent the possibility of infinite loops
(in preparation for the private/fileprivate split)
An "access scope" is the outermost DeclContext where a particular
declaration may be referenced: for a 'fileprivate' declaration it's
the enclosing file, and for an 'internal' declaration it's the module.
'public' corresponds to a scope of "everything", represented by a null
DeclContext.
This model extends naturally to the (not-yet-implemented) SE-0025
notion of 'private', where the access scope is a declaration's
immediately enclosing DeclContext.
Complicating this model is the revised rules that allow, e.g., a public
declaration to be declared within an internal type. The access scope
for this declaration is still just the module, not "everything".
This commit reworks formal access control checking in terms of this
model, including tightening up some of the handling for '@testable'.
This implements the rule that you must be able to access a declaration's
type everywhere you can reference the declaration.
This was not intended to change compiler behavior, but in practice it
has made cross-file dependency tracking a bit more conservative
(unnecessarily), caught a mistake in diagnosing access violations,
and fixed a fuzzer-based crasher (see test changes).
Progress on SE-0025 ('private' and 'fileprivate')
Rather than synthesizing a global operator '==' for Equatable enums,
synthesize a member operator, which is more idiomatic and much
cleaner.
To make sure that these synthesized operators can actually be found,
start considering operator requirements in protocols
more generally in the type checker, so that, e.g., "myEnum == myEnum"
will type-check against Equatable.== and, on successful type-check,
will call the (newly-synthesized) witness for '=='. This both makes it
easier to make sure we find the operators in, e.g., complex multi-file
and lazy-type checking scenarios, and is a step toward the
type-checking improvements described in SE-0091.
Allow 'static' (or, in classes, final 'class') operators to be
declared within types and extensions thereof. Within protocols,
require operators to be marked 'static'. Use a warning with a Fix-It
to stage this in, so we don't break the world's code.
Protocol conformance checking already seems to work, so add some tests
for that. Update a pile of tests and the standard library to include
the required 'static' keywords.
There is an amusing name-mangling change here. Global operators were
getting marked as 'static' (for silly reasons), so their mangled names
had the 'Z' modifier for static methods, even though this doesn't make
sense. Now, operators within types and extensions need to be 'static'
as written.
trying to set the superclass on classes in such situations by setting the superclass of an invalid decl to the error type.
This fixes a bunch of compiler crashes, and also changes some errors in other tests where the main error is the invalid declaration and now the
downstream errors can be a bit different because the decl has been invalidated.
Previously getInterfaceType() would punt to getType() if no
interface type was set. This patch changes getInterfaceType()
to assert if no interface type is set, and updates various
places to set the interface type explicitly.
This brings us a step closer to removing PolymorphicFunctionType.
Rather than using a specialized matching rule in the type checker that
depends on having default arguments in types, use call argument
matching consistently.
Note #1: This (correctly) breaks some existing code that depends on
inferring a parameter type of () for a single-argument parameter from
a no-argument function type().
Note #2: This pessimizes a code completion test, where the code
completion engine seems to depend on some quirks of argument
matching. The "type relationship" matching needs non-trivial work.
The underlying type can now refer to generic parameters from an
outer context, and we allow qualified and unqualified access to
such typealiases.
One problem remains, with specializations of generic typealiases
in expression parsing context, marked with FIXME in the test.
Consider this code:
struct A<T> {
struct B {}
struct C<U> {}
}
Previously:
- getDeclaredType() of 'A.B' would give 'A<T>.B'
- getDeclaredTypeInContext() of 'A.B' would give 'A<T>.B'
- getDeclaredType() of 'A.C' would give 'A<T>.C'
- getDeclaredTypeInContext() of 'A.C' would give 'A<T>.C<U>'
This was causing problems for nested generics. Now, with this change,
- getDeclaredType() of 'A.B' gives 'A.B' (*)
- getDeclaredTypeInContext() of 'A.B' gives 'A<T>.B'
- getDeclaredType() of 'A.C' gives 'A.C' (*)
- getDeclaredTypeInContext() of 'A.C' gives 'A<T>.C<U>'
(Differences marked with (*)).
Also, this change makes these accessors fully lazy. Previously,
only getDeclaredTypeInContext() and getDeclaredIterfaceType()
were lazy, whereas getDeclaredType() was built from validateDecl().
Fix a few spots where the return value wasn't being checked
properly.
These functions return ErrorType if a circularity was detected via
the generic parameter list, or if the extension did not resolve.
They return Type() if the extension cannot be resolved *yet*.
This is pretty subtle, and I'll need to do another pass over
callers of these functions at some point. Many of them should be
moved over to use getSelfInContext(), getSelfOfContext() and
getSelfInterfaceType() instead.
Finally, this patch consolidates logic for diagnosting invalid
nesting of types.
The parser had some code for protocols in bad places and bad things
inside protocols, and Sema had several different bail-outs for
bad things in protocols, nested generic types, and stuff nested
inside protocol extensions.
Combine all of these into a single set of checks in Sema. Note
that we no longer give up early if we find invalid nesting.
Leaving decls unvalidated and un-type-checked only leads to
further problems. Now that all the preliminary crap has been
fixed, we can go ahead and start validating these funny nested
decls, actually fixing some crashers in the process.
Another pre-emptive compiler_crasher regression fix.
I have an idea for consolidating some of these hacky circularity
checks in a nice way, but not now.
Every call to validateGenericTypeSignature() had the same
boilerplate following; move the common logic into that
function.
As one might expect, each callsite had slight variants on
the same underlying logic -- this makes them consistent.
Also, this slightly widens the scope during which
GenericTypeDecl::isValidatingGenericSignature() returns
true.
Interesting, that change introduces a diagnostic in an
existing testcase where previously there was none:
protocol P {
associatedtype T
}
struct S<A: P where A.T == S<A>> {}
While it looks like this generic signature was built
correctly, in fact I think we weren't computing
conformances for the substitution of 'A' in 'S<A>'.
After trying small variations on the above testcase,
I quickly ran into SILGen crashes, which the diagnostic
now prevents. A few interesting cases still crash.
See test/decl/protocol/req/recursion.swift for the
gory details.
There was a weirdness with ProtocolType::get() that was causing me grief
while trying to refactor getDeclaredType() and related code in another
patch.
Instead of caching the result like we do elsewhere, this would directly
store the new type into the ProtocolDecl. This is smelly, so let's not
do that.
Mostly NFC, but note that DeclContext::getDeclaredInterfaceType()
returns Type() for invalid extensions, whereas the older way
of going through getAsNominalTypeOrNominalTypeExtensionContext()
would crash because we'd call getDeclaredInterfaceType() on a
null decl.
The old check was problematic because it would sometimes return
ErrorType from accessing the generic parameters of a type that was
in the process of having its generic signature validated.
Instead fix the root cause of the circularity, which was recursion
through resolveType() when resolving a type's inheritance clause.
To fix it, let's just not walk adopted protocols when looking up
the superclass of a class. Inheriting from an associated type does
not seem very useful, and will probably be hard to get right in
the general case.
I wasn't able to reduce a useful test case, but this patch prevents
compiler_crashers regressions with some other changes I'm working on.
This now fails with the infamous 'Assertion failed: ((conforms ||
replacement->is<ErrorType>() || firstArchetype->getIsRecursive() ||
isOpenedAnyObject(replacement) || replacement->is<GenericTypeParamType>())
&& "Constraint system missed a conformance?")' error.
The actual problem is something with unbound generics and inference
of generic parameters. Here's a minimal test case:
protocol A {}
struct B<f> {}
func a<T:A>() {
class AA {
var t:B=B()
}
}
I'll fix it soon.
There was a weird corner case with nested generic functions that
would fail in the SIL verifier with some nonsense about archetypes
out of context.
Fix this the "right" way, by re-working Sema function declaration
validation to assign generic signatures in a more principled way.
Previously, nested functions did not get an interface type unless
they themselves had generic parameters.
This was inconsistent with methods nested inside generic types,
which did get an interface type even if they themselves did not
have a generic parameter list.
There's some spill-over in SILGen from this change. Mostly it
makes things more consistent and fixes some corner cases.
With the previous resolveTypeInContext() patch, a few compiler
crashers regressed with this problem, presumably because we were now
performing lookups in more contexts than before.
This is a class of problems where we would attempt a recursive
validation:
1) Generic signature validation begins for type T
2) Name lookup in type context finds a non-type declaration D nested in T
3) Generic signature validation begins for D
4) The outer generic context of D is T, but T doesn't have a generic
signature yet
The right way to break such cycles is to implement the iterative
decl checker design. However when the recursion is via name lookup,
we can try to avoid the problem in the first place by not validating
non-type declarations if the client requested a type-only lookup.
Note that there is a small semantic change here, where programs that
were previously rejected as invalid because of name clashes are
now valid. It is arguable if we want to allow stuff like this or not:
class A {
func A(a: A) {}
}
or
class Case {}
enum Foo {
case Case(Case)
}
However at the very least, the new behavior is better because it
gives us an opportunity to add a diagnostic in the right place
later. The old diagnostics were not very good, for example the
second example just yields "use of undeclared type 'Case'".
In other examples, the undeclared type diagnostic would come up
multiple times, or we would generate a cryptic "type 'A' used within
its own definition".
As far as I understand, this should not change behavior of any existing
valid code.
This is a big refactoring of resolveTypeInContext() which makes
the function clearer to understand by merging various special
cases and generalizing the logic for walking parent and superclass
contexts to cover more cases.
This improves typealiases in protocols a bit:
1) Previously a typealias in a protocol either had to be concrete,
or consist of a single path of member types from Self, eg
Self.A.B. Lift this restriction, so we can now write things like
protocol Fireworks {
associatedtype Exploding
typealias Exploder = Exploding -> [Exploding]
}
2) Protocol typealiases can now be accessed via qualified lookup
on concrete types. Getting this working for unqualified lookup
requires further refactorings which will be in a subsequent
patch.
This reverts commit 586288312c. It broke
tests:
Swift :: IDE/complete_override_access_control.swift
Swift :: IDE/complete_value_expr.swift
Swift :: SourceKit/DocSupport/doc_swift_module.swift
Swift :: decl/typealias/associated_types.swift
Swift :: decl/typealias/typealias.swift