Skip to content

Commit

Permalink
Merge pull request #17057 from JuliaLang/jn/world
Browse files Browse the repository at this point in the history
type inference runtime correctness (fix #265)
  • Loading branch information
vtjnash authored Dec 23, 2016
2 parents f27c6f3 + 51eaece commit 44d7677
Showing 51 changed files with 2,095 additions and 761 deletions.
7 changes: 7 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -22,6 +22,9 @@ Language changes
for `.*` etcetera. This also means that "dot operations" automatically
fuse into a single loop, along with other dot calls `f.(x)`. ([#17623])

* Newly defined methods are no longer callable from the same dynamic runtime
scope they were defined in ([#17057]).

Breaking changes
----------------

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

* The runtime now enforces when new method definitions can take effect ([#17057]).
The flip-side of this is that new method definitions should now reliably actually
take effect, and be called when evaluating new code ([#265]).

Library improvements
--------------------

6 changes: 3 additions & 3 deletions base/REPL.jl
Original file line number Diff line number Diff line change
@@ -66,7 +66,7 @@ function eval_user_input(ast::ANY, backend::REPLBackend)
value = eval(Main, ast)
backend.in_eval = false
# note: value wrapped in a closure to ensure it doesn't get passed through expand
eval(Main, Expr(:(=), :ans, Expr(:call, ()->value)))
eval(Main, Expr(:body, Expr(:(=), :ans, QuoteNode(value)), Expr(:return, nothing)))
put!(backend.response_channel, (value, nothing))
end
break
@@ -153,9 +153,9 @@ function print_response(errio::IO, val::ANY, bt, show_value::Bool, have_color::B
if val !== nothing && show_value
try
if specialdisplay === nothing
display(val)
eval(Main, Expr(:body, Expr(:return, Expr(:call, display, QuoteNode(val)))))
else
display(specialdisplay,val)
eval(Main, Expr(:body, Expr(:return, Expr(:call, specialdisplay, QuoteNode(val)))))
end
catch err
println(errio, "Error showing value of type ", typeof(val), ":")
5 changes: 3 additions & 2 deletions base/REPLCompletions.jl
Original file line number Diff line number Diff line change
@@ -281,11 +281,12 @@ function get_type_call(expr::Expr)
found ? push!(args, typ) : push!(args, Any)
end
# use _methods_by_ftype as the function is supplied as a type
mt = Base._methods_by_ftype(Tuple{ft, args...}, -1)
world = typemax(UInt)
mt = Base._methods_by_ftype(Tuple{ft, args...}, -1, world)
length(mt) == 1 || return (Any, false)
m = first(mt)
# Typeinference
params = Core.Inference.InferenceParams()
params = Core.Inference.InferenceParams(world)
return_type = Core.Inference.typeinf_type(m[3], m[1], m[2], true, params)
return_type === nothing && return (Any, false)
return (return_type, true)
3 changes: 3 additions & 0 deletions base/base.jl
Original file line number Diff line number Diff line change
@@ -57,7 +57,10 @@ Alternatively, there is no unique most-specific method.
type MethodError <: Exception
f
args
world::UInt
MethodError(f::ANY, args::ANY, world::UInt) = new(f, args, world)
end
MethodError(f::ANY, args::ANY) = MethodError(f, args, typemax(UInt))

"""
EOFError()
10 changes: 10 additions & 0 deletions base/boot.jl
Original file line number Diff line number Diff line change
@@ -308,6 +308,7 @@ unsafe_convert{T}(::Type{T}, x::T) = x

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


# primitive array constructors
(::Type{Array{T,N}}){T,N}(d::NTuple{N,Int}) =
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)
Array{T}(::Type{T}, m::Int,n::Int,o::Int) = Array{T,3}(m,n,o)


# primitive Symbol constructors
Symbol(s::String) = Symbol(s.data)
function Symbol(a::Array{UInt8,1})
return ccall(:jl_symbol_n, Ref{Symbol}, (Ptr{UInt8}, Int),
ccall(:jl_array_ptr, Ptr{UInt8}, (Any,), a),
Intrinsics.arraylen(a))
end


# docsystem basics
macro doc(x...)
atdoc(x...)
7 changes: 4 additions & 3 deletions base/client.jl
Original file line number Diff line number Diff line change
@@ -142,12 +142,13 @@ function eval_user_input(ast::ANY, show_value)
else
ast = expand(ast)
value = eval(Main, ast)
eval(Main, Expr(:(=), :ans, Expr(:call, ()->value)))
if value!==nothing && show_value
eval(Main, Expr(:body, Expr(:(=), :ans, QuoteNode(value)), Expr(:return, nothing)))
if !(value === nothing) && show_value
if have_color
print(answer_color())
end
try display(value)
try
eval(Main, Expr(:body, Expr(:return, Expr(:call, display, QuoteNode(value)))))
catch err
println(STDERR, "Evaluation succeeded, but an error occurred while showing value of type ", typeof(value), ":")
rethrow(err)
19 changes: 6 additions & 13 deletions base/coreimg.jl
Original file line number Diff line number Diff line change
@@ -6,14 +6,16 @@ import Core: print, println, show, write, unsafe_write, STDOUT, STDERR

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

eval(x) = Core.eval(Inference,x)
eval(m,x) = Core.eval(m,x)
eval(x) = Core.eval(Inference, x)
eval(m, x) = Core.eval(m, x)

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

## Load essential files and libraries
include("ctypes.jl")
include("essentials.jl")
include("ctypes.jl")
include("generator.jl")
include("reflection.jl")
include("options.jl")
@@ -33,15 +35,6 @@ include("operators.jl")
include("pointer.jl")
const checked_add = +
const checked_sub = -
if !isdefined(Main, :Base)
# conditional to allow redefining Core.Inference after base exists
(::Type{T}){T}(arg) = convert(T, arg)::T
end

# Symbol constructors
Symbol(s::String) = Symbol(s.data)
Symbol(a::Array{UInt8,1}) =
ccall(:jl_symbol_n, Ref{Symbol}, (Ptr{UInt8}, Int32), a, length(a))

# core array operations
include("array.jl")
2 changes: 1 addition & 1 deletion base/docs/core.jl
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@ import ..esc, ..push!, ..getindex, ..current_module, ..unsafe_load, ..Csize_t
function doc!(str, ex)
ptr = unsafe_load(Core.Intrinsics.cglobal(:jl_filename, Ptr{UInt8}))
len = ccall(:strlen, Csize_t, (Ptr{UInt8},), ptr)
file = ccall(:jl_symbol_n, Any, (Ptr{UInt8}, Int32), ptr, len)
file = ccall(:jl_symbol_n, Any, (Ptr{UInt8}, Csize_t), ptr, len)
line = unsafe_load(Core.Intrinsics.cglobal(:jl_lineno, Int32)) # Cint
push!(DOCS, (current_module(), ex, str, file, line))
end
6 changes: 4 additions & 2 deletions base/error.jl
Original file line number Diff line number Diff line change
@@ -38,7 +38,9 @@ systemerror(p, b::Bool; extrainfo=nothing) = b ? throw(Main.Base.SystemError(str
assert(x) = x ? nothing : throw(Main.Base.AssertionError())
macro assert(ex, msgs...)
msg = isempty(msgs) ? ex : msgs[1]
if !isempty(msgs) && (isa(msg, Expr) || isa(msg, Symbol))
if isa(msg, AbstractString)
msg = msg # pass-through
elseif !isempty(msgs) && (isa(msg, Expr) || isa(msg, Symbol))
# message is an expression needing evaluating
msg = :(Main.Base.string($(esc(msg))))
elseif isdefined(Main, :Base) && isdefined(Main.Base, :string)
@@ -47,7 +49,7 @@ macro assert(ex, msgs...)
# string() might not be defined during bootstrap
msg = :(Main.Base.string($(Expr(:quote,msg))))
end
:($(esc(ex)) ? $(nothing) : throw(Main.Base.AssertionError($msg)))
return :($(esc(ex)) ? $(nothing) : throw(Main.Base.AssertionError($msg)))
end

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

0 comments on commit 44d7677

Please sign in to comment.