Reference
Macros
DispatchDoctor._Macros.@stable — Macro@stable [options...] [code_block]A macro to enforce type stability in functions. When applied, it ensures that the return type of the function is concrete. If type instability is detected, a TypeInstabilityError is thrown.
Options
default_mode::String="error":- Change the default mode from
"error"to"warn"to only emit a warning, or"disable"to disable type instability checks by default. - To locally or globally override the mode for a package that uses DispatchDoctor, you can use the
"dispatch_doctor_mode"key in your LocalPreferences.toml (typically configured with Preferences.jl).
- Change the default mode from
default_codegen_level::String="debug":- Set the code generation level to
"min"to only generate a single function body for each stabilized function. The default,"debug", generates an entire duplicate function so that@code_warntypecan be used. - To locally or globally override the code generation level for a package that uses DispatchDoctor, you can use the
"dispatch_doctor_codegen_level"key in your LocalPreferences.toml.
- Set the code generation level to
default_union_limit::Int=1:- Sets the maximum elements in a union to be considered stable. The default is
1, meaning that all unions are considered unstable. A value of2would indicate thatUnion{Float32,Float64}is considered stable, butUnion{Float16,Float32,Float64}is not. - To locally or globally override the union limit for a package that uses DispatchDoctor, you can use the
"dispatch_doctor_union_limit"key in your LocalPreferences.toml.
- Sets the maximum elements in a union to be considered stable. The default is
Example
using DispatchDoctor: @stable
@stable function relu(x)
if x > 0
return x
else
return 0.0
end
endwhich will automatically flag any type instability:
julia> relu(1.0)
1.0
julia> relu(0)
ERROR: TypeInstabilityError: Instability detected in function `relu`
with arguments `(Int64,)`. Inferred to be `Union{Float64, Int64}`,
which is not a concrete type.Extended help
You may also apply @stable to arbitrary blocks of code, such as begin or module, and have it be applied to all functions. (Just note that this skips closure functions.)
using DispatchDoctor: @stable
@stable begin
f(x) = x
g(x) = x > 0 ? x : 0.0
@unstable begin
g(x::Int) = x > 0 ? x : 0.0
end
module A
h(x) = x
include("myfile.jl")
end
endThis @stable will apply to f, g, h, as well as all functions within myfile.jl. It skips the definition g(x::Int), meaning that when Int input is provided to g, type instability is not detected.
DispatchDoctor._Macros.@unstable — Macro@unstable [code_block]A no-op macro to hide blocks of code from @stable.
Utilities
If you wish to turn off @stable for a single function call, you can use allow_unstable:
DispatchDoctor._RuntimeChecks.allow_unstable — Functionallow_unstable(f::F) where {F<:Function}Globally disable type DispatchDoctor instability checks within the provided function f.
This function allows you to execute a block of code where type instability checks are disabled. It ensures that the checks are re-enabled after the block is executed, even if an error occurs.
This function uses a ReentrantLock and will throw an error if used from two tasks at once.
Usage
allow_unstable() do
# do unstable stuff
endArguments
f::F: A function to be executed with type instability checks disabled.
Returns
- The result of the function
f.
Notes
You cannot call allow_unstable from two tasks at once. An error will be thrown if you try to do so.
@stable will normally interact with macros by propagating them to the function definition as well as the function simulator. If you would like to change this behavior, or declare a macro as being incompatible with @stable, you can use register_macro!:
DispatchDoctor._Interactions.register_macro! — Functionregister_macro!(macro_name::Symbol, behavior::MacroInteractions)Register a macro with a specified behavior in the MACRO_BEHAVIOR list.
This function adds a new macro and its associated behavior to the global list that tracks how macros should be treated when encountered during the stabilization process. The behavior can be one of CompatibleMacro, IncompatibleMacro, or DontPropagateMacro, which influences how the @stable macro interacts with the registered macro.
The default behavior for @stable is to assume CompatibleMacro unless explicitly declared.
Arguments
macro_name::Symbol: The symbol representing the macro to register.behavior::MacroInteractions: The behavior to associate with the macro, which dictates how it should be handled.
Examples
using DispatchDoctor: register_macro!, IncompatibleMacro
register_macro!(Symbol("@mymacro"), IncompatibleMacro)Internals
DispatchDoctor._Utils.type_instability — Functiontype_instability(T::Type)Returns true if this type is not concrete. Will also return false for Union{}, so that errors can propagate.