Skip to content

Commit

Permalink
Enforce @attr uses to always provide a return type (#1782)
Browse files Browse the repository at this point in the history
  • Loading branch information
lgoettgens authored Sep 4, 2024
1 parent 75a8537 commit 025eabc
Show file tree
Hide file tree
Showing 3 changed files with 10 additions and 20 deletions.
15 changes: 2 additions & 13 deletions src/Attributes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ end


"""
@attr [RetType] funcdef
@attr RetType funcdef
This macro is applied to the definition of a unary function, and enables
caching ("memoization") of its return values based on the argument. This
Expand Down Expand Up @@ -323,22 +323,11 @@ julia> myattr(obj) # second time uses the cached result
```
"""
macro attr(ex1, exs...)
if length(exs) == 0
rettype = Any
expr = ex1
elseif length(exs) == 1
rettype = ex1
expr = exs[1]
else
throw(ArgumentError("too many macro arguments"))
end
macro attr(rettype, expr::Expr)
d = MacroTools.splitdef(expr)
length(d[:args]) == 1 || throw(ArgumentError("Only unary functions are supported"))
length(d[:kwargs]) == 0 || throw(ArgumentError("Keyword arguments are not supported"))

# TODO: handle optional ::RetType

# store the original function name
name = d[:name]

Expand Down
3 changes: 2 additions & 1 deletion src/Deprecations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ import .Generic: set_exponent_vector!; @deprecate set_exponent_vector!(a::Generi
import .Generic: is_gen; @deprecate is_gen(x::Generic.MPoly{T}, ::Type{Val{ord}}) where {T <: RingElement, ord} is_gen(x, Val(ord))
import .Generic: degree; @deprecate degree(f::Generic.MPoly{T}, i::Int, ::Type{Val{ord}}) where {T <: RingElement, ord} degree(f, i, Val(ord))

# deprecated during 0.42.*
# will become deprecated in 0.43.0
change_base_ring(p::MPolyRingElem{T}, g, new_polynomial_ring) where {T<:RingElement} = map_coefficients(g, p, parent = new_polynomial_ring)
mulmod(a::S, b::S, mod::Vector{S}) where {S <: MPolyRingElem} = Base.divrem(a * b, mod)[2]
var"@attr"(__source__::LineNumberNode, __module__::Base.Module, expr::Expr) = var"@attr"(__source__, __module__, :Any, expr) # delegate `@attr functionexpression` to `@attr Any functionexpression` (macros are just functions with this weird extra syntax)
12 changes: 6 additions & 6 deletions test/Attributes-test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,8 @@ A cached attribute.
"""
@attr Tuple{T,DataType,Vector{Any}} cached_attr(obj::T) where T = (obj,T,[])

# cached attribute without return type specification
@attr cached_attr2(obj::T) where T = (obj,T,[])
# cached attribute with bad return type specification
@attr Any cached_attr2(obj::T) where T = (obj,T,[])

# cached attribute with return type specification depending on the input type
my_derived_type(::Type{Tmp.Container{T}}) where T = T
Expand All @@ -201,7 +201,7 @@ my_derived_type(::Type{Tmp.Container{T}}) where T = T
@test cached_attr(x) == y
@test cached_attr(x) === y

# check cached without type specification is not inferring return types correctly
# check cached with bad type specification is not inferring return types correctly
@test_throws ErrorException @inferred cached_attr2(x)

# check when return type is derived via a function from input type
Expand All @@ -225,16 +225,16 @@ my_derived_type(::Type{Tmp.Container{T}}) where T = T
@test functionloc(uncached_attr)[2] < functionloc(cached_attr)[2]
end

if VERSION >= v"1.7"
@static if VERSION >= v"1.7"
# the following tests need the improved `@macroexpand` from Julia 1.7
@testset "@attr error handling" begin
# wrong number of arguments
@test_throws ArgumentError @macroexpand @attr foo() = 1
@test_throws ArgumentError @macroexpand @attr foo(x::Int, y::Int) = 1
@test_throws ArgumentError @macroexpand @attr Int foo() = 1
@test_throws ArgumentError @macroexpand @attr Int foo(x::Int, y::Int) = 1
@test_throws ArgumentError @macroexpand @attr Int foo(x::Int) = 1 Any
@test_throws ArgumentError @macroexpand @attr Int Int Int
@test_throws MethodError @macroexpand @attr Int foo(x::Int) = 1 Any
@test_throws MethodError @macroexpand @attr Int Int Int

# wrong kind of arguments
#@test_throws ArgumentError @macroexpand @attr Int Int
Expand Down

0 comments on commit 025eabc

Please sign in to comment.