@@ -337,20 +337,24 @@ end
337
337
338
338
"""
339
339
@pure ex
340
- @pure(ex)
341
340
342
341
`@pure` gives the compiler a hint for the definition of a pure function,
343
342
helping for type inference.
344
343
345
- This macro is intended for internal compiler use and may be subject to changes.
344
+ !!! warning
345
+ This macro is intended for internal compiler use and may be subject to changes.
346
+
347
+ !!! warning
348
+ In Julia 1.8 and higher, it is favorable to use [`@assume_effects`](@ref) instead of `@pure`.
349
+ This is because `@assume_effects` allows a finer grained control over Julia's purity
350
+ modeling and the effect system enables a wider range of optimizations.
346
351
"""
347
352
macro pure (ex)
348
353
esc (isa (ex, Expr) ? pushmeta! (ex, :pure ) : ex)
349
354
end
350
355
351
356
"""
352
357
@constprop setting ex
353
- @constprop(setting, ex)
354
358
355
359
`@constprop` controls the mode of interprocedural constant propagation for the
356
360
annotated function. Two `setting`s are supported:
@@ -373,11 +377,35 @@ end
373
377
374
378
"""
375
379
@assume_effects setting... ex
376
- @assume_effects(setting..., ex)
377
380
378
381
`@assume_effects` overrides the compiler's effect modeling for the given method.
379
382
`ex` must be a method definition or `@ccall` expression.
380
383
384
+ ```jldoctest
385
+ julia> Base.@assume_effects :terminates_locally function pow(x)
386
+ # this :terminates_locally allows `pow` to be constant-folded
387
+ res = 1
388
+ 1 < x < 20 || error("bad pow")
389
+ while x > 1
390
+ res *= x
391
+ x -= 1
392
+ end
393
+ return res
394
+ end
395
+ pow (generic function with 1 method)
396
+
397
+ julia> code_typed() do
398
+ pow(12)
399
+ end
400
+ 1-element Vector{Any}:
401
+ CodeInfo(
402
+ 1 ─ return 479001600
403
+ ) => Int64
404
+
405
+ julia> Base.@assume_effects :total_may_throw @ccall jl_type_intersection(Vector{Int}::Any, Vector{<:Integer}::Any)::Any
406
+ Vector{Int64} (alias for Array{Int64, 1})
407
+ ```
408
+
381
409
!!! warning
382
410
Improper use of this macro causes undefined behavior (including crashes,
383
411
incorrect answers, or other hard to track bugs). Use with care and only if
@@ -512,11 +540,26 @@ This `setting` combines the following other assertions:
512
540
- `:terminates_globally`
513
541
and is a convenient shortcut.
514
542
543
+ ---
544
+ # `:total_may_throw`
545
+
546
+ This `setting` combines the following other assertions:
547
+ - `:consistent`
548
+ - `:effect_free`
549
+ - `:terminates_globally`
550
+ and is a convenient shortcut.
551
+
515
552
!!! note
516
- `@assume_effects :total` is similar to `@Base.pure` with the primary
553
+ This setting is particularly useful since it allows the compiler to evaluate a call of
554
+ the applied method when all the call arguments are fully known to be constant, no matter
555
+ if the call results in an error or not.
556
+
557
+ `@assume_effects :total_may_throw` is similar to [`@pure`](@ref) with the primary
517
558
distinction that the `:consistent`-cy requirement applies world-age wise rather
518
559
than globally as described above. However, in particular, a method annotated
519
- `@Base.pure` is always `:total`.
560
+ `@pure` should always be `:total` or `:total_may_throw`.
561
+ Another advantage is that effects introduced by `@assume_effects` are propagated to
562
+ callers interprocedurally while a purity defined by `@pure` is not.
520
563
"""
521
564
macro assume_effects (args... )
522
565
(consistent, effect_free, nothrow, terminates_globally, terminates_locally) =
@@ -537,12 +580,14 @@ macro assume_effects(args...)
537
580
terminates_locally = true
538
581
elseif setting === :total
539
582
consistent = effect_free = nothrow = terminates_globally = true
583
+ elseif setting === :total_may_throw
584
+ consistent = effect_free = terminates_globally = true
540
585
else
541
586
throw (ArgumentError (" @assume_effects $setting not supported" ))
542
587
end
543
588
end
544
589
ex = args[end ]
545
- isa (ex, Expr) || throw (ArgumentError (" Bad expression `$ex ` in @constprop [settings] ex" ))
590
+ isa (ex, Expr) || throw (ArgumentError (" Bad expression `$ex ` in `@assume_effects [settings] ex` " ))
546
591
if ex. head === :macrocall && ex. args[1 ] == Symbol (" @ccall" )
547
592
ex. args[1 ] = GlobalRef (Base, Symbol (" @ccall_effects" ))
548
593
insert! (ex. args, 3 , Core. Compiler. encode_effects_override (Core. Compiler. EffectsOverride (
725
770
726
771
"""
727
772
@generated f
728
- @generated(f)
773
+
729
774
`@generated` is used to annotate a function which will be generated.
730
775
In the body of the generated function, only types of arguments can be read
731
776
(not the values). The function returns a quoted expression evaluated when the
0 commit comments