Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

error hint for getproperty(::Dict, ::Symbol) #54504

Merged
merged 19 commits into from
Jun 12, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion base/boot.jl
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ export
InterruptException, InexactError, OutOfMemoryError, ReadOnlyMemoryError,
OverflowError, StackOverflowError, SegmentationFault, UndefRefError, UndefVarError,
TypeError, ArgumentError, MethodError, AssertionError, LoadError, InitError,
UndefKeywordError, ConcurrencyViolationError,
UndefKeywordError, ConcurrencyViolationError, FieldError,
# AST representation
Expr, QuoteNode, LineNumberNode, GlobalRef,
# object model functions
Expand Down Expand Up @@ -404,6 +404,11 @@ struct AssertionError <: Exception
end
AssertionError() = AssertionError("")

struct FieldError <: Exception
type::DataType
field::Symbol
end

abstract type WrappedException <: Exception end

struct LoadError <: WrappedException
Expand Down
31 changes: 31 additions & 0 deletions base/errorshow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,12 @@ function showerror(io::IO, ex::MethodError)
nothing
end

function showerror(io::IO, exc::FieldError)
@nospecialize
print(io, "FieldError: type $(exc.type |> nameof) has no field $(exc.field)")
Base.Experimental.show_error_hints(io, exc)
end

striptype(::Type{T}) where {T} = T
striptype(::Any) = nothing

Expand Down Expand Up @@ -1086,6 +1092,31 @@ end

Experimental.register_error_hint(methods_on_iterable, MethodError)

# Display a hint in case the user tries to access non-member fields of container type datastructures
function fielderror_hint_handler(io, exc)
@nospecialize
field = exc.field
type = exc.type
if type <: Dict
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be AbstractDict perhaps?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I disagree. I could implement an AbstractDict that forwards getproperty to getindex.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be said "typically" then.

println(io,
"""
\nDid you mean to access dict values using key: `:$field` ?
Consider using indexing syntax.

# Example
julia> dict = Dict(:$(field)=>5)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems odd to use markdown syntax here since this will just get printed to stderr.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, the error hints tend to be quite short and to the point. Something like:

Dictionaries are indexed using the [key] syntax

or something along those lines should be enough.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For most markdown syntax (e.g. code formatting), I agree with you (see above conversation in this PR). However, the single # header is also reasonable plaintext "syntax".

This is a very niche error case (it only happens when you call my_dict.foo) for some my_dict::Dict, so it is unlikely that this will come across as spammy. The only case I can think of where this extended explanation would be unwelcome is if folks are intentionally attempting to access internal Dict fields and also making typos.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's good to keep the styling consistent with the rest of the hints for things to be cohesive. Following the example of * on AbstractString here would be the simplest.

Dict{Symbol, Int64} with 1 entry:
:$(field) => 5
arhik marked this conversation as resolved.
Show resolved Hide resolved

julia> dict[:$(field)]
5
"""
)
end
end

Experimental.register_error_hint(fielderror_hint_handler, FieldError)

# ExceptionStack implementation
size(s::ExceptionStack) = size(s.stack)
getindex(s::ExceptionStack, i::Int) = s.stack[i]
Expand Down
2 changes: 1 addition & 1 deletion base/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -976,7 +976,7 @@ julia> struct Foo
end

julia> Base.fieldindex(Foo, :z)
ERROR: type Foo has no field z
ERROR: FieldError: type Foo has no field z
Stacktrace:
[...]

Expand Down
8 changes: 4 additions & 4 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4080,7 +4080,7 @@ static jl_llvm_functions_t
jl_value_t *rettype,
jl_codegen_params_t &params);

static void emit_hasnofield_error_ifnot(jl_codectx_t &ctx, Value *ok, jl_sym_t *type, jl_cgval_t name);
static void emit_hasnofield_error_ifnot(jl_codectx_t &ctx, Value *ok, jl_datatype_t *type, jl_cgval_t name);

static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f,
ArrayRef<jl_cgval_t> argv, size_t nargs, jl_value_t *rt,
Expand Down Expand Up @@ -4590,15 +4590,15 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f,
assert(jl_svec_len(fn) == 1);
Value *typ_sym = literal_pointer_val(ctx, jl_svecref(fn, 0));
Value *cond = ctx.builder.CreateICmpEQ(mark_callee_rooted(ctx, typ_sym), mark_callee_rooted(ctx, boxed(ctx, fld)));
emit_hasnofield_error_ifnot(ctx, cond, utt->name->name, fld);
emit_hasnofield_error_ifnot(ctx, cond, utt, fld);
*ret = emit_getfield_knownidx(ctx, obj, 0, utt, order);
return true;
}
else {
Value *index = ctx.builder.CreateCall(prepare_call(jlfieldindex_func),
{emit_typeof(ctx, obj, false, false), boxed(ctx, fld), ConstantInt::get(getInt32Ty(ctx.builder.getContext()), 0)});
Value *cond = ctx.builder.CreateICmpNE(index, ConstantInt::get(getInt32Ty(ctx.builder.getContext()), -1));
emit_hasnofield_error_ifnot(ctx, cond, utt->name->name, fld);
emit_hasnofield_error_ifnot(ctx, cond, utt, fld);
Value *idx2 = ctx.builder.CreateAdd(ctx.builder.CreateIntCast(index, ctx.types().T_size, false), ConstantInt::get(ctx.types().T_size, 1)); // getfield_unknown is 1 based
if (emit_getfield_unknownidx(ctx, ret, obj, idx2, utt, jl_false, order))
return true;
Expand Down Expand Up @@ -5429,7 +5429,7 @@ static jl_cgval_t emit_call(jl_codectx_t &ctx, jl_expr_t *ex, jl_value_t *rt, bo

// --- accessing and assigning variables ---

static void emit_hasnofield_error_ifnot(jl_codectx_t &ctx, Value *ok, jl_sym_t *type, jl_cgval_t name)
static void emit_hasnofield_error_ifnot(jl_codectx_t &ctx, Value *ok, jl_datatype_t *type, jl_cgval_t name)
{
++EmittedUndefVarErrors;
assert(name.typ == (jl_value_t*)jl_symbol_type);
Expand Down
2 changes: 1 addition & 1 deletion src/datatype.c
Original file line number Diff line number Diff line change
Expand Up @@ -1736,7 +1736,7 @@ JL_DLLEXPORT int jl_field_index(jl_datatype_t *t, jl_sym_t *fld, int err)
}
}
if (err)
jl_has_no_field_error(t->name->name, fld);
jl_has_no_field_error(t, fld);
return -1;
}

Expand Down
1 change: 1 addition & 0 deletions src/jl_exported_data.inc
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@
XX(jl_uint8_type) \
XX(jl_undefref_exception) \
XX(jl_undefvarerror_type) \
XX(jl_fielderror_type) \
XX(jl_unionall_type) \
XX(jl_uniontype_type) \
XX(jl_upsilonnode_type) \
Expand Down
1 change: 1 addition & 0 deletions src/jltypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -3727,6 +3727,7 @@ void post_boot_hooks(void)
jl_diverror_exception = jl_new_struct_uninit((jl_datatype_t*)core("DivideError"));
jl_undefref_exception = jl_new_struct_uninit((jl_datatype_t*)core("UndefRefError"));
jl_undefvarerror_type = (jl_datatype_t*)core("UndefVarError");
jl_fielderror_type = (jl_datatype_t*)core("FieldError");
jl_atomicerror_type = (jl_datatype_t*)core("ConcurrencyViolationError");
jl_interrupt_exception = jl_new_struct_uninit((jl_datatype_t*)core("InterruptException"));
jl_boundserror_type = (jl_datatype_t*)core("BoundsError");
Expand Down
3 changes: 2 additions & 1 deletion src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -869,6 +869,7 @@ extern JL_DLLIMPORT jl_datatype_t *jl_initerror_type JL_GLOBALLY_ROOTED;
extern JL_DLLIMPORT jl_datatype_t *jl_typeerror_type JL_GLOBALLY_ROOTED;
extern JL_DLLIMPORT jl_datatype_t *jl_methoderror_type JL_GLOBALLY_ROOTED;
extern JL_DLLIMPORT jl_datatype_t *jl_undefvarerror_type JL_GLOBALLY_ROOTED;
extern JL_DLLIMPORT jl_datatype_t *jl_fielderror_type JL_GLOBALLY_ROOTED;
extern JL_DLLIMPORT jl_datatype_t *jl_atomicerror_type JL_GLOBALLY_ROOTED;
extern JL_DLLIMPORT jl_datatype_t *jl_missingcodeerror_type JL_GLOBALLY_ROOTED;
extern JL_DLLIMPORT jl_datatype_t *jl_lineinfonode_type JL_GLOBALLY_ROOTED;
Expand Down Expand Up @@ -2024,7 +2025,7 @@ JL_DLLEXPORT void JL_NORETURN jl_type_error_rt(const char *fname,
jl_value_t *ty JL_MAYBE_UNROOTED,
jl_value_t *got JL_MAYBE_UNROOTED);
JL_DLLEXPORT void JL_NORETURN jl_undefined_var_error(jl_sym_t *var, jl_value_t *scope JL_MAYBE_UNROOTED);
JL_DLLEXPORT void JL_NORETURN jl_has_no_field_error(jl_sym_t *type_name, jl_sym_t *var);
JL_DLLEXPORT void JL_NORETURN jl_has_no_field_error(jl_datatype_t *t, jl_sym_t *var);
JL_DLLEXPORT void JL_NORETURN jl_atomic_error(char *str);
JL_DLLEXPORT void JL_NORETURN jl_bounds_error(jl_value_t *v JL_MAYBE_UNROOTED,
jl_value_t *t JL_MAYBE_UNROOTED);
Expand Down
4 changes: 2 additions & 2 deletions src/rtutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,9 +152,9 @@ JL_DLLEXPORT void JL_NORETURN jl_undefined_var_error(jl_sym_t *var, jl_value_t *
jl_throw(jl_new_struct(jl_undefvarerror_type, var, scope));
}

JL_DLLEXPORT void JL_NORETURN jl_has_no_field_error(jl_sym_t *type_name, jl_sym_t *var)
JL_DLLEXPORT void JL_NORETURN jl_has_no_field_error(jl_datatype_t *t, jl_sym_t *var)
{
jl_errorf("type %s has no field %s", jl_symbol_name(type_name), jl_symbol_name(var));
jl_throw(jl_new_struct(jl_fielderror_type, t, var));
}

JL_DLLEXPORT void JL_NORETURN jl_atomic_error(char *str) // == jl_exceptionf(jl_atomicerror_type, "%s", str)
Expand Down
3 changes: 2 additions & 1 deletion src/staticdata.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ extern "C" {
// TODO: put WeakRefs on the weak_refs list during deserialization
// TODO: handle finalizers

#define NUM_TAGS 190
#define NUM_TAGS 191

// An array of references that need to be restored from the sysimg
// This is a manually constructed dual of the gvars array, which would be produced by codegen for Julia code, for C.
Expand Down Expand Up @@ -235,6 +235,7 @@ jl_value_t **const*const get_tags(void) {
INSERT_TAG(jl_loaderror_type);
INSERT_TAG(jl_initerror_type);
INSERT_TAG(jl_undefvarerror_type);
INSERT_TAG(jl_fielderror_type);
INSERT_TAG(jl_stackovf_exception);
INSERT_TAG(jl_diverror_exception);
INSERT_TAG(jl_interrupt_exception);
Expand Down
2 changes: 1 addition & 1 deletion stdlib/LinearAlgebra/test/bunchkaufman.jl
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ bimint = rand(1:5, n, 2)
bc1 = bunchkaufman(Symmetric(asym, uplo))
@test getproperty(bc1, uplo)*bc1.D*transpose(getproperty(bc1, uplo)) ≈ asym[bc1.p, bc1.p]
@test getproperty(bc1, uplo)*bc1.D*transpose(getproperty(bc1, uplo)) ≈ bc1.P*asym*transpose(bc1.P)
@test_throws ErrorException bc1.Z
@test_throws FieldError bc1.Z
@test_throws ArgumentError uplo === :L ? bc1.U : bc1.L
end
# test Base.iterate
Expand Down
2 changes: 1 addition & 1 deletion stdlib/LinearAlgebra/test/cholesky.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ function unary_ops_tests(a, ca, tol; n=size(a, 1))
@test logabsdet_ca[1] ≈ logabsdet_a[1]
@test logabsdet_ca[2] ≈ logabsdet_a[2]
@test isposdef(ca)
@test_throws ErrorException ca.Z
@test_throws FieldError ca.Z
@test size(ca) == size(a)
@test Array(copy(ca)) ≈ a
@test tr(ca) ≈ tr(a) skip=ca isa CholeskyPivoted
Expand Down
4 changes: 2 additions & 2 deletions stdlib/LinearAlgebra/test/eigen.jl
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ aimg = randn(n,n)/2
@test eigvecs(asym_sg, ASG2) == f.vectors
@test eigvals(f) === f.values
@test eigvecs(f) === f.vectors
@test_throws ErrorException f.Z
@test_throws FieldError f.Z

d,v = eigen(asym_sg, ASG2)
@test d == f.values
Expand Down Expand Up @@ -141,7 +141,7 @@ aimg = randn(n,n)/2
@test f.values ≈ eigvals(a1_nsg, a2_nsg; sortby = sortfunc)
@test prod(f.values) ≈ prod(eigvals(a1_nsg/a2_nsg, sortby = sortfunc)) atol=50000ε
@test eigvecs(a1_nsg, a2_nsg; sortby = sortfunc) == f.vectors
@test_throws ErrorException f.Z
@test_throws FieldError f.Z

g = eigen(a1_nsg, Diagonal(1:n1))
@test a1_nsg*g.vectors ≈ (Diagonal(1:n1)*g.vectors) * Diagonal(g.values)
Expand Down
2 changes: 1 addition & 1 deletion stdlib/LinearAlgebra/test/hessenberg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ let n = 10
@test size(H.Q, 2) == size(A, 2)
@test size(H.Q) == size(A)
@test size(H) == size(A)
@test_throws ErrorException H.Z
@test_throws FieldError H.Z
@test convert(Array, H) ≈ A
@test (H.Q * H.H) * H.Q' ≈ A ≈ (Matrix(H.Q) * Matrix(H.H)) * Matrix(H.Q)'
@test (H.Q' * A) * H.Q ≈ H.H
Expand Down
2 changes: 1 addition & 1 deletion stdlib/LinearAlgebra/test/lq.jl
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ rectangularQ(Q::LinearAlgebra.LQPackedQ) = convert(Array, Q)
for (ii, lq_obj) in enumerate(lqa)
@test ref_obs[ii] == lq_obj
end
@test_throws ErrorException lqa.Z
@test_throws FieldError lqa.Z
@test Array(copy(adjoint(lqa))) ≈ a'
@test q*squareQ(q)' ≈ Matrix(I, n, n)
@test l*q ≈ a
Expand Down
4 changes: 2 additions & 2 deletions stdlib/LinearAlgebra/test/lu.jl
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ dimg = randn(n)/2
κ = cond(a,1)
@testset "(Automatic) Square LU decomposition" begin
lua = factorize(a)
@test_throws ErrorException lua.Z
@test_throws FieldError lua.Z
l,u,p = lua.L, lua.U, lua.p
ll,ul,pl = @inferred lu(a)
@test ll * ul ≈ a[pl,:]
Expand Down Expand Up @@ -88,7 +88,7 @@ dimg = randn(n)/2
lud = @inferred lu(d)
@test LinearAlgebra.issuccess(lud)
@test @inferred(lu(lud)) == lud
@test_throws ErrorException lud.Z
@test_throws FieldError lud.Z
@test lud.L*lud.U ≈ lud.P*Array(d)
@test lud.L*lud.U ≈ Array(d)[lud.p,:]
@test AbstractArray(lud) ≈ d
Expand Down
8 changes: 4 additions & 4 deletions stdlib/LinearAlgebra/test/qr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ rectangularQ(Q::LinearAlgebra.AbstractQ) = Matrix(Q)
@testset "QR decomposition (without pivoting)" begin
qra = @inferred qr(a)
q, r = qra.Q, qra.R
@test_throws ErrorException qra.Z
@test_throws FieldError qra.Z
@test q'*squareQ(q) ≈ Matrix(I, a_1, a_1)
@test q*squareQ(q)' ≈ Matrix(I, a_1, a_1)
@test q'*Matrix(1.0I, a_1, a_1)' ≈ squareQ(q)'
Expand Down Expand Up @@ -79,7 +79,7 @@ rectangularQ(Q::LinearAlgebra.AbstractQ) = Matrix(Q)
@testset "Thin QR decomposition (without pivoting)" begin
qra = @inferred qr(a[:, 1:n1], NoPivot())
q,r = qra.Q, qra.R
@test_throws ErrorException qra.Z
@test_throws FieldError qra.Z
@test q'*squareQ(q) ≈ Matrix(I, a_1, a_1)
@test q'*rectangularQ(q) ≈ Matrix(I, a_1, n1)
@test q*r ≈ a[:, 1:n1]
Expand All @@ -106,7 +106,7 @@ rectangularQ(Q::LinearAlgebra.AbstractQ) = Matrix(Q)

qrpa = factorize(a[1:n1,:])
q,r = qrpa.Q, qrpa.R
@test_throws ErrorException qrpa.Z
@test_throws FieldError qrpa.Z
p = qrpa.p
@test q'*squareQ(q) ≈ Matrix(I, n1, n1)
@test q*squareQ(q)' ≈ Matrix(I, n1, n1)
Expand Down Expand Up @@ -134,7 +134,7 @@ rectangularQ(Q::LinearAlgebra.AbstractQ) = Matrix(Q)
@testset "(Automatic) Thin (pivoted) QR decomposition" begin
qrpa = factorize(a[:,1:n1])
q,r = qrpa.Q, qrpa.R
@test_throws ErrorException qrpa.Z
@test_throws FieldError qrpa.Z
p = qrpa.p
@test q'*squareQ(q) ≈ Matrix(I, a_1, a_1)
@test q*squareQ(q)' ≈ Matrix(I, a_1, a_1)
Expand Down
6 changes: 3 additions & 3 deletions stdlib/LinearAlgebra/test/schur.jl
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ aimg = randn(n,n)/2
@test sort(imag(f.values)) ≈ sort(imag(d))
@test istriu(f.Schur) || eltype(a)<:Real
@test convert(Array, f) ≈ a
@test_throws ErrorException f.A
@test_throws FieldError f.A

sch, vecs, vals = schur(UpperTriangular(triu(a)))
@test vecs*sch*vecs' ≈ triu(a)
Expand Down Expand Up @@ -68,7 +68,7 @@ aimg = randn(n,n)/2
O = ordschur(S, select)
sum(select) != 0 && @test S.values[findall(select)] ≈ O.values[1:sum(select)]
@test O.vectors*O.Schur*O.vectors' ≈ ordschura
@test_throws ErrorException f.A
@test_throws FieldError f.A
Snew = LinearAlgebra.Schur(S.T, S.Z, S.values)
SchurNew = ordschur!(copy(Snew), select)
@test O.vectors ≈ SchurNew.vectors
Expand All @@ -88,7 +88,7 @@ aimg = randn(n,n)/2
@test f.Q*f.T*f.Z' ≈ a2_sf
@test istriu(f.S) || eltype(a)<:Real
@test istriu(f.T) || eltype(a)<:Real
@test_throws ErrorException f.A
@test_throws FieldError f.A

sstring = sprint((t, s) -> show(t, "text/plain", s), f.S)
tstring = sprint((t, s) -> show(t, "text/plain", s), f.T)
Expand Down
10 changes: 5 additions & 5 deletions stdlib/LinearAlgebra/test/svd.jl
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ aimg = randn(n,n)/2
@test usv.U * (Diagonal(usv.S) * usv.Vt) ≈ a
@test convert(Array, usv) ≈ a
@test usv.Vt' ≈ usv.V
@test_throws ErrorException usv.Z
@test_throws FieldError usv.Z
b = rand(eltya,n)
@test usv\b ≈ a\b
@test Base.propertynames(usv) == (:U, :S, :V, :Vt)
Expand All @@ -94,7 +94,7 @@ aimg = randn(n,n)/2
@test usv.U * (Diagonal(usv.S) * usv.Vt) ≈ transform(a)
@test convert(Array, usv) ≈ transform(a)
@test usv.Vt' ≈ usv.V
@test_throws ErrorException usv.Z
@test_throws FieldError usv.Z
b = rand(eltya,n)
@test usv\b ≈ transform(a)\b
end
Expand All @@ -106,8 +106,8 @@ aimg = randn(n,n)/2
@test gsvd.U*gsvd.D1*gsvd.R*gsvd.Q' ≈ a
@test gsvd.V*gsvd.D2*gsvd.R*gsvd.Q' ≈ a_svd
@test usv.Vt' ≈ usv.V
@test_throws ErrorException usv.Z
@test_throws ErrorException gsvd.Z
@test_throws FieldError usv.Z
@test_throws FieldError gsvd.Z
@test gsvd.vals ≈ svdvals(a,a_svd)
α = eltya == Int ? -1 : rand(eltya)
β = svd(α)
Expand Down Expand Up @@ -148,7 +148,7 @@ aimg = randn(n,n)/2
@test usv.U * (Diagonal(usv.S) * usv.Vt) ≈ T(asym)
@test convert(Array, usv) ≈ T(asym)
@test usv.Vt' ≈ usv.V
@test_throws ErrorException usv.Z
@test_throws FieldError usv.Z
b = rand(eltya,n)
@test usv\b ≈ T(asym)\b
end
Expand Down
2 changes: 1 addition & 1 deletion test/compiler/codegen.jl
Original file line number Diff line number Diff line change
Expand Up @@ -859,7 +859,7 @@ foo50964(1) # Shouldn't assert!

# https://github.com/JuliaLang/julia/issues/51233
obj51233 = (1,)
@test_throws ErrorException obj51233.x
@test_throws FieldError obj51233.x

# Very specific test for multiversioning
if Sys.ARCH === :x86_64
Expand Down
2 changes: 1 addition & 1 deletion test/compiler/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,7 @@ end
@test f15259(1,2) == (1,2,1,2)
# check that error cases are still correct
@eval g15259(x,y) = (a = $(Expr(:new, :A15259, :x, :y)); a.z)
@test_throws ErrorException g15259(1,1)
@test_throws FieldError g15259(1,1)
@eval h15259(x,y) = (a = $(Expr(:new, :A15259, :x, :y)); getfield(a, 3))
@test_throws BoundsError h15259(1,1)

Expand Down
6 changes: 3 additions & 3 deletions test/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1924,9 +1924,9 @@ end

# issue #4526
f4526(x) = isa(x.a, Nothing)
@test_throws ErrorException f4526(1)
@test_throws ErrorException f4526(im)
@test_throws ErrorException f4526(1+2im)
@test_throws FieldError f4526(1)
@test_throws FieldError f4526(im)
@test_throws FieldError f4526(1+2im)

# issue #4528
function f4528(A, B)
Expand Down
Loading