From afc5558a89f78243f5d4e90911dd55180abcd9bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20G=C3=B6ttgens?= Date: Mon, 4 Sep 2023 17:19:39 +0200 Subject: [PATCH 1/2] Piracy fix for kwcall --- src/piracy.jl | 19 +++++++++++++++---- test/test_piracy.jl | 3 ++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/piracy.jl b/src/piracy.jl index e29018bf..5375ea7e 100644 --- a/src/piracy.jl +++ b/src/piracy.jl @@ -162,14 +162,25 @@ function is_pirate(meth::Method; treat_as_own = Union{Function,Type}[]) signature = Base.unwrap_unionall(meth.sig) + function_type_index = 1 + if signature.parameters[1] === typeof(Core.kwcall) + # kwcall is a special case, since it is not a real function + # but a wrapper around a function, the third parameter is the original + # function, its positional arguments follow. + function_type_index += 2 + end + # the first parameter in the signature is the function type, and it # follows slightly other rules if it happens to be a Union type - is_foreign_method(signature.parameters[1], method_pkg; treat_as_own = treat_as_own) || - return false + is_foreign_method( + signature.parameters[function_type_index], + method_pkg; + treat_as_own = treat_as_own, + ) || return false - all( + return all( param -> is_foreign(param, method_pkg; treat_as_own = treat_as_own), - signature.parameters[2:end], + signature.parameters[function_type_index+1:end], ) end diff --git a/test/test_piracy.jl b/test/test_piracy.jl index 78de01d3..2ba30df3 100644 --- a/test/test_piracy.jl +++ b/test/test_piracy.jl @@ -37,6 +37,7 @@ Base.findlast(::ForeignParameterizedType{Foo}, x::Int) = x + 1 # Not piracy const MyUnion = Union{Int,Foo} MyUnion(x::Int) = x +MyUnion(; x::Int) = x export MyUnion @@ -71,7 +72,7 @@ end 2 + # Foo constructors 1 + # Bar constructor 2 + # f - 1 + # MyUnion + 4 + # MyUnion (incl. kwcall) 6 + # findlast 3 + # findfirst 1 + # ForeignType callable From 9ac8a9518b109ef22c0e0304d47aecd437e763a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20G=C3=B6ttgens?= Date: Tue, 5 Sep 2023 12:36:41 +0200 Subject: [PATCH 2/2] Fix for older julias --- src/piracy.jl | 4 +++- src/utils.jl | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/piracy.jl b/src/piracy.jl index 5375ea7e..ff2ca352 100644 --- a/src/piracy.jl +++ b/src/piracy.jl @@ -1,5 +1,7 @@ module Piracy +using ..Aqua: is_kwcall + if VERSION >= v"1.6-" using Test: is_in_mods else @@ -163,7 +165,7 @@ function is_pirate(meth::Method; treat_as_own = Union{Function,Type}[]) signature = Base.unwrap_unionall(meth.sig) function_type_index = 1 - if signature.parameters[1] === typeof(Core.kwcall) + if is_kwcall(signature) # kwcall is a special case, since it is not a real function # but a wrapper around a function, the third parameter is the original # function, its positional arguments follow. diff --git a/src/utils.jl b/src/utils.jl index 0179714e..386dcdb3 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -157,3 +157,22 @@ function format_diff( $text_b """ end + +function is_kwcall(signature::DataType) + @static if VERSION < v"1.9" + try + return length(signature.parameters) >= 3 && + signature <: Tuple{Function,Any,Any,Vararg} && + ( + signature.parameters[3] <: Type || + isconcretetype(signature.parameters[3]) + ) && + signature.parameters[1] === Core.kwftype(signature.parameters[3]) + catch err + @warn "Please open an issue on JuliaTesting/Aqua.jl for \"is_kwcall\" and the following data:" signature err + return false + end + else + return signature.parameters[1] === typeof(Core.kwcall) + end +end