Record the initializer type as soon as we have a solution, before
it is applied, and get the type from the constriant system instead
of from the final type checked expression.
Note that the coerceToMaterializable() was unnecessary, since we
always coerce the value to an rvalue type with coerceToType().
Eventually coerceToMaterializable() should go away.
This is mostly NFC, except using the result of simplifyType() rather
than the type of the final expression changes some diagnostics where it
appears we were previously losing sugar.
Also this accidentally fixes a crasher. Unfortunately the underlying
issue is still there (applying a solution has bugs with opened
existentials "leaking" out) -- this merely masks the problem by
getting the initializer type directly from the constriant system.
This lets you match `case .foo` when `foo` resolves to any static member, instead of only a `case`, albeit without the exhaustiveness checking and subpattern capabilities of proper cases. While we're here, adjust the type system we set up for unresolved patterns embedded in expressions so that we give better signal in the error messages too.
This used to cause SILGen to capture and subsequently load `self` as a
constant. Then, when the super call was SILGen’d, it assumed that
`self` would be loaded Boxed. Diagnose before hitting SILGen so we
don’t have to pollute Lowering with code that handles `self` in this
odd position.
String literal expressions, as well as the magic literals #file and
tuple value that is then fed into one or two call expressions. For
string literals, that tuple value was implicitly splatted, breaking
AST invariants.
Instead, keep string literals and these magic literals that produce a
string as a single expression node, but store the declarations that
will be used to transform the raw literal into the complete
literal. SILGen will form the appropriate calls. This representation
is far simpler---the AST no longer has a bunch of implicit nodes---and
doesn't break AST invariants.
- All parts of the compiler now use ‘P1 & P2’ syntax
- The demangler and AST printer wrap the composition in parens if it is
in a metatype lookup
- IRGen mangles compositions differently
- “protocol<>” is now “swift.Any”
- “protocol<_TP1P,_TP1Q>” is now “_TP1P&_TP1Q”
- Tests cases are updated and added to test the new syntax and mangling
This commit defines the ‘Any’ keyword, implements parsing for composing
types with an infix ‘&’, and provides a fixit to convert ‘protocol<>’
- Updated tests & stdlib for new composition syntax
- Provide errors when compositions used in inheritance.
Any is treated as a contextual keyword. The name ‘Any’
is used emit the empty composition type. We have to
stop user declaring top level types spelled ‘Any’ too.
This reverts commit dc24c2bd34.
Turns out Chris fixed the build but when I was looking at the bots, his fix had
not been tested yet, so I thought the tree was still red and was trying to
revert to green.
along with recent policy changes:
- For expression types that are not specifically handled, make sure to
produce a general "unused value" warning, catching a bunch of unused
values in the testsuite.
- For unused operator results, diagnose them as uses of the operator
instead of "calls".
- For calls, mutter the type of the result for greater specificity.
- For initializers, mutter the type of the initialized value.
- Look through OpenExistentialExpr's so we can handle protocol member
references propertly.
- Look through several other expressions so we handle @discardableResult
better.
It is a common point of confusion that code like:
switch value {
case .Foo, .Bar where someNumber != 100:
Only applies the where clause to the second pattern, not every pattern in the case.
Resolve this by warning about the ambiguity, providing two notes (with fixits) that
resolve the issue in different ways:
t.swift:25:17: warning: 'where' only applies to the second pattern match in this case
case .Foo, .Bar where someNumber != 100:
~~~~ ^ ~~~~~~~~~~~~~~~~~
t.swift:25:12: note: disambiguate by adding a line break between them if this is desired
case .Foo, .Bar where someNumber != 100:
^
t.swift:25:6: note: duplicate the 'where' on both patterns to check both patterns
case .Foo, .Bar where someNumber != 100:
^~~~
where someNumber != 100
Parser now accepts multiple patterns in switch cases that contain variables.
Every pattern must contain the same variable names, but can be in arbitrary
positions. New error for variable that doesn't exist in all patterns.
Sema now checks cases with multiple patterns that each occurence of a variable
name is bound to the same type. New error for unexpected types.
SILGen now shares basic blocks for switch cases that contain multiple
patterns. That BB takes incoming arguments from each applicable pattern match
emission with the specific var decls for the pattern that matched.
Added tests for all three of these, and some simple IDE completion
sanity tests.
This tweet: https://twitter.com/radexp/status/694561060230184960 pointed out
the sad truth that most people don't know that stmt-condition can contain
(including a fixit) when they try to use && instead of commas between clauses.
Before:
t.swift:4:16: error: #available may only be used as condition of an 'if', 'guard' or 'while' statement
if x == y && #available(iOS 9, *) { }
^
t.swift:5:27: error: expected '{' after 'if' condition
if #available(iOS 9, *) && x == y {}
^
t.swift:5:37: error: braced block of statements is an unused closure
if #available(iOS 9, *) && x == y {}
^
t.swift:5:37: error: expression resolves to an unused function
if #available(iOS 9, *) && x == y {}
^~
After:
t.swift:4:13: error: expected ',' joining parts of a multi-clause condition
if x == y && #available(iOS 9, *) { }
^~
,
t.swift:5:27: error: expected ',' joining parts of a multi-clause condition
if #available(iOS 9, *) && x == y {}
^~
,
People will keep typing try/catch either due to muscle memory from other languages or
when they are first learning swift. We now produce a nice error message + fixit of:
t.swift:14:3: error: the 'do' keyword is used to specify a 'catch' region
try {
^~~
do
instead of spewing out:
t.swift:15:4: error: consecutive statements on a line must be separated by ';'
} catch { }
^
;
t.swift:15:5: error: expected expression
} catch { }
^
t.swift:15:11: error: braced block of statements is an unused closure
} catch { }
^
t.swift:14:7: error: expression resolves to an unused function
try {
~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
t.swift:15:11: error: expression resolves to an unused function
} catch { }
^~~
t.swift:14:3: warning: no calls to throwing functions occur within 'try' expression
try {
^
Also cleaned up unnecessary body.isNonNull() check here. The code just
above already constructs a synthetic empty brace stmt for the body if
it didn’t have a real one.
Generally speaking, it's necessary to typecheck all parts of a
statement regardless of whether earlier parts failed to typecheck. For
example, even if the condition of an if-statement fails to typecheck, we
should still check its branches. This way all expressions in the AST are
processed (i.e. SequenceExprs translated to trees) and we get more
diagnostics.
The big thing left to fix is for-each statement checking. If there are
any type errors in the pattern or sequence of a for-each statement, the
body doesn't get type-checked.
<rdar://problem/23684220>
Warns of deprecation, checks all the appropriate bits to see if we can
do an automatic fix, and generates fix-its if that is valid.
Also adds a note if the loop looks like it ought to be a simple
for-each, but really isn’t because the loop var is modified inside the
loop.