Skip to content

Commit 44d7677

Browse files
authored
Merge pull request #17057 from JuliaLang/jn/world
type inference runtime correctness (fix #265)
2 parents f27c6f3 + 51eaece commit 44d7677

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+2095
-761
lines changed

NEWS.md

+7
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ Language changes
2222
for `.*` etcetera. This also means that "dot operations" automatically
2323
fuse into a single loop, along with other dot calls `f.(x)`. ([#17623])
2424

25+
* Newly defined methods are no longer callable from the same dynamic runtime
26+
scope they were defined in ([#17057]).
27+
2528
Breaking changes
2629
----------------
2730

@@ -50,6 +53,10 @@ This section lists changes that do not have deprecation warnings.
5053
* `broadcast` now treats `Ref` (except for `Ptr`) arguments as 0-dimensional
5154
arrays ([#18965]).
5255

56+
* The runtime now enforces when new method definitions can take effect ([#17057]).
57+
The flip-side of this is that new method definitions should now reliably actually
58+
take effect, and be called when evaluating new code ([#265]).
59+
5360
Library improvements
5461
--------------------
5562

base/REPL.jl

+3-3
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ function eval_user_input(ast::ANY, backend::REPLBackend)
6666
value = eval(Main, ast)
6767
backend.in_eval = false
6868
# note: value wrapped in a closure to ensure it doesn't get passed through expand
69-
eval(Main, Expr(:(=), :ans, Expr(:call, ()->value)))
69+
eval(Main, Expr(:body, Expr(:(=), :ans, QuoteNode(value)), Expr(:return, nothing)))
7070
put!(backend.response_channel, (value, nothing))
7171
end
7272
break
@@ -153,9 +153,9 @@ function print_response(errio::IO, val::ANY, bt, show_value::Bool, have_color::B
153153
if val !== nothing && show_value
154154
try
155155
if specialdisplay === nothing
156-
display(val)
156+
eval(Main, Expr(:body, Expr(:return, Expr(:call, display, QuoteNode(val)))))
157157
else
158-
display(specialdisplay,val)
158+
eval(Main, Expr(:body, Expr(:return, Expr(:call, specialdisplay, QuoteNode(val)))))
159159
end
160160
catch err
161161
println(errio, "Error showing value of type ", typeof(val), ":")

base/REPLCompletions.jl

+3-2
Original file line numberDiff line numberDiff line change
@@ -281,11 +281,12 @@ function get_type_call(expr::Expr)
281281
found ? push!(args, typ) : push!(args, Any)
282282
end
283283
# use _methods_by_ftype as the function is supplied as a type
284-
mt = Base._methods_by_ftype(Tuple{ft, args...}, -1)
284+
world = typemax(UInt)
285+
mt = Base._methods_by_ftype(Tuple{ft, args...}, -1, world)
285286
length(mt) == 1 || return (Any, false)
286287
m = first(mt)
287288
# Typeinference
288-
params = Core.Inference.InferenceParams()
289+
params = Core.Inference.InferenceParams(world)
289290
return_type = Core.Inference.typeinf_type(m[3], m[1], m[2], true, params)
290291
return_type === nothing && return (Any, false)
291292
return (return_type, true)

base/base.jl

+3
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,10 @@ Alternatively, there is no unique most-specific method.
5757
type MethodError <: Exception
5858
f
5959
args
60+
world::UInt
61+
MethodError(f::ANY, args::ANY, world::UInt) = new(f, args, world)
6062
end
63+
MethodError(f::ANY, args::ANY) = MethodError(f, args, typemax(UInt))
6164

6265
"""
6366
EOFError()

base/boot.jl

+10
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,7 @@ unsafe_convert{T}(::Type{T}, x::T) = x
308308

309309
typealias NTuple{N,T} Tuple{Vararg{T,N}}
310310

311+
311312
# primitive array constructors
312313
(::Type{Array{T,N}}){T,N}(d::NTuple{N,Int}) =
313314
ccall(:jl_new_array, Array{T,N}, (Any,Any), Array{T,N}, d)
@@ -338,6 +339,15 @@ Array{T}(::Type{T}, m::Int,n::Int) = Array{T,2}(m,n)
338339
Array{T}(::Type{T}, m::Int,n::Int,o::Int) = Array{T,3}(m,n,o)
339340

340341

342+
# primitive Symbol constructors
343+
Symbol(s::String) = Symbol(s.data)
344+
function Symbol(a::Array{UInt8,1})
345+
return ccall(:jl_symbol_n, Ref{Symbol}, (Ptr{UInt8}, Int),
346+
ccall(:jl_array_ptr, Ptr{UInt8}, (Any,), a),
347+
Intrinsics.arraylen(a))
348+
end
349+
350+
341351
# docsystem basics
342352
macro doc(x...)
343353
atdoc(x...)

base/client.jl

+4-3
Original file line numberDiff line numberDiff line change
@@ -142,12 +142,13 @@ function eval_user_input(ast::ANY, show_value)
142142
else
143143
ast = expand(ast)
144144
value = eval(Main, ast)
145-
eval(Main, Expr(:(=), :ans, Expr(:call, ()->value)))
146-
if value!==nothing && show_value
145+
eval(Main, Expr(:body, Expr(:(=), :ans, QuoteNode(value)), Expr(:return, nothing)))
146+
if !(value === nothing) && show_value
147147
if have_color
148148
print(answer_color())
149149
end
150-
try display(value)
150+
try
151+
eval(Main, Expr(:body, Expr(:return, Expr(:call, display, QuoteNode(value)))))
151152
catch err
152153
println(STDERR, "Evaluation succeeded, but an error occurred while showing value of type ", typeof(value), ":")
153154
rethrow(err)

base/coreimg.jl

+6-13
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,16 @@ import Core: print, println, show, write, unsafe_write, STDOUT, STDERR
66

77
ccall(:jl_set_istopmod, Void, (Bool,), false)
88

9-
eval(x) = Core.eval(Inference,x)
10-
eval(m,x) = Core.eval(m,x)
9+
eval(x) = Core.eval(Inference, x)
10+
eval(m, x) = Core.eval(m, x)
1111

12-
include = Core.include
12+
const include = Core.include
13+
# conditional to allow redefining Core.Inference after base exists
14+
isdefined(Main, :Base) || ((::Type{T}){T}(arg) = convert(T, arg)::T)
1315

1416
## Load essential files and libraries
15-
include("ctypes.jl")
1617
include("essentials.jl")
18+
include("ctypes.jl")
1719
include("generator.jl")
1820
include("reflection.jl")
1921
include("options.jl")
@@ -33,15 +35,6 @@ include("operators.jl")
3335
include("pointer.jl")
3436
const checked_add = +
3537
const checked_sub = -
36-
if !isdefined(Main, :Base)
37-
# conditional to allow redefining Core.Inference after base exists
38-
(::Type{T}){T}(arg) = convert(T, arg)::T
39-
end
40-
41-
# Symbol constructors
42-
Symbol(s::String) = Symbol(s.data)
43-
Symbol(a::Array{UInt8,1}) =
44-
ccall(:jl_symbol_n, Ref{Symbol}, (Ptr{UInt8}, Int32), a, length(a))
4538

4639
# core array operations
4740
include("array.jl")

base/docs/core.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import ..esc, ..push!, ..getindex, ..current_module, ..unsafe_load, ..Csize_t
77
function doc!(str, ex)
88
ptr = unsafe_load(Core.Intrinsics.cglobal(:jl_filename, Ptr{UInt8}))
99
len = ccall(:strlen, Csize_t, (Ptr{UInt8},), ptr)
10-
file = ccall(:jl_symbol_n, Any, (Ptr{UInt8}, Int32), ptr, len)
10+
file = ccall(:jl_symbol_n, Any, (Ptr{UInt8}, Csize_t), ptr, len)
1111
line = unsafe_load(Core.Intrinsics.cglobal(:jl_lineno, Int32)) # Cint
1212
push!(DOCS, (current_module(), ex, str, file, line))
1313
end

base/error.jl

+4-2
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@ systemerror(p, b::Bool; extrainfo=nothing) = b ? throw(Main.Base.SystemError(str
3838
assert(x) = x ? nothing : throw(Main.Base.AssertionError())
3939
macro assert(ex, msgs...)
4040
msg = isempty(msgs) ? ex : msgs[1]
41-
if !isempty(msgs) && (isa(msg, Expr) || isa(msg, Symbol))
41+
if isa(msg, AbstractString)
42+
msg = msg # pass-through
43+
elseif !isempty(msgs) && (isa(msg, Expr) || isa(msg, Symbol))
4244
# message is an expression needing evaluating
4345
msg = :(Main.Base.string($(esc(msg))))
4446
elseif isdefined(Main, :Base) && isdefined(Main.Base, :string)
@@ -47,7 +49,7 @@ macro assert(ex, msgs...)
4749
# string() might not be defined during bootstrap
4850
msg = :(Main.Base.string($(Expr(:quote,msg))))
4951
end
50-
:($(esc(ex)) ? $(nothing) : throw(Main.Base.AssertionError($msg)))
52+
return :($(esc(ex)) ? $(nothing) : throw(Main.Base.AssertionError($msg)))
5153
end
5254

5355
# NOTE: Please keep the constant values specified below in sync with the doc string

0 commit comments

Comments
 (0)