• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

JuliaLang / julia / #37596

pending completion
#37596

push

local

web-flow
🤖 [master] Bump the Pkg stdlib from 2c04d5a98 to b044bf6a2 (#50851)

Co-authored-by: Dilum Aluthge <dilum@aluthge.com>

71913 of 84418 relevant lines covered (85.19%)

32144286.87 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

68.33
/base/refpointer.jl
1
# This file is a part of Julia. License is MIT: https://julialang.org/license
2

3
"""
4
    Ref{T}
5

6
An object that safely references data of type `T`. This type is guaranteed to point to
7
valid, Julia-allocated memory of the correct type. The underlying data is protected from
8
freeing by the garbage collector as long as the `Ref` itself is referenced.
9

10
In Julia, `Ref` objects are dereferenced (loaded or stored) with `[]`.
11

12
Creation of a `Ref` to a value `x` of type `T` is usually written `Ref(x)`.
13
Additionally, for creating interior pointers to containers (such as Array or Ptr),
14
it can be written `Ref(a, i)` for creating a reference to the `i`-th element of `a`.
15

16
`Ref{T}()` creates a reference to a value of type `T` without initialization.
17
For a bitstype `T`, the value will be whatever currently resides in the memory
18
allocated. For a non-bitstype `T`, the reference will be undefined and attempting to
19
dereference it will result in an error, "UndefRefError: access to undefined reference".
20

21
To check if a `Ref` is an undefined reference, use [`isassigned(ref::RefValue)`](@ref).
22
For example, `isassigned(Ref{T}())` is `false` if `T` is not a bitstype.
23
If `T` is a bitstype, `isassigned(Ref{T}())` will always be true.
24

25
When passed as a `ccall` argument (either as a `Ptr` or `Ref` type), a `Ref`
26
object will be converted to a native pointer to the data it references.
27
For most `T`, or when converted to a `Ptr{Cvoid}`, this is a pointer to the
28
object data. When `T` is an `isbits` type, this value may be safely mutated,
29
otherwise mutation is strictly undefined behavior.
30

31
As a special case, setting `T = Any` will instead cause the creation of a
32
pointer to the reference itself when converted to a `Ptr{Any}`
33
(a `jl_value_t const* const*` if T is immutable, else a `jl_value_t *const *`).
34
When converted to a `Ptr{Cvoid}`, it will still return a pointer to the data
35
region as for any other `T`.
36

37
A `C_NULL` instance of `Ptr` can be passed to a `ccall` `Ref` argument to initialize it.
38

39
# Use in broadcasting
40
`Ref` is sometimes used in broadcasting in order to treat the referenced values as a scalar.
41

42
# Examples
43

44
```jldoctest
45
julia> Ref(5)
46
Base.RefValue{Int64}(5)
47

48
julia> isa.(Ref([1,2,3]), [Array, Dict, Int]) # Treat reference values as scalar during broadcasting
49
3-element BitVector:
50
 1
51
 0
52
 0
53

54
julia> Ref{Function}()  # Undefined reference to a non-bitstype, Function
55
Base.RefValue{Function}(#undef)
56

57
julia> try
58
           Ref{Function}()[] # Dereferencing an undefined reference will result in an error
59
       catch e
60
           println(e)
61
       end
62
UndefRefError()
63

64
julia> Ref{Int64}()[]; # A reference to a bitstype refers to an undetermined value if not given
65

66
julia> isassigned(Ref{Int64}()) # A reference to a bitstype is always assigned
67
true
68

69
julia> Ref{Int64}(0)[] == 0 # Explicitly give a value for a bitstype reference
70
true
71
```
72
"""
73
Ref
74

75
# C NUL-terminated string pointers; these can be used in ccall
76
# instead of Ptr{Cchar} and Ptr{Cwchar_t}, respectively, to enforce
77
# a check for embedded NUL chars in the string (to avoid silent truncation).
78
if Int === Int64
79
    primitive type Cstring  64 end
80
    primitive type Cwstring 64 end
81
else
82
    primitive type Cstring  32 end
83
    primitive type Cwstring 32 end
84
end
85

86

87
### General Methods for Ref{T} type
88

89
eltype(x::Type{<:Ref{T}}) where {T} = @isdefined(T) ? T : Any
1,574,371✔
90
convert(::Type{Ref{T}}, x::Ref{T}) where {T} = x
×
91
size(x::Ref) = ()
1✔
92
axes(x::Ref) = ()
1,575,868✔
93
length(x::Ref) = 1
×
94
isempty(x::Ref) = false
×
95
ndims(x::Ref) = 0
1✔
96
ndims(::Type{<:Ref}) = 0
1,575,940✔
97
iterate(r::Ref) = (r[], nothing)
2✔
98
iterate(r::Ref, s) = nothing
2✔
99
IteratorSize(::Type{<:Ref}) = HasShape{0}()
2✔
100

101
# create Ref objects for general object conversion
102
unsafe_convert(::Type{Ref{T}}, x::Ref{T}) where {T} = unsafe_convert(Ptr{T}, x)
3,668,573✔
103
unsafe_convert(::Type{Ref{T}}, x) where {T} = unsafe_convert(Ptr{T}, x)
×
104

105
convert(::Type{Ref{T}}, x) where {T} = RefValue{T}(x)::RefValue{T}
25,894,701✔
106

107
### Methods for a Ref object that is backed by an array at index i
108
struct RefArray{T,A<:AbstractArray{T},R} <: Ref{T}
109
    x::A
110
    i::Int
111
    roots::R # should be either ::Nothing or ::Any
112
    RefArray{T,A,R}(x,i,roots=nothing) where {T,A<:AbstractArray{T},R} = new(x,i,roots)
2,239✔
113
end
114
RefArray(x::AbstractArray{T}, i::Int, roots::Any) where {T} = RefArray{T,typeof(x),Any}(x, i, roots)
2,208✔
115
RefArray(x::AbstractArray{T}, i::Int=1, roots::Nothing=nothing) where {T} = RefArray{T,typeof(x),Nothing}(x, i, nothing)
62✔
116
RefArray(x::AbstractArray{T}, i::Integer, roots::Any) where {T} = RefArray{T,typeof(x),Any}(x, Int(i), roots)
×
117
RefArray(x::AbstractArray{T}, i::Integer, roots::Nothing=nothing) where {T} = RefArray{T,typeof(x),Nothing}(x, Int(i), nothing)
×
118
convert(::Type{Ref{T}}, x::AbstractArray{T}) where {T} = RefArray(x, 1)
9✔
119

120
function unsafe_convert(P::Union{Type{Ptr{T}},Type{Ptr{Cvoid}}}, b::RefArray{T})::P where T
30✔
121
    if allocatedinline(T)
30✔
122
        p = pointer(b.x, b.i)
2,244✔
123
    elseif isconcretetype(T) && ismutabletype(T)
×
124
        p = pointer_from_objref(b.x[b.i])
×
125
    else
126
        # see comment on equivalent branch for RefValue
127
        p = pointerref(Ptr{Ptr{Cvoid}}(pointer(b.x, b.i)), 1, Core.sizeof(Ptr{Cvoid}))
×
128
    end
129
    return p
30✔
130
end
131
function unsafe_convert(::Type{Ptr{Any}}, b::RefArray{Any})::Ptr{Any}
×
132
    return pointer(b.x, b.i)
×
133
end
134

135
###
136
if is_primary_base_module
137
    Ref(x::Any) = RefValue(x)
11,233,539✔
138
    Ref{T}() where {T} = RefValue{T}() # Ref{T}()
241,911✔
139
    Ref{T}(x) where {T} = RefValue{T}(x) # Ref{T}(x)
3,387,904✔
140

141
    Ref(x::Ref, i::Integer) = (i != 1 && error("Ref only has one element"); x)
×
142
    Ref(x::Ptr{T}, i::Integer) where {T} = x + (i - 1) * Core.sizeof(T)
×
143

144
    # convert Arrays to pointer arrays for ccall
145
    function Ref{P}(a::Array{<:Union{Ptr,Cwstring,Cstring}}) where P<:Union{Ptr,Cwstring,Cstring}
×
146
        return RefArray(a) # effectively a no-op
×
147
    end
148
    function Ref{P}(a::Array{T}) where P<:Union{Ptr,Cwstring,Cstring} where T
2,208✔
149
        if (!isbitstype(T) && T <: eltype(P))
2,208✔
150
            # this Array already has the right memory layout for the requested Ref
151
            return RefArray(a,1,false) # root something, so that this function is type-stable
×
152
        else
153
            ptrs = Vector{P}(undef, length(a)+1)
2,208✔
154
            roots = Vector{Any}(undef, length(a))
2,208✔
155
            for i = 1:length(a)
4,415✔
156
                root = cconvert(P, a[i])
44,781✔
157
                ptrs[i] = unsafe_convert(P, root)::P
44,781✔
158
                roots[i] = root
44,781✔
159
            end
87,355✔
160
            ptrs[length(a)+1] = C_NULL
2,208✔
161
            return RefArray(ptrs,1,roots)
2,208✔
162
        end
163
    end
164
    Ref(x::AbstractArray, i::Integer) = RefArray(x, i)
22✔
165
end
166

167
cconvert(::Type{Ptr{P}}, a::Array{<:Ptr}) where {P<:Ptr} = a
×
168
cconvert(::Type{Ref{P}}, a::Array{<:Ptr}) where {P<:Ptr} = a
×
169
cconvert(::Type{Ptr{P}}, a::Array) where {P<:Union{Ptr,Cwstring,Cstring}} = Ref{P}(a)
2,165✔
170
cconvert(::Type{Ref{P}}, a::Array) where {P<:Union{Ptr,Cwstring,Cstring}} = Ref{P}(a)
43✔
171

172
# pass NTuple{N,T} as Ptr{T}/Ref{T}
173
cconvert(::Type{Ref{T}}, t::NTuple{N,T}) where {N,T} = Ref{NTuple{N,T}}(t)
4✔
174
cconvert(::Type{Ref{T}}, r::Ref{NTuple{N,T}}) where {N,T} = r
3✔
175
unsafe_convert(::Type{Ref{T}}, r::Ref{NTuple{N,T}}) where {N,T} =
7✔
176
    convert(Ptr{T}, unsafe_convert(Ptr{NTuple{N,T}}, r))
177
unsafe_convert(::Type{Ptr{T}}, r::Ref{NTuple{N,T}}) where {N,T} =
38,506✔
178
    convert(Ptr{T}, unsafe_convert(Ptr{NTuple{N,T}}, r))
179
unsafe_convert(::Type{Ptr{T}}, r::Ptr{NTuple{N,T}}) where {N,T} =
×
180
    convert(Ptr{T}, r)
181

182
###
183

184
getindex(b::RefArray) = b.x[b.i]
4✔
185
setindex!(b::RefArray, x) = (b.x[b.i] = x; b)
2✔
186

187
###
188

189
"""
190
    LLVMPtr{T, AS}
191

192
A pointer type that more closely resembles LLVM semantics: It includes the pointer address
193
space, and will be passed as an actual pointer instead of an integer.
194

195
This type is mainly used to interface with code that has strict requirements about pointers,
196
e.g., intrinsics that are selected based on the address space, or back-ends that require
197
pointers to be identifiable by their types.
198
"""
199
Core.LLVMPtr
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc