Skip to content

Commit 2fa3edc

Browse files
committed
elaborate the @nospecialize docstring a bit
Adapted from #41931.
1 parent 0deb326 commit 2fa3edc

File tree

1 file changed

+37
-5
lines changed

1 file changed

+37
-5
lines changed

base/essentials.jl

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,12 @@ end
5454
@nospecialize
5555
5656
Applied to a function argument name, hints to the compiler that the method
57-
should not be specialized for different types of that argument,
58-
but instead to use precisely the declared type for each argument.
59-
This is only a hint for avoiding excess code generation.
60-
Can be applied to an argument within a formal argument list,
57+
implementation should not be specialized for different types of that argument,
58+
but instead use the declared type for that argument.
59+
It can be applied to an argument within a formal argument list,
6160
or in the function body.
62-
When applied to an argument, the macro must wrap the entire argument expression.
61+
When applied to an argument, the macro must wrap the entire argument expression, e.g.,
62+
`@nospecialize(x::Real)` or `@nospecialize(i::Integer...)` rather than wrapping just the argument name.
6363
When used in a function body, the macro must occur in statement position and
6464
before any code.
6565
@@ -87,6 +87,38 @@ end
8787
f(y) = [x for x in y]
8888
@specialize
8989
```
90+
91+
!!! note
92+
`@nospecialize` affects code generation but not inference: it limits the diversity
93+
of the resulting native code, but it does not impose any limitations (beyond the
94+
standard ones) on type-inference.
95+
96+
# Example
97+
98+
```julia
99+
julia> f(A::AbstractArray) = g(A)
100+
f (generic function with 1 method)
101+
102+
julia> @noinline g(@nospecialize(A::AbstractArray)) = A[1]
103+
g (generic function with 1 method)
104+
105+
julia> @code_typed f([1.0])
106+
CodeInfo(
107+
1 ─ %1 = invoke Main.g(_2::AbstractArray)::Float64
108+
└── return %1
109+
) => Float64
110+
```
111+
112+
Here, the `@nospecialize` annotation results in the equivalent of
113+
114+
```julia
115+
f(A::AbstractArray) = invoke(g, Tuple{AbstractArray}, A)
116+
```
117+
118+
ensuring that only one version of native code will be generated for `g`,
119+
one that is generic for any `AbstractArray`.
120+
However, the specific return type is still inferred for both `g` and `f`,
121+
and this is still used in optimizing the callers of `f` and `g`.
90122
"""
91123
macro nospecialize(vars...)
92124
if nfields(vars) === 1

0 commit comments

Comments
 (0)