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

JuliaLang / julia / #37433

pending completion
#37433

push

local

web-flow
Merge pull request #48513 from JuliaLang/jn/extend-once

ensure extension triggers are only run by the package that satified them

60 of 60 new or added lines in 1 file covered. (100.0%)

72324 of 82360 relevant lines covered (87.81%)

31376331.4 hits per line

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

70.0
/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
### General Methods for Ref{T} type
87

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

100
# create Ref objects for general object conversion
101
unsafe_convert(::Type{Ref{T}}, x::Ref{T}) where {T} = unsafe_convert(Ptr{T}, x)
87,530,538✔
102
unsafe_convert(::Type{Ref{T}}, x) where {T} = unsafe_convert(Ptr{T}, x)
×
103

104
convert(::Type{Ref{T}}, x) where {T} = RefValue{T}(x)::RefValue{T}
6,127,863✔
105

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

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

134
###
135
if is_primary_base_module
136
    Ref(x::Any) = RefValue(x)
11,223,229✔
137
    Ref{T}() where {T} = RefValue{T}() # Ref{T}()
39,408,275✔
138
    Ref{T}(x) where {T} = RefValue{T}(x) # Ref{T}(x)
41,000,423✔
139

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

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

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

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

181
###
182

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

186
###
187

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

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

194
This type is mainly used to interface with code that has strict requirements about pointers,
195
e.g., intrinsics that are selected based on the address space, or back-ends that require
196
pointers to be identifiable by their types.
197
"""
198
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