@@ -106,6 +106,40 @@ macro specialize(vars...)
106
106
return Expr (:meta , :specialize , vars... )
107
107
end
108
108
109
+ """
110
+ @isdefined s -> Bool
111
+
112
+ Tests whether variable `s` is defined in the current scope.
113
+
114
+ See also [`isdefined`](@ref).
115
+
116
+ # Examples
117
+ ```jldoctest
118
+ julia> @isdefined newvar
119
+ false
120
+
121
+ julia> newvar = 1
122
+ 1
123
+
124
+ julia> @isdefined newvar
125
+ true
126
+
127
+ julia> function f()
128
+ println(@isdefined x)
129
+ x = 3
130
+ println(@isdefined x)
131
+ end
132
+ f (generic function with 1 method)
133
+
134
+ julia> f()
135
+ false
136
+ true
137
+ ```
138
+ """
139
+ macro isdefined (s:: Symbol )
140
+ return Expr (:escape , Expr (:isdefined , s))
141
+ end
142
+
109
143
macro _pure_meta ()
110
144
return Expr (:meta , :pure )
111
145
end
@@ -207,31 +241,6 @@ ERROR: ArgumentError: Cannot call tail on an empty tuple.
207
241
tail (x:: Tuple ) = argtail (x... )
208
242
tail (:: Tuple{} ) = throw (ArgumentError (" Cannot call tail on an empty tuple." ))
209
243
210
- tuple_type_head (T:: Type ) = (@_pure_meta ; fieldtype (T, 1 ))
211
-
212
- function tuple_type_tail (T:: Type )
213
- @_pure_meta
214
- if isa (T, UnionAll)
215
- return UnionAll (T. var, tuple_type_tail (T. body))
216
- elseif isa (T, Union)
217
- return Union{tuple_type_tail (T. a), tuple_type_tail (T. b)}
218
- else
219
- T. name === Tuple. name || throw (MethodError (tuple_type_tail, (T,)))
220
- if isvatuple (T) && length (T. parameters) == 1
221
- va = T. parameters[1 ]
222
- (isa (va, DataType) && isa (va. parameters[2 ], Int)) || return T
223
- return Tuple{Vararg{va. parameters[1 ], va. parameters[2 ]- 1 }}
224
- end
225
- return Tuple{argtail (T. parameters... )... }
226
- end
227
- end
228
-
229
- tuple_type_cons (:: Type , :: Type{Union{}} ) = Union{}
230
- function tuple_type_cons (:: Type{S} , :: Type{T} ) where T<: Tuple where S
231
- @_pure_meta
232
- Tuple{S, T. parameters... }
233
- end
234
-
235
244
function unwrap_unionall (@nospecialize (a))
236
245
while isa (a,UnionAll)
237
246
a = a. body
248
257
249
258
# replace TypeVars in all enclosing UnionAlls with fresh TypeVars
250
259
function rename_unionall (@nospecialize (u))
251
- if ! isa (u,UnionAll)
260
+ if ! isa (u, UnionAll)
252
261
return u
253
262
end
254
263
body = rename_unionall (u. body)
@@ -301,52 +310,49 @@ function typename(a::Union)
301
310
end
302
311
typename (union:: UnionAll ) = typename (union. body)
303
312
304
- const AtLeast1 = Tuple{Any, Vararg{Any}}
305
-
306
- # converting to empty tuple type
307
- convert (:: Type{Tuple{}} , :: Tuple{} ) = ()
308
- convert (:: Type{Tuple{}} , x:: AtLeast1 ) = throw (MethodError (convert, (Tuple{}, x)))
309
-
310
- # converting to tuple types with at least one element
311
- convert (:: Type{T} , x:: T ) where {T<: AtLeast1 } = x
312
- convert (:: Type{T} , x:: AtLeast1 ) where {T<: AtLeast1 } =
313
- (convert (tuple_type_head (T), x[1 ]), convert (tuple_type_tail (T), tail (x))... )
314
-
315
- # converting to Vararg tuple types
316
- convert (:: Type{Tuple{Vararg{V}}} , x:: Tuple{Vararg{V}} ) where {V} = x
317
- convert (T:: Type{Tuple{Vararg{V}}} , x:: Tuple ) where {V} =
318
- (convert (tuple_type_head (T), x[1 ]), convert (T, tail (x))... )
319
-
320
- # TODO : the following definitions are equivalent (behaviorally) to the above method
321
- # I think they may be faster / more efficient for inference,
322
- # if we could enable them, but are they?
323
- # TODO : These currently can't be used (#21026, #23017) since with
324
- # z(::Type{<:Tuple{Vararg{T}}}) where {T} = T
325
- # calling
326
- # z(Tuple{Val{T}} where T)
327
- # fails, even though `Type{Tuple{Val}} == Type{Tuple{Val{S}} where S}`
328
- # and so T should be `Val` (aka `Val{S} where S`)
329
- # convert(_::Type{Tuple{S}}, x::Tuple{S}) where {S} = x
330
- # convert(_::Type{Tuple{S}}, x::Tuple{Any}) where {S} = (convert(S, x[1]),)
331
- # convert(_::Type{T}, x::T) where {S, N, T<:Tuple{S, Vararg{S, N}}} = x
332
- # convert(_::Type{Tuple{S, Vararg{S, N}}},
333
- # x::Tuple{Any, Vararg{Any, N}}) where
334
- # {S, N} = cnvt_all(S, x...)
335
- # convert(_::Type{Tuple{Vararg{S, N}}},
336
- # x::Tuple{Vararg{Any, N}}) where
337
- # {S, N} = cnvt_all(S, x...)
338
- # TODO : These are similar to the methods we currently use but cnvt_all might work better:
339
- # convert(_::Type{Tuple{Vararg{S}}},
340
- # x::Tuple{Any, Vararg{Any}}) where
341
- # {S} = cnvt_all(S, x...)
342
- # convert(_::Type{Tuple{Vararg{S}}},
343
- # x::Tuple{Vararg{Any}}) where
344
- # {S} = cnvt_all(S, x...)
345
- # cnvt_all(T) = ()
346
- # cnvt_all(T, x, rest...) = (convert(T, x), cnvt_all(T, rest...)...)
347
- # TODO : These may be necessary if the above are enabled
313
+ _tuple_error (T:: Type , x) = (@_noinline_meta ; throw (MethodError (convert, (T, x))))
314
+
315
+ convert (:: Type{T} , x:: T ) where {T<: Tuple } = x
316
+ function convert (:: Type{T} , x:: NTuple{N,Any} ) where {N, T<: Tuple }
317
+ # First see if there could be any conversion of the input type that'd be a subtype of the output.
318
+ # If not, we'll throw an explicit MethodError (otherwise, it might throw a typeassert).
319
+ if typeintersect (NTuple{N,Any}, T) === Union{}
320
+ _tuple_error (T, x)
321
+ end
322
+ cvt1 (n) = (@_inline_meta ; convert (fieldtype (T, n), getfield (x, n, #= boundscheck=# false )))
323
+ return ntuple (cvt1, Val (N)):: NTuple{N,Any}
324
+ end
325
+
326
+ # optimizations?
327
+ # converting to tuple types of fixed length
328
+ # convert(::Type{T}, x::T) where {N, T<:NTuple{N,Any}} = x
329
+ # convert(::Type{T}, x::NTuple{N,Any}) where {N, T<:NTuple{N,Any}} =
330
+ # ntuple(n -> convert(fieldtype(T, n), x[n]), Val(N))
331
+ # convert(::Type{T}, x::Tuple{Vararg{Any}}) where {N, T<:NTuple{N,Any}} =
332
+ # throw(MethodError(convert, (T, x)))
333
+ # converting to tuple types of indefinite length
334
+ # convert(::Type{Tuple{Vararg{V}}}, x::Tuple{Vararg{V}}) where {V} = x
335
+ # convert(::Type{NTuple{N, V}}, x::NTuple{N, V}) where {N, V} = x
336
+ # function convert(T::Type{Tuple{Vararg{V}}}, x::Tuple) where {V}
337
+ # @isdefined(V) || (V = fieldtype(T, 1))
338
+ # return map(t -> convert(V, t), x)
339
+ # end
340
+ # function convert(T::Type{NTuple{N, V}}, x::NTuple{N, Any}) where {N, V}
341
+ # @isdefined(V) || (V = fieldtype(T, 1))
342
+ # return map(t -> convert(V, t), x)
343
+ # end
344
+ # short tuples
348
345
# convert(::Type{Tuple{}}, ::Tuple{}) = ()
349
- # convert(::Type{Tuple{Vararg{S}}} where S, ::Tuple{}) = ()
346
+ # convert(::Type{Tuple{S}}, x::Tuple{S}) where {S} = x
347
+ # convert(::Type{Tuple{S, T}}, x::Tuple{S, T}) where {S, T} = x
348
+ # convert(::Type{Tuple{S, T, U}}, x::Tuple{S, T, U}) where {S, T, U} = x
349
+ # convert(::Type{Tuple{S}}, x::Tuple{Any}) where {S} = (convert(S, x[1]),)
350
+ # convert(::Type{Tuple{S, T}}, x::Tuple{Any, Any}) where {S, T} = (convert(S, x[1]), convert(T, x[2]),)
351
+ # convert(::Type{Tuple{S, T, U}}, x::Tuple{Any, Any, Any}) where {S, T, U} = (convert(S, x[1]), convert(T, x[2]), convert(U, x[3]))
352
+ # convert(::Type{Tuple{}}, x::Tuple) = _tuple_error(Tuple{}, x)
353
+ # convert(::Type{Tuple{S}}, x::Tuple) = _tuple_error(Tuple{S}, x)
354
+ # convert(::Type{Tuple{S, T}}, x::Tuple{Any, Any}) where {S, T} =_tuple_error(Tuple{S, T}, x)
355
+ # convert(::Type{Tuple{S, T, U}}, x::Tuple{Any, Any, Any}) where {S, T, U} = _tuple_error(Tuple{S, T, U}, x)
350
356
351
357
"""
352
358
oftype(x, y)
@@ -695,7 +701,7 @@ julia> f(Val(true))
695
701
struct Val{x}
696
702
end
697
703
698
- Val (x) = ( @_pure_meta ; Val {x} () )
704
+ Val (x) = Val {x} ()
699
705
700
706
"""
701
707
invokelatest(f, args...; kwargs...)
0 commit comments