Code like that is usually indicative of programmer error, and does not
round-trip through module interface files since there is no source
syntax to refer to an outer generic parameter.
For source compatibility this is a warning, but becomes an error with
-swift-version 6.
Fixes rdar://problem/108385980 and https://github.com/apple/swift/issues/62767.
Override checking checks if the derived declaration's generic
signature is compatible with the base, but it does this after
doing a bunch of other checks which feed potentially invalid
type parameters to generic signature queries.
Now that the requirement machine is stricter about this kind
of this, re-organize some code to get around this.
Unfortunately this regresses a diagnostic, because we reject
candidates with mismatched generic requirements earlier in
the process.
AbstractGenericSignatureRequest tries to minimize the number of GSBs that we
spin up by only creating a GSB if the generic parameter and requirement types
are canonical. If they're not canonical, it first canonicalizes them, then
kicks off a request to compute the canonical signature, and finally, re-applies
type sugar.
We would do this by building a mapping for re-sugaring generic parameters,
however this mapping was only populated for the newly-added generic parameters.
If some of the newly-added generic requirements mention the base signature's
generic parameters, they would remain canonicalized.
Fixes <rdar://problem/67579220>.
* [Diagnostics] Update 'does not override' diagnostic message to include protocol context as well
* [Sema] Check whether the override context is a class or a protocol for diagnostic purposes
* [Test] Update tests with new diagnostic message for overrides in protocol context
* [Sema] Adjust diagnostic for overrides in structs and enums to use the existing 'override_nonclass_decl' diagnostic
When a method in an extension of a class looks like an
override of a method from the base class, we emit a
diagnostic.
However due to a bug we used to skip this diagnostic for
certain members of constrained extensions.
Indeed it feels like we should not be doing this check
at all for members of constrained extensions, so lets
explicitly skip it, fixing a source compatibility problem
that was introduced when the unrelated bug was fixed.
Fixes <rdar://problem/57029805>, <https://bugs.swift.org/browse/SR-11740>.
This makes diagnostics more verbose and accurate, because
it's possible to distinguish how many parameters there are
based on the message itself.
Also there are multiple diagnostic messages in a format of
`<descriptive-kind> <decl-name> ...` that get printed as
e.g. `subscript 'subscript'` if empty labels are omitted.
Stop creating ImplicitlyUnwrappedOptional<T> so that we can remove it
from the type system.
Enable the code that generates disjunctions for Optional<T> and
rewrites expressions based on the original declared type being 'T!'.
Most of the changes supporting this were previously merged to master,
but some things were difficult to merge to master without actually
removing IUOs from the type system:
- Dynamic member lookup and dynamic subscripting
- Changes to ensure the bridging peephole still works
Past commits have attempted to retain as much fidelity with how we
were printing things as possible. There are some cases where we still
are not printing things the same way:
- In diagnostics we will print '?' rather than '!'
- Some SourceKit and Code Completion output where we print a Type
rather than Decl.
Things like module printing via swift-ide-test attempt to print '!'
any place that we now have Optional types that were declared as IUOs.
There are some diagnostics regressions related to the fact that we can
no longer "look through" IUOs. For the same reason some output and
functionality changes in Code Completion. I have an idea of how we can
restore these, and have opened a bug to investigate doing so.
There are some small source compatibility breaks that result from
this change:
- Results of dynamic lookup that are themselves declared IUO can in
rare circumstances be inferred differently. This shows up in
test/ClangImporter/objc_parse.swift, where we have
var optStr = obj.nsstringProperty
Rather than inferring optStr to be 'String!?', we now infer this to
be 'String??', which is in line with the expectations of SE-0054.
The fact that we were only inferring the outermost IUO to be an
Optional in Swift 4 was a result of the incomplete implementation of
SE-0054 as opposed to a particular design. This should rarely cause
problems since in the common-case of actually using the property rather
than just assigning it to a value with inferred type, we will behave
the same way.
- Overloading functions with inout parameters strictly by a difference
in optionality (i.e. Optional<T> vs. ImplicitlyUnwrappedOptional<T>)
will result in an error rather than the diagnostic that was added
in Swift 4.1.
- Any place where '!' was being used where it wasn't supposed to be
allowed by SE-0054 will now treat the '!' as if it were '?'.
Swift 4.1 generates warnings for these saying that putting '!'
in that location is deprecated. These locations include for example
typealiases or any place where '!' is nested in another type like
`Int!?` or `[Int!]`.
This commit effectively means ImplicitlyUnwrappedOptional<T> is no
longer part of the type system, although I haven't actually removed
all of the code dealing with it yet.
ImplicitlyUnwrappedOptional<T> is is dead, long live implicitly
unwrapped Optional<T>!
Resolves rdar://problem/33272674.
The Swift class model does not support overriding declarations where either
the overridden declaration or the overriding declaration are in an extension.
However, the Objective-C class model does, so marking the declaration as
@objc (when possible) will work around the limitation.
Customize the "cannot override declaration in extension" diagnostic to
suggest adding @objc to the overridden declaration in cases where
@objc is permitted. Fixes SR-6512 / rdar://problem/35787914.
Previous versions of Swift accidentally treated lazy properties as
computed properties because of how they were implemented. Now that we
check this correctly, we've broken source compatibility. Downgrade the
error to a warning in this case.
(Arguably we could /allow/ overriding with a stored property. The
original concerns were that you could accidentally end up with extra
storage you didn't need, and that observing accessors would behave
differently based on whether or not the property was overriding. But
there's at least no ambiguity for 'lazy', which can't have observing
accessors today.)
rdar://problem/35870371
Introduce a warning about redeclaring the associated types from an
inherited protocol in the protocol being checked:
* If the new declaration is an associated type, note that the
declaration could be replaced by requirements in the protocol's
where clause.
* If the new declaration is a typealias, note that it could be
replaced by a same-type constraint in the protocol's where clause.
Type::subst() does stupid things if you give it a
GenericFunctionType, attempting to build a new "substituted"
GenericSignature by hand.
As the newly-added test case demonstrates, this can trigger
assertions, and the callers of adjustSuperclassMemberDeclType()
didn't care about the generic signature anyway, so strip it off
first.
Soon, I want to have Type::subst() assert if it encounters a
GenericFunctionType, and remove all the junk there altogether,
but there's more work to be done first.
Progress on <rdar://problem/30817732> (RxCocoa build failures on
master), but now it hits further regressions.
- If a parameter type is a sugared function type, mark the type
as non-escaping by default. Previously, we were only doing this
if the parameter type was written as a function type, with no
additional sugar.
This means in the following cases, the function parameter type
is now non-escaping:
func foo(f: ((Int) -> Void))
typealias Fn = (Int) -> Void
func foo(f: Fn)
- Also, allow @escaping to be used in the above cases:
func foo(f: @escaping ((Int) -> Void))
typealias Fn = (Int) -> Void
func foo(f: @escaping Fn)
- Diagnose usages of @escaping in inappropriate locations, instead
of just ignoring them.
It is unfortunate that sometimes we end up desugaring the typealias,
but currently there are other cases where this occurs too, such as
qualified lookpu of protocol typealiases with a concrete base
type, and generic type aliases. A more general representation for
sugared types (such as an AttributedType sugared type) would allow
us to solve this in a more satisfactory manner in the future.
However at the very least this patch factors out the common code
paths and adds comments, so it shouldn't be too bad going forward.
Note that this is a source-breaking change, both because @escaping
might need to be added to parameters with a sugared function type,
and @escaping might be removed if it appears somewhere where we
do not mark function types as non-escaping by default.
This flips the switch to have @noescape be the default semantics for
function types in argument positions, for everything except property
setters. Property setters are naturally escaping, so they keep their
escaping-by-default behavior.
Adds contentual printing, and updates the test cases.
There is some further (non-source-breaking) work to be done for
SE-0103:
- We need the withoutActuallyEscaping function
- Improve diagnostics and QoI to at least @noescape's standards
- Deprecate / drop @noescape, right now we allow it
- Update internal code completion printing to be contextual
- Add more tests to explore tricky corner cases
- Small regressions in fixits in attr/attr_availability.swift
This at least emits notes when someone overrides something but
gets the types a little wrong (more than just mismatched optionals,
as handled in d669d152).
Part of rdar://problem/26183575
In the case of an invalid override of an init, mark the override invalid, not the
init. This way, code that uses the init can be parsed and analyzed correctly and
bogus downstream errors are reduced.
Before:
t.swift:2:12: error: initializer does not override a designated initializer from its superclass
override init() {}
~~~~~~~~ ^
t.swift:5:1: error: cannot invoke initializer for type 'C' with no arguments
C()
^
t.swift:6:1: error: 'B' cannot be constructed because it has no accessible initializers
B()
^
After:
t.swift:2:12: error: initializer does not override a designated initializer from its superclass
override init() {}
~~~~~~~~ ^