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.
'fileprivate' is considered a broader level of access than 'private',
but for now both of them are still available to the entire file. This
is intended as a migration aid.
One interesting fallout of the "access scope" model described in
758cf64 is that something declared 'private' at file scope is actually
treated as 'fileprivate' for diagnostic purposes. This is something
we can fix later, once the full model is in place. (It's not really
/wrong/ in that they have identical behavior, but diagnostics still
shouldn't refer to a type explicitly declared 'private' as
'fileprivate'.)
As a note, ValueDecl::getEffectiveAccess will always return 'FilePrivate'
rather than 'Private'; for purposes of optimization and code generation,
we should never try to distinguish these two cases.
This should have essentially no effect on code that's /not/ using
'fileprivate' other than altered diagnostics.
Progress on SE-0025 ('fileprivate' and 'private')
pattern matches. In the case of an 'if let' with an explicit type, produce a
Taylor'd diagnostic that rewrites the condition to the right type.
This wraps up:
<rdar://problem/27457457> [Type checker] Diagnose unsavory optional injections
common standard library operators. This is progress towards:
<rdar://problem/27457457> [Type checker] Diagnose unsavory optional injections
but there is more work to be done here.
change includes both the necessary protocol updates and the deprecation
warnings
suitable for migration. A future patch will remove the renamings and
make this
a hard error.
Fix-it suggests normal argument expression, instead of of enclosing whole
expression with parens.
* Moved diagnostic logic to Sema, because we have to add correct argument
label for the closure.
if arr.starts(with: IDs) { $0.id == $2 } { ... }
~~^
, isEquivalent: )
* We now accept trailing closures for each expressions and right before `where`
clause, as well as closures right before the body.
if let _ = maybeInt { 1 }, someOtherCondition { ... }
~^
( )
for let x in arr.map { $0 * 4 } where x != 0 { ... }
~^
( )
* [Fixit] Add a fixit for converting non-trailing closures to trailing closures.
* [test] Update test to reflect the added note about converting to trailing closures.
Reminded by Ben's last commit of code completion, I noticed that some users
do not use trailing closures when helping migrating their code. To enhance the discoverability
of this feature, this fix helps users to convert non-trailing closures to trailing
closures. To ensure disambiguity after conversion, we check name conflict before adding
the note.
In C++ we can't have nice things. The macro name 'defer' collided with
use of 'defer' in the Tokens.def file and we were already doing horrible
workarounds in a couple of places to allow them to be included into the
same file. So use a less awesome but more robust name (thanks to Joe for
suggesting SWIFT_DEFER).
Incidentally, sort a bunch of #inlcudes.
Due to a modeling error in the type checker's folding of type
references into type expressions, code such as "strideof(Int)" would
be accepted without the required ".self". Commit
4a60b6cbf4 fixes the modeling issue but
left the historical accepts-invalid; now, diagnose these cases with a
warning + Fix-It to ease the transition.
Fixes SR-899.
Whenever we have a call, retrieve the argument labels from the
argument structurally and associate them with the callee. We were
previously doing this as a separate AST walk (which was unnecessary),
so fold that into constraint generation for a CallExpr.
This is a slightly-pared-back version of
3753d779bc that isn't so rigid in its
interpretation of ASTs. I'll tighten up the semantics over time.
TypeExpr formation from expressions is eager, and was pulling in the
parentheses used to form a call argument, e.g.,
strideof(Int)
would end up being a CallExpr whose argument was a TypeExpr containing
the type "(Int)". This had the side effect of not requiring ".self"
where it should (as reported in SR-899), e.g., the correct code for
the above would be:
strideof(Int.self)
Don't pull the parentheses of a call argument into the TypeExpr, so we
get a more sane AST. This would fix SR-899, but because SE-0090 is in
limbo right now, we don't actually want to require the initial code to
be considered well-formed right now. Therefore, put a hack into the
checking for ".self" that ignores this specific case.
Whenever we have a call, retrieve the argument labels from the
argument structurally and associate them with the callee. We were
previously doing this as a separate AST walk (which was unnecessary),
so fold that into constraint generation for a CallExpr. We were also
allowing weird ASTs to effectively disable this information: tighten
that up and require that CallExprs always have a ParenExpr, TupleExpr,
or (as a temporary hack) a TypeExpr whose representation is a
TupleTypeRepr as their argument prior to type checking. This gives us
a more sane AST to work with, and guarantees that we aren't losing
label information.
From the user perspective, this should be NFC, because it's mostly AST
cleanup and staging.
This is the protocol version of 7bfdd4a2: if a protocol requirement
has a newly-bridged type (say, 'URL' instead of 'NSURL'), then any
conforming types will need to update their implementations of the
requirement. Reuse the override-checking mechanism to do so when
we're reasonably confident about it.
This slots the checking into the existing protocol diagnostics, which
doesn't result in the best user experience.
note: protocol requires property 'prop' with type 'Refrigerator?'
var prop: Refrigerator? { get }
^
note: candidate has non-matching type 'APPRefrigerator?'
var prop: APPRefrigerator? {
^ ~~~~~~~~~~~~~~~~
Refrigerator?
But we can come back and improve that later; right now this is better
than nothing.
rdar://problem/26237030
With the introduction of near-miss checking for optional @objc
protocol requirements, the omit-needless-words logic within the type
checker started being applied to arbitrary declarations that might not
have been type-checked, leading to crashes in various multi-file
scenarios that I wasn't able to reduce down to a sensible test
case. Make sure these declarations get type-checked, fixing
rdar://problem/26413181.
...or renaming to operators, unless we're sure the original thing was
an operator expression. There are just a lot of ways this can be
screwed up.
(Some cases of this can certainly be implemented. I may file a
StarterBug later.)
Fixes 797260939 to not crash when all argument labels match except
for the missing label of a trailing closure. (This is specifically
for the fix-it generated for calling an unavailable-and-renamed API,
not for just getting the argument labels wrong in a normal call.)
rdar://problem/26234493
When we see a string literal used to initializer a Selector, and that
string literal names the selector for the getter or setter of an
Objective-C property, suggest #selector(getter: ...) or
This completes SE-0064. Big thanks for Alex Hoppen (@ahoppen) for his
contributions here.
This was easy with a bit of refactoring, but eventually I'd love to
converge override checking and witness checking logic a bit more.
Fixes <rdar://26183366>.
This is the second half of the previous commit. The most common case
of this will be due to the new rules for imported Objective-C API,
but it will also catch things like "I forgot to make the first
parameter not have an argument label".
When attempting to compile Swift 2 code (or any Swift code using the
Swift 2 names) in Swift 3, the compiler diagnostics are often entirely
useless because the names have changed radically enough that one
generally gets "no member named 'foo'" errors rather than a helpful
"'foo' was renamed to 'bar'" error. This makes for a very poor user
experience when (e.g.) trying to move Swift 2 code forward to Swift 3.
To improve the experience, when the Swift 2 and Swift 3 names of an
API differ, the Clang importer will produce a "stub" declaration that
matches the Swift 2 API. That stub will be marked with a synthesized
attribute
@available(unavailable, renamed: "the-swift-3-name")
that enables better diagnostics (e.g., "'foo' is unavailable: renamed
to 'bar') along with Fix-Its (courtesy of @jrose-apple's recent work)
that fix the Swift 2 code to compile in Swift 3.
This change addresses much of rdar://problem/25309323 (concerning QoI
of Swift 2 code compiled with a Swift 3 compiler), but some cleanup
remains.
We don't want to show the funny "getter:Foo.bar(self:)" syntax to
developers, so whenever possible be a little more explicit.
'foo' has been replaced by 'X.newFoo'
'bar(x:)' has been replaced by property 'X.bar'
'baz(x:y:)' has been replaced by instance method 'X.baz(y:)'
(We do run up against the limitation of a string -- this diagnostic
does not do any lookup to find out if the resulting decl actually exists.)
Example:
@available(*, unavailable, renamed: "setter:CGRect.diagonal(self:_:)")
func scale(_ rect: inout CGRect, toDiagonalLength length: CGFloat)
(My examples are getting more and more contrived, but there you go.)
This is pretty much the same as the getter handling, except that we also
want to strip off the '&' at the call site.
While I'm at it, prefer deleting trailing commas and space to leading
commas and space when removing an argument. That's a little more
aesthetically pleasing. We still have to delete a preceding comma if
it's the last argument that's being removed.
Example:
@available(*, unavailable, renamed: "getter:UIColor.CIColor(self:)")
func convertToCIColor(_ color: UIColor) -> CIColor
This syntax looks weird, but it's the same as what's used by
NS_SWIFT_NAME. I intend to improve the diagnostic text once I have
all the fix-its working.
Next up: setters!
Example:
@available(*, unavailable, renamed: "Sequence.enumerated(self:)")
func enumerate<Seq: SequenceType>(_ sequence: Seq) ->
EnumerateSequence<Seq>
This will allow us to reuse this logic to suggest fixes for APIs
turned into members by NS_SWIFT_NAME.