Skip to content

Commit

Permalink
elaborate the @nospecialize docstring a bit
Browse files Browse the repository at this point in the history
Adapted from #41931.
  • Loading branch information
aviatesk committed Apr 11, 2022
1 parent 0deb326 commit 2fa3edc
Showing 1 changed file with 37 additions and 5 deletions.
42 changes: 37 additions & 5 deletions base/essentials.jl
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,12 @@ end
@nospecialize
Applied to a function argument name, hints to the compiler that the method
should not be specialized for different types of that argument,
but instead to use precisely the declared type for each argument.
This is only a hint for avoiding excess code generation.
Can be applied to an argument within a formal argument list,
implementation should not be specialized for different types of that argument,
but instead use the declared type for that argument.
It can be applied to an argument within a formal argument list,
or in the function body.
When applied to an argument, the macro must wrap the entire argument expression.
When applied to an argument, the macro must wrap the entire argument expression, e.g.,
`@nospecialize(x::Real)` or `@nospecialize(i::Integer...)` rather than wrapping just the argument name.
When used in a function body, the macro must occur in statement position and
before any code.
Expand Down Expand Up @@ -87,6 +87,38 @@ end
f(y) = [x for x in y]
@specialize
```
!!! note
`@nospecialize` affects code generation but not inference: it limits the diversity
of the resulting native code, but it does not impose any limitations (beyond the
standard ones) on type-inference.
# Example
```julia
julia> f(A::AbstractArray) = g(A)
f (generic function with 1 method)
julia> @noinline g(@nospecialize(A::AbstractArray)) = A[1]
g (generic function with 1 method)
julia> @code_typed f([1.0])
CodeInfo(
1 ─ %1 = invoke Main.g(_2::AbstractArray)::Float64
└── return %1
) => Float64
```
Here, the `@nospecialize` annotation results in the equivalent of
```julia
f(A::AbstractArray) = invoke(g, Tuple{AbstractArray}, A)
```
ensuring that only one version of native code will be generated for `g`,
one that is generic for any `AbstractArray`.
However, the specific return type is still inferred for both `g` and `f`,
and this is still used in optimizing the callers of `f` and `g`.
"""
macro nospecialize(vars...)
if nfields(vars) === 1
Expand Down

0 comments on commit 2fa3edc

Please sign in to comment.