diff --git a/base/compiler/effects.jl b/base/compiler/effects.jl index ace47df9153ef..ec64b7601bc76 100644 --- a/base/compiler/effects.jl +++ b/base/compiler/effects.jl @@ -54,6 +54,37 @@ analyzed method (see the implementation of `merge_effects!`). Each effect proper initialized with `ALWAYS_TRUE`/`true` and then transitioned towards `ALWAYS_FALSE`/`false`. Note that within the current flow-insensitive analysis design, effects detected by local analysis on each statement usually taint the global conclusion conservatively. + +## Key for `show` output of Effects: + +The output represents the state of different effect properties in the following order: + +1. `consistent` (`c`): + - `+c` (green): `ALWAYS_TRUE` + - `-c` (red): `ALWAYS_FALSE` + - `?c` (yellow): `CONSISTENT_IF_NOTRETURNED` and/or `CONSISTENT_IF_INACCESSIBLEMEMONLY` +2. `effect_free` (`e`): + - `+e` (green): `ALWAYS_TRUE` + - `-e` (red): `ALWAYS_FALSE` + - `?e` (yellow): `EFFECT_FREE_IF_INACCESSIBLEMEMONLY` +3. `nothrow` (`n`): + - `+n` (green): `true` + - `-n` (red): `false` +4. `terminates` (`t`): + - `+t` (green): `true` + - `-t` (red): `false` +5. `notaskstate` (`s`): + - `+s` (green): `true` + - `-s` (red): `false` +6. `inaccessiblememonly` (`m`): + - `+m` (green): `ALWAYS_TRUE` + - `-m` (red): `ALWAYS_FALSE` + - `?m` (yellow): `INACCESSIBLEMEM_OR_ARGMEMONLY` +7. `noinbounds` (`i`): + - `+i` (green): `true` + - `-i` (red): `false` + +Additionally, if the `nonoverlayed` property is false, a red prime symbol (′) is displayed after the tuple. """ struct Effects consistent::UInt8 diff --git a/base/reflection.jl b/base/reflection.jl index a3e98e11a5f04..197742318bb4b 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -1525,6 +1525,42 @@ function return_types(@nospecialize(f), @nospecialize(types=default_tt(f)); return rts end +""" + infer_effects(f, types=default_tt(f); world=get_world_counter(), interp=Core.Compiler.NativeInterpreter(world)) + +Compute the `Effects` of a function `f` with argument types `types`. The `Effects` represents the computational effects of the function call, such as whether it is free of side effects, guaranteed not to throw an exception, guaranteed to terminate, etc. The `world` and `interp` arguments specify the world counter and the native interpreter to use for the analysis. + +# Arguments +- `f`: The function to analyze. +- `types` (optional): The argument types of the function. Defaults to the default tuple type of `f`. +- `world` (optional): The world counter to use for the analysis. Defaults to the current world counter. +- `interp` (optional): The native interpreter to use for the analysis. Defaults to a new `Core.Compiler.NativeInterpreter` with the specified `world`. + +# Returns +- `effects::Effects`: The computed effects of the function call. + +# Example + +```julia +julia> function foo(x) + y = x * 2 + return y + end; + +julia> effects = Base.infer_effects(foo, (Int,)) +(+c,+e,+n,+t,+s,+m,+i) +``` + +This function will return an `Effects` object with information about the computational effects of the function `foo` when called with an `Int` argument. See the documentation for `Effects` for more information on the various effect properties. + +!!! warning + The `infer_effects` function should not be used from generated functions; + doing so will result in an error. + +# See Also +- [`Core.Compiler.Effects`](@ref): A type representing the computational effects of a method call. +- [`Base.@assume_effects`](@ref): A macro for making assumptions about the effects of a method. +""" function infer_effects(@nospecialize(f), @nospecialize(types=default_tt(f)); world = get_world_counter(), interp = Core.Compiler.NativeInterpreter(world))