Instead of looking at the requirements before passing them off to
the GSB, let's look at the difference between the final signature
and the original signature.
This makes the checks more accurate, for example we want to
detect that 'E' was specialized in the below:
@_specialize(where S == Set<String>)
public func takesSequenceAndElement<S, E>(_: S, _: E)
where S : Sequence, E == S.Element {}
This attribute allows to define a pre-specialized entry point of a
generic function in a library.
The following definition provides a pre-specialized entry point for
`genericFunc(_:)` for the parameter type `Int` that clients of the
library can call.
```
@_specialize(exported: true, where T == Int)
public func genericFunc<T>(_ t: T) { ... }
```
Pre-specializations of internal `@inlinable` functions are allowed.
```
@usableFromInline
internal struct GenericThing<T> {
@_specialize(exported: true, where T == Int)
@inlinable
internal func genericMethod(_ t: T) {
}
}
```
There is syntax to pre-specialize a method from a different module.
```
import ModuleDefiningGenericFunc
@_specialize(exported: true, target: genericFunc(_:), where T == Double)
func prespecialize_genericFunc(_ t: T) { fatalError("dont call") }
```
Specially marked extensions allow for pre-specialization of internal
methods accross module boundries (respecting `@inlinable` and
`@usableFromInline`).
```
import ModuleDefiningGenericThing
public struct Something {}
@_specializeExtension
extension GenericThing {
@_specialize(exported: true, target: genericMethod(_:), where T == Something)
func prespecialize_genericMethod(_ t: T) { fatalError("dont call") }
}
```
rdar://64993425
The client code doesn't actually call into these specialized functions even
though they have public linkage. This could lead to TBD verification failure
shown in rdar://44777994.
This patch also warns users' codebase when `export: true` is specified.
Within the compiler, we use the term "layout constraint" for any
constraint that affects the layout of a type parameter that has that
constraint. However, the only user-visible constraint is "AnyObject",
and calling that a layout constraint is confusing. Drop the term
"layout" from diagnostics.
Fixes rdar://problem/35295372.
When we see two type(aliase)s with the same name in a protocol
hierarchy, make them equal with an implied same-type requirement. This
detects inconstencies in typealiases across different protocols, and
eliminates the need for ad hoc consistency checking. This is a step
toward simplifying away the need for direct-diagnosis operations
involving concrete type mismatches.
While here, warn when we see an associated type with the same as a
typealias from an inherited protocol; in this case, the associated
type is basically useless, because it's going to be equivalent to the
typealias.
As we've done with layout requirements, introduce a new entry point
(addTypeRequirement) that handles unresolved type requirements of the
form `T: U`, resolves the types, and then can
1. Diagnose any immediate problems with the types,
2. Delay the type requirement if one of the types cannot be resolved,
or
3. Break it into one or more "direct" requirements.
This allows us to clean up and centralize a bunch of checking that was
scattered/duplicated across the GSB and type checker.
This PR addresses TODOs from #8241.
- It supports merging for layout constraints, e.g., if both a _Trivial constraint and a _Trivial(64) constraint appear on a type parameter, we keep only _Trivial(64) as a more specific layout constraint. We do a similar thing for ref-counted/native-ref-counted. The overall idea is to keep the more specific of two compatible layout constraints.
- The presence of a superclass constraint implies a layout constraint, e.g., a superclass constraint implies _Class or _NativeClass
Diagnose redundant same-type constraints using most of the same
machinery for diagnosing other redundant constraints. However,
same-type constraints are particularly interesting because
redundancies can be spelled in a number of different ways. Address
this using the connected components of the subgraph involving only
derived requirements (which is already used for the minimized generic
signature). Then, separate all of the non-derived requirements into
the intracomponent requirements and intercomponent requirements:
* All of the intracomponent requirements are redundant by definition,
because the components are defined by derived constraints.
* For the intercomponent requirements, form a spanning tree among the
various components and diagnose as redundant any edges that do not
extend the spanning tree.
As we've done with all of the other kinds of constraints, keep track
of all of the layout constraints on the equivalence class. Use the
normal mechanism to diagnose conflicts between different layout
constraints, warn about duplicate layout constraints, etc.
Diagnose when a same-type constraint (to a concrete type) is made
redundant by another same-type constraint. Slightly improve the
diagnostic that handles collisions between two same-type constraints.
All of the implementation work to make this possible was completed in
prior commits, so loosen the restriction from "one side must be a type
parameter" or "one side must contain a type parameter".
Rather than using "isEqual" to match same-type constraints among
concrete types, use a full type matched to recursively decompose the
structure. This allows us to support same-type constraints that end up
being of the form X<T> == X<U>, where T and U are type parameters of
some sort.
Fixes rdar://problem/29333056.
Clean up the representation of PotentialArchetype in a few small ways:
* Eliminate the GenericTypeParamType* at the root, and instead just
store a GenericParamKey. That makes the potential archetypes
independent of a particular set of generic parameters.
* Give potential archetypes a link back to their owning
ArchetypeBuilder, so we can get contextual information (etc.) when
needed. We can remove the "builder" arguments as a separate step.
Also, collapse getName()/getDebugName()/getFullName() into
getNestedName() and getDebugName(). Generic parameters don't have
"names" per se, so they should only show up in debug dumps.
In support of the former, clean up some of the diagnostics emitted by
the archetype builder that were using 'Identifier' or 'StringRef'
where they should have been using a 'Type' (i.e., the type behind the
dependent archetype).
This was causing us to emit diagnostics talking about τ_m_n, which is
not helpful.
Now that generic function types print sanely, print them in a few
places where we were previously printing PolymorphicFunctionTypes.
This fixes several issues:
- By default parent types of alias types are not printed which results in
- Erroneous fixits, for example when casting to 'Notification.Name' from a string, which ends up adding erroneous cast
as "Name(rawValue: ...)"
- Hard to understand types in code-completion results and diagnostics
- When printing with 'fully-qualified' option typealias types are printed erroneously like this "<PARENT>.Type.<TYPEALIAS>"
The change make typealias printing same as nominal types and addresses the above.
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 '>'.
This was mistakenly reverted in an attempt to fix buildbots.
Unfortunately it's now smashed into one commit.
---
Introduce @_specialize(<type list>) internal attribute.
This attribute can be attached to generic functions. The attribute's
arguments must be a list of concrete types to be substituted in the
function's generic signature. Any number of specializations may be
associated with a generic function.
This attribute provides a hint to the compiler. At -O, the compiler
will generate the specified specializations and emit calls to the
specialized code in the original generic function guarded by type
checks.
The current attribute is designed to be an internal tool for
performance experimentation. It does not affect the language or
API. This work may be extended in the future to add user-visible
attributes that do provide API guarantees and/or direct dispatch to
specialized code.
This attribute works on any generic function: a freestanding function
with generic type parameters, a nongeneric method declared in a
generic class, a generic method in a nongeneric class or a generic
method in a generic class. A function's generic signature is a
concatenation of the generic context and the function's own generic
type parameters.
e.g.
struct S<T> {
var x: T
@_specialize(Int, Float)
mutating func exchangeSecond<U>(u: U, _ t: T) -> (U, T) {
x = t
return (u, x)
}
}
// Substitutes: <T, U> with <Int, Float> producing:
// S<Int>::exchangeSecond<Float>(u: Float, t: Int) -> (Float, Int)
---
[SILOptimizer] Introduce an eager-specializer pass.
This pass finds generic functions with @_specialized attributes and
generates specialized code for the attribute's concrete types. It
inserts type checks and guarded dispatch at the beginning of the
generic function for each specialization. Since we don't currently
expose this attribute as API and don't specialize vtables and witness
tables yet, the only way to reach the specialized code is by calling
the generic function which performs the guarded dispatch.
In the future, we can build on this work in several ways:
- cross module dispatch directly to specialized code
- dynamic dispatch directly to specialized code
- automated specialization based on less specific hints
- partial specialization
- and so on...
I reorganized and refactored the optimizer's generic utilities to
support direct function specialization as opposed to apply
specialization.
Temporarily reverting @_specialize because stdlib unit tests are
failing on an internal branch during deserialization.
This reverts commit e2c43cfe14, reversing
changes made to 9078011f93.
This attribute can be attached to generic functions. The attribute's
arguments must be a list of concrete types to be substituted in the
function's generic signature. Any number of specializations may be
associated with a generic function.
This attribute provides a hint to the compiler. At -O, the compiler
will generate the specified specializations and emit calls to the
specialized code in the original generic function guarded by type
checks.
The current attribute is designed to be an internal tool for
performance experimentation. It does not affect the language or
API. This work may be extended in the future to add user-visible
attributes that do provide API guarantees and/or direct dispatch to
specialized code.
This attribute works on any generic function: a freestanding function
with generic type parameters, a nongeneric method declared in a
generic class, a generic method in a nongeneric class or a generic
method in a generic class. A function's generic signature is a
concatenation of the generic context and the function's own generic
type parameters.
e.g.
struct S<T> {
var x: T
@_specialize(Int, Float)
mutating func exchangeSecond<U>(u: U, _ t: T) -> (U, T) {
x = t
return (u, x)
}
}
// Substitutes: <T, U> with <Int, Float> producing:
// S<Int>::exchangeSecond<Float>(u: Float, t: Int) -> (Float, Int)