SE-206 deprecated hashValue as a protocol requirement. We should gently encourage people to migrate to hash(into:), for its more secure, easier and faster hashing.
Emit a compiler warning whenever hashValue has an explicit implementation, but hash(into:) doesn’t.
* [AST] Remove stored TypeLoc from TypedPattern
TypedPattern was only using this TypeLoc as a means to a TypeRepr, which
caused it to store the pattern type twice (through the superclass and through
the TypeLoc itself.)
This also fixes a bug where deserializing a TypedPattern doesn't store
the type correctly and generally cleans up TypedPattern initialization.
Resolves rdar://44144435
* Address review comments
Parsed declarations would create an untyped 'self' parameter;
synthesized, imported and deserialized declarations would get a
typed one.
In reality the type, if any, depends completely on the properties
of the function in question, so we can just lazily create the
'self' parameter when needed.
If the function already has a type, we give it a type right there;
otherwise, we check if a 'self' was already created when we
compute a function's type and set the type of 'self' then.
Use the usual bag of tricks to eliminating dependence on the
TypeChecker instance: static functions, LazyResolver callbacks, and
emitting diagnostics on decls/ASTContext.
- getAsDeclOrDeclExtensionContext -> getAsDecl
This is basically the same as a dyn_cast, so it should use a 'getAs'
name like TypeBase does.
- getAsNominalTypeOrNominalTypeExtensionContext -> getSelfNominalTypeDecl
- getAsClassOrClassExtensionContext -> getSelfClassDecl
- getAsEnumOrEnumExtensionContext -> getSelfEnumDecl
- getAsStructOrStructExtensionContext -> getSelfStructDecl
- getAsProtocolOrProtocolExtensionContext -> getSelfProtocolDecl
- getAsTypeOrTypeExtensionContext -> getSelfTypeDecl (private)
These do /not/ return some form of 'this'; instead, they get the
extended types when 'this' is an extension. They started off life with
'is' names, which makes sense, but changed to this at some point. The
names I went with match up with getSelfInterfaceType and
getSelfTypeInContext, even though strictly speaking they're closer to
what getDeclaredInterfaceType does. But it didn't seem right to claim
that an extension "declares" the ClassDecl here.
- getAsProtocolExtensionContext -> getExtendedProtocolDecl
Like the above, this didn't return the ExtensionDecl; it returned its
extended type.
This entire commit is a mechanical change: find-and-replace, followed
by manual reformatted but no code changes.
(or __derived_struct_equals)
We want to make sure that if someone replaces the synthesized
implementation with a handwritten one, it doesn't change the ABI.
The simplest way to do that is to not use this clever workaround.
https://bugs.swift.org/browse/SR-8294
Existing comment references the old way to do the comparison with a
state variable. Updated comment covers how the function works and
matches up the parameter names too.
There are two general constructor forms here:
- One took the number of parameter lists, to be filled in later.
Now, this takes a boolean indicating if there is an implicit
'self'.
- The other one took the actual parameter lists and filled them
in right away. This now takes a separate 'self' ParamDecl and
ParameterList.
Instead of storing the number of parameter lists, an
AbstractFunctionDecl now only needs to store if there is a 'self'
or not.
I've updated most places that construct AbstractFunctionDecls to
properly use these new forms. In the ClangImporter, there is
more code that remains to be untangled, so we continue to build
multiple ParameterLists and unpack them into a ParamDecl and
ParameterList at the last minute.
Because people put all sorts of nonsense into @objc enums (most
reasonably, "private cases", which represent valid values that are not
API), the Swift-synthesized implementation of 'hash(into:)' needs to
not expect a switch statement to be exhaustive. And since
Swift-defined @objc enums are supposed to behave enough like C-defined
enums, they should at least handle simple method calls with an invalid
raw value, which means that 'rawValue' likewise should not use a
switch.
This patch provides alternate implementations that look like this:
extension ImportedEnum {
public var rawValue: Int {
return unsafeBitCast(self, to: Int.self)
}
public func hash(into hasher: inout Hasher) {
hasher.combine(self.rawValue)
}
}
rdar://problem/41913284
Previously, some PBDs weren't being marked implicit even though the associated vars were implicit. PatternBindingDecl::createImplicit will be even nicer when we start parsing the location of the equals token.
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.
Several different places in the codebase synthesize IntegerLiteralExprs from computed unsigned variables; each one requires several lines of code and does things slightly differently. Write one central helper method to handle this.
Introduce some metaprogramming of accessors and generally prepare
for storing less-structured accessor lists.
NFC except for a change to the serialization format.
This works for all protocols except for Decodable on non-final classes, because
the init requirement has to be 'required' and thus in the type's declaration.
Fixes most of https://bugs.swift.org/browse/SR-6803.
Instead of passing around a TypeChecker and three Decls (the nominal type, the
protocol, and the decl declaring the conformance) everywhere, we can just pass
one object.
This should be [NFC].
For enums with no associated values, it is better to move the hasher.combine call out of the switch statement, like this:
func hash(into hasher: inout Hasher) {
let discriminator: Int
switch self {
case a: discriminator = 0
case b: discriminator = 1
case c: discriminator = 2
}
hasher.combine(discriminator)
}
This enables the optimizer to replace the switch statement with a simple integer promotion, restoring earlier behavior.
This removes the default implementation of hash(into:), and replaces it with automatic synthesis built into the compiler. Hashable can now be implemented by defining either hashValue or hash(into:) -- the compiler supplies the missing half automatically, in all cases.
To determine which hash(into:) implementation to generate, the synthesizer resolves hashValue -- if it finds a synthesized definition for it, then the generated hash(into:) body implements hashing from scratch, feeding components into the hasher. Otherwise, the body implements hash(into:) in terms of hashValue.
Since 'private' means "limit to the enclosing scope (and extensions
thereof)", putting it on a member means that the member can't be
accessed everywhere the type might show up. That's normally a good
thing, but it's not the desired effect for synthesized members used
for derived conformances, and when it comes to class initializers this
actually violates AST invariants.
rdar://problem/39478298
This is our first statement attribute, made more complicated by the
fact that a 'case'/'default' isn't really a normal statement. I've
chosen /not/ to implement a general statement attribute logic like we
have for types and decls at this time, but I did get the compiler
parsing arbitrary attributes before 'case' and 'default'. As a bonus,
we now treat all cases within functions as being switch-like rather
than enum-like, which is better for recovery when not in a switch.
This has three principal advantages:
- It gives some additional type-safety when working
with known accessors.
- It makes it significantly easier to test whether a declaration
is an accessor and encourages the use of a common idiom.
- It saves a small amount of memory in both FuncDecl and its
serialized form.