From f82ce5c89f3b319fd0b7692527ef28449c2a2795 Mon Sep 17 00:00:00 2001 From: Eric Davies Date: Thu, 14 Jun 2018 16:19:12 -0500 Subject: [PATCH 1/3] Add hasfield to check for field existence --- base/exports.jl | 1 + base/reflection.jl | 21 +++++++++++++++++++++ doc/src/base/base.md | 1 + 3 files changed, 23 insertions(+) diff --git a/base/exports.jl b/base/exports.jl index b7492fc2a6b53..ad6fa04d4e828 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -714,6 +714,7 @@ export fieldname, fieldnames, fieldcount, + hasfield, propertynames, isabstracttype, isbitstype, diff --git a/base/reflection.jl b/base/reflection.jl index 12d7cbcd46540..2a9734a0f7000 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -560,6 +560,27 @@ function fieldindex(T::DataType, name::Symbol, err::Bool=true) return Int(ccall(:jl_field_index, Cint, (Any, Any, Cint), T, name, err)+1) end +""" + hasfield(T, name::Symbol) + +Return `true` if a composite DataType `T` has a field called `name`. + +# Examples +```jldoctest +julia> struct Foo + x::Int64 + y::String + end + +julia> Base.hasfield(Foo, :x) +true + +julia> Base.hasfield(Foo, :balloon) +false +``` +""" +hasfield(T::DataType, name::Symbol) = fieldindex(T, name, false) > 0 + argument_datatype(@nospecialize t) = ccall(:jl_argument_datatype, Any, (Any,), t) function argument_mt(@nospecialize t) dt = argument_datatype(t) diff --git a/doc/src/base/base.md b/doc/src/base/base.md index 030ffe3a837e4..4460b61da35bf 100644 --- a/doc/src/base/base.md +++ b/doc/src/base/base.md @@ -154,6 +154,7 @@ Base.isbitstype Core.fieldtype Base.fieldcount Base.fieldoffset +Base.hasfield Base.datatype_alignment Base.datatype_haspadding Base.datatype_pointerfree From cd302d093c35ecfb9fa98a08b11332e5df6f8e41 Mon Sep 17 00:00:00 2001 From: Eric Davies Date: Fri, 15 Jun 2018 10:37:27 -0500 Subject: [PATCH 2/3] Add tests for hasfield --- test/reflection.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/reflection.jl b/test/reflection.jl index 6c57ba4bde132..c12bfeebbaf85 100644 --- a/test/reflection.jl +++ b/test/reflection.jl @@ -230,6 +230,11 @@ tlayout = TLayout(5,7,11) @test_throws ArgumentError fieldname(TLayout, 4) @test_throws BoundsError fieldoffset(TLayout, 4) +for name in (:x, :y, :z) + @test hasfield(TLayout, name) +end +@test !hasfield(TLayout, :parameters) + @test fieldtype(Tuple{Vararg{Int8}}, 1) === Int8 @test fieldtype(Tuple{Vararg{Int8}}, 10) === Int8 @test_throws BoundsError fieldtype(Tuple{Vararg{Int8}}, 0) From da36b48eb2b2a4151c58eda6400d2aa76edb113f Mon Sep 17 00:00:00 2001 From: Eric Davies Date: Fri, 15 Jun 2018 14:11:07 -0500 Subject: [PATCH 3/3] Add news for hasfield --- NEWS.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS.md b/NEWS.md index df9d327cb2718..4a7ad9bae386c 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1269,6 +1269,8 @@ Deprecated or removed * `atan2` is now a 2-argument method of `atan` ([#27248]). + * `hasfield` was added to check if a composite type has a field of a given name ([#27582]) + Command-line option changes ---------------------------