|
54 | 54 | @nospecialize |
55 | 55 |
|
56 | 56 | 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, |
61 | 60 | 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. |
63 | 63 | When used in a function body, the macro must occur in statement position and |
64 | 64 | before any code. |
65 | 65 |
|
|
87 | 87 | f(y) = [x for x in y] |
88 | 88 | @specialize |
89 | 89 | ``` |
| 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`. |
90 | 122 | """ |
91 | 123 | macro nospecialize(vars...) |
92 | 124 | if nfields(vars) === 1 |
|
0 commit comments