Improve error messages when overloads+coercions do not work
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
fd44ec8d79
commit
e031d7bc10
17 changed files with 188 additions and 24 deletions
|
@ -230,6 +230,7 @@ class elaborator::imp {
|
||||||
args[0] = f_choices[j];
|
args[0] = f_choices[j];
|
||||||
types[0] = f_choice_types[j];
|
types[0] = f_choice_types[j];
|
||||||
good_choices.clear();
|
good_choices.clear();
|
||||||
|
best_num_coercions = num_coercions;
|
||||||
}
|
}
|
||||||
good_choices.push_back(j);
|
good_choices.push_back(j);
|
||||||
}
|
}
|
||||||
|
@ -239,14 +240,20 @@ class elaborator::imp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (good_choices.size() == 0) {
|
if (good_choices.size() == 0) {
|
||||||
// TODO add information to the exception
|
throw no_overload_exception(*m_owner, ctx, src, f_choices.size(), f_choices.data(), f_choice_types.data(),
|
||||||
throw exception("none of the overloads are good");
|
args.size() - 1, args.data() + 1, types.data() + 1);
|
||||||
} else if (good_choices.size() == 1) {
|
} else if (good_choices.size() == 1) {
|
||||||
// found overload
|
// found overload
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
// TODO add information to the exception
|
buffer<expr> good_f_choices;
|
||||||
throw exception("ambiguous overload");
|
buffer<expr> good_f_choice_types;
|
||||||
|
for (unsigned j : good_choices) {
|
||||||
|
good_f_choices.push_back(f_choices[j]);
|
||||||
|
good_f_choice_types.push_back(f_choice_types[j]);
|
||||||
|
}
|
||||||
|
throw ambiguous_overload_exception(*m_owner, ctx, src, good_f_choices.size(), good_f_choices.data(), good_f_choice_types.data(),
|
||||||
|
args.size() - 1, args.data() + 1, types.data() + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,14 +8,37 @@ Author: Leonardo de Moura
|
||||||
#include "lean_elaborator.h"
|
#include "lean_elaborator.h"
|
||||||
|
|
||||||
namespace lean {
|
namespace lean {
|
||||||
|
format pp(formatter fmt, context const & ctx, std::vector<expr> const & exprs, std::vector<expr> const & types, options const & opts) {
|
||||||
|
unsigned indent = get_pp_indent(opts);
|
||||||
|
lean_assert(exprs.size() == types.size());
|
||||||
|
auto it1 = exprs.begin();
|
||||||
|
auto it2 = types.begin();
|
||||||
|
format r;
|
||||||
|
for (; it1 != exprs.end(); ++it1, ++it2) {
|
||||||
|
r += nest(indent, compose(line(), group(format{fmt(ctx, *it1, false, opts), space(), colon(),
|
||||||
|
nest(indent, format{line(), fmt(ctx, *it2, false, opts)})})));
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
format pp(formatter fmt, elaborator_exception const & ex, options const & opts) {
|
format pp(formatter fmt, elaborator_exception const & ex, options const & opts) {
|
||||||
unsigned indent = get_pp_indent(opts);
|
unsigned indent = get_pp_indent(opts);
|
||||||
format expr_f = fmt(ex.get_context(), ex.get_expr(), false, opts);
|
context const & ctx = ex.get_context();
|
||||||
format elb_f = ex.get_elaborator().pp(fmt, opts);
|
if (overload_exception const * _ex = dynamic_cast<overload_exception const *>(&ex)) {
|
||||||
return format({format(ex.what()), space(), format("at term"),
|
format r;
|
||||||
nest(indent, compose(line(), expr_f)),
|
r += format{format(ex.what()), line(), format("Candidates:")};
|
||||||
line(), format("Elaborator state"),
|
r += pp(fmt, ctx, _ex->get_fs(), _ex->get_f_types(), opts);
|
||||||
nest(indent, compose(line(), elb_f))});
|
r += format{line(), format("Arguments:")};
|
||||||
|
r += pp(fmt, ctx, _ex->get_args(), _ex->get_arg_types(), opts);
|
||||||
|
return r;
|
||||||
|
} else {
|
||||||
|
format expr_f = fmt(ctx, ex.get_expr(), false, opts);
|
||||||
|
format elb_f = ex.get_elaborator().pp(fmt, opts);
|
||||||
|
return format({format(ex.what()), space(), format("at term"),
|
||||||
|
nest(indent, compose(line(), expr_f)),
|
||||||
|
line(), format("Elaborator state"),
|
||||||
|
nest(indent, compose(line(), elb_f))});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
regular const & operator<<(regular const & out, elaborator_exception const & ex) {
|
regular const & operator<<(regular const & out, elaborator_exception const & ex) {
|
||||||
|
|
|
@ -55,6 +55,46 @@ public:
|
||||||
virtual char const * what() const noexcept { return "type mismatch during term elaboration"; }
|
virtual char const * what() const noexcept { return "type mismatch during term elaboration"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class overload_exception : public elaborator_exception {
|
||||||
|
std::vector<expr> m_fs;
|
||||||
|
std::vector<expr> m_f_types;
|
||||||
|
std::vector<expr> m_args;
|
||||||
|
std::vector<expr> m_arg_types;
|
||||||
|
public:
|
||||||
|
overload_exception(elaborator const & elb, context const & ctx, expr const & s,
|
||||||
|
unsigned num_fs, expr const * fs, expr const * ftypes,
|
||||||
|
unsigned num_args, expr const * args, expr const * argtypes):
|
||||||
|
elaborator_exception(elb, ctx, s),
|
||||||
|
m_fs(fs, fs + num_fs),
|
||||||
|
m_f_types(ftypes, ftypes + num_fs),
|
||||||
|
m_args(args, args + num_args),
|
||||||
|
m_arg_types(argtypes, argtypes + num_args) {
|
||||||
|
}
|
||||||
|
virtual ~overload_exception() {}
|
||||||
|
std::vector<expr> const & get_fs() const { return m_fs; }
|
||||||
|
std::vector<expr> const & get_f_types() const { return m_f_types; }
|
||||||
|
std::vector<expr> const & get_args() const { return m_args; }
|
||||||
|
std::vector<expr> const & get_arg_types() const { return m_arg_types; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class no_overload_exception : public overload_exception {
|
||||||
|
public:
|
||||||
|
no_overload_exception(elaborator const & elb, context const & ctx, expr const & s,
|
||||||
|
unsigned num_fs, expr const * fs, expr const * ftypes,
|
||||||
|
unsigned num_args, expr const * args, expr const * argtypes):
|
||||||
|
overload_exception(elb, ctx, s, num_fs, fs, ftypes, num_args, args, argtypes) {}
|
||||||
|
virtual char const * what() const noexcept { return "application type mismatch, none of the overloads can be used"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class ambiguous_overload_exception : public overload_exception {
|
||||||
|
public:
|
||||||
|
ambiguous_overload_exception(elaborator const & elb, context const & ctx, expr const & s,
|
||||||
|
unsigned num_fs, expr const * fs, expr const * ftypes,
|
||||||
|
unsigned num_args, expr const * args, expr const * argtypes):
|
||||||
|
overload_exception(elb, ctx, s, num_fs, fs, ftypes, num_args, args, argtypes) {}
|
||||||
|
virtual char const * what() const noexcept { return "ambiguous overloads"; }
|
||||||
|
};
|
||||||
|
|
||||||
format pp(formatter fmt, elaborator_exception const & ex, options const & opts);
|
format pp(formatter fmt, elaborator_exception const & ex, options const & opts);
|
||||||
regular const & operator<<(regular const & out, elaborator_exception const & ex);
|
regular const & operator<<(regular const & out, elaborator_exception const & ex);
|
||||||
diagnostic const & operator<<(diagnostic const & out, elaborator_exception const & ex);
|
diagnostic const & operator<<(diagnostic const & out, elaborator_exception const & ex);
|
||||||
|
|
|
@ -31,6 +31,8 @@ void init_builtin_notation(frontend & f) {
|
||||||
f.add_infixr("\u21D4", 25, mk_iff_fn()); // "⇔"
|
f.add_infixr("\u21D4", 25, mk_iff_fn()); // "⇔"
|
||||||
|
|
||||||
f.add_infixl("+", 65, mk_nat_add_fn());
|
f.add_infixl("+", 65, mk_nat_add_fn());
|
||||||
|
f.add_infixl("-", 65, mk_nat_sub_fn());
|
||||||
|
f.add_prefix("-", 75, mk_nat_neg_fn());
|
||||||
f.add_infixl("*", 70, mk_nat_mul_fn());
|
f.add_infixl("*", 70, mk_nat_mul_fn());
|
||||||
f.add_infix("<=", 50, mk_nat_le_fn());
|
f.add_infix("<=", 50, mk_nat_le_fn());
|
||||||
f.add_infix("\u2264", 50, mk_nat_le_fn()); // ≤
|
f.add_infix("\u2264", 50, mk_nat_le_fn()); // ≤
|
||||||
|
|
|
@ -23,6 +23,7 @@ Author: Leonardo de Moura
|
||||||
#include "lean_pp.h"
|
#include "lean_pp.h"
|
||||||
#include "lean_frontend.h"
|
#include "lean_frontend.h"
|
||||||
#include "lean_coercion.h"
|
#include "lean_coercion.h"
|
||||||
|
#include "lean_elaborator.h"
|
||||||
|
|
||||||
#ifndef LEAN_DEFAULT_PP_MAX_DEPTH
|
#ifndef LEAN_DEFAULT_PP_MAX_DEPTH
|
||||||
#define LEAN_DEFAULT_PP_MAX_DEPTH std::numeric_limits<unsigned>::max()
|
#define LEAN_DEFAULT_PP_MAX_DEPTH std::numeric_limits<unsigned>::max()
|
||||||
|
@ -922,6 +923,22 @@ class pp_fn {
|
||||||
return mk_result(r_format, p_arg.second + p_v.second + 1);
|
return mk_result(r_format, p_arg.second + p_v.second + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result pp_choice(expr const & e, unsigned depth) {
|
||||||
|
lean_assert(is_choice(e));
|
||||||
|
unsigned num = get_num_choices(e);
|
||||||
|
format r_format;
|
||||||
|
unsigned r_weight;
|
||||||
|
for (unsigned i = 0; i < num; i++) {
|
||||||
|
if (i > 0)
|
||||||
|
r_format += format{space(), format("|"), line()};
|
||||||
|
expr const & c = get_choice(e, i);
|
||||||
|
result p_c = pp_child(c, depth);
|
||||||
|
r_weight += p_c.second;
|
||||||
|
r_format += p_c.first;
|
||||||
|
}
|
||||||
|
return mk_result(r_format, r_weight+1);
|
||||||
|
}
|
||||||
|
|
||||||
result pp(expr const & e, unsigned depth, bool main = false) {
|
result pp(expr const & e, unsigned depth, bool main = false) {
|
||||||
check_interrupted(m_interrupted);
|
check_interrupted(m_interrupted);
|
||||||
if (!is_atomic(e) && (m_num_steps > m_max_steps || depth > m_max_depth)) {
|
if (!is_atomic(e) && (m_num_steps > m_max_steps || depth > m_max_depth)) {
|
||||||
|
@ -934,7 +951,9 @@ class pp_fn {
|
||||||
return mk_result(format(it->second), 1);
|
return mk_result(format(it->second), 1);
|
||||||
}
|
}
|
||||||
result r;
|
result r;
|
||||||
if (is_lower(e)) {
|
if (is_choice(e)) {
|
||||||
|
return pp_choice(e, depth);
|
||||||
|
} if (is_lower(e)) {
|
||||||
r = pp_lower(e, depth);
|
r = pp_lower(e, depth);
|
||||||
} else if (is_lift(e)) {
|
} else if (is_lift(e)) {
|
||||||
r = pp_lift(e, depth);
|
r = pp_lift(e, depth);
|
||||||
|
|
|
@ -126,6 +126,8 @@ MK_BUILTIN(nat_le_fn, nat_le_value);
|
||||||
MK_CONSTANT(nat_ge_fn, name({"Nat", "ge"}));
|
MK_CONSTANT(nat_ge_fn, name({"Nat", "ge"}));
|
||||||
MK_CONSTANT(nat_lt_fn, name({"Nat", "lt"}));
|
MK_CONSTANT(nat_lt_fn, name({"Nat", "lt"}));
|
||||||
MK_CONSTANT(nat_gt_fn, name({"Nat", "gt"}));
|
MK_CONSTANT(nat_gt_fn, name({"Nat", "gt"}));
|
||||||
|
MK_CONSTANT(nat_sub_fn, name({"Nat", "sub"}));
|
||||||
|
MK_CONSTANT(nat_neg_fn, name({"Nat", "neg"}));
|
||||||
// =======================================
|
// =======================================
|
||||||
|
|
||||||
// =======================================
|
// =======================================
|
||||||
|
@ -461,6 +463,9 @@ void add_arith_theory(environment & env) {
|
||||||
env.add_definition(int_lt_fn_name, ii_b, Fun({{x, Int}, {y, Int}}, Not(iLe(y, x))));
|
env.add_definition(int_lt_fn_name, ii_b, Fun({{x, Int}, {y, Int}}, Not(iLe(y, x))));
|
||||||
env.add_definition(int_gt_fn_name, ii_b, Fun({{x, Int}, {y, Int}}, Not(iLe(x, y))));
|
env.add_definition(int_gt_fn_name, ii_b, Fun({{x, Int}, {y, Int}}, Not(iLe(x, y))));
|
||||||
|
|
||||||
|
env.add_definition(nat_sub_fn_name, Nat >> (Nat >> Int), Fun({{x, Nat}, {y, Nat}}, iSub(n2i(x), n2i(y))));
|
||||||
|
env.add_definition(nat_neg_fn_name, Nat >> Int, Fun({x, Nat}, iNeg(n2i(x))));
|
||||||
|
|
||||||
env.add_definition(real_sub_fn_name, rr_r, Fun({{x, Real}, {y, Real}}, rAdd(x, rMul(mk_real_value(-1), y))));
|
env.add_definition(real_sub_fn_name, rr_r, Fun({{x, Real}, {y, Real}}, rAdd(x, rMul(mk_real_value(-1), y))));
|
||||||
env.add_definition(real_neg_fn_name, r_r, Fun({x, Real}, rMul(mk_real_value(-1), x)));
|
env.add_definition(real_neg_fn_name, r_r, Fun({x, Real}, rMul(mk_real_value(-1), x)));
|
||||||
env.add_definition(real_ge_fn_name, rr_b, Fun({{x, Real}, {y, Real}}, rLe(y, x)));
|
env.add_definition(real_ge_fn_name, rr_b, Fun({{x, Real}, {y, Real}}, rLe(y, x)));
|
||||||
|
|
|
@ -22,21 +22,35 @@ inline expr nVal(unsigned v) { return mk_nat_value(v); }
|
||||||
bool is_nat_value(expr const & e);
|
bool is_nat_value(expr const & e);
|
||||||
mpz const & nat_value_numeral(expr const & e);
|
mpz const & nat_value_numeral(expr const & e);
|
||||||
|
|
||||||
|
/** \brief Nat::add : Nat -> Nat -> Nat */
|
||||||
expr mk_nat_add_fn();
|
expr mk_nat_add_fn();
|
||||||
inline expr nAdd(expr const & e1, expr const & e2) { return mk_app(mk_nat_add_fn(), e1, e2); }
|
inline expr nAdd(expr const & e1, expr const & e2) { return mk_app(mk_nat_add_fn(), e1, e2); }
|
||||||
|
|
||||||
|
/** \brief Nat::sub : Nat -> Nat -> Int */
|
||||||
|
expr mk_nat_sub_fn();
|
||||||
|
inline expr nSub(expr const & e1, expr const & e2) { return mk_app(mk_nat_sub_fn(), e1, e2); }
|
||||||
|
|
||||||
|
/** \brief Nat::neg : Nat -> Int */
|
||||||
|
expr mk_nat_neg_fn();
|
||||||
|
inline expr nNeg(expr const & e1, expr const & e2) { return mk_app(mk_nat_neg_fn(), e1, e2); }
|
||||||
|
|
||||||
|
/** \brief Nat::mul : Nat -> Nat -> Nat */
|
||||||
expr mk_nat_mul_fn();
|
expr mk_nat_mul_fn();
|
||||||
inline expr nMul(expr const & e1, expr const & e2) { return mk_app(mk_nat_mul_fn(), e1, e2); }
|
inline expr nMul(expr const & e1, expr const & e2) { return mk_app(mk_nat_mul_fn(), e1, e2); }
|
||||||
|
|
||||||
|
/** \brief Nat::le : Nat -> Nat -> Bool */
|
||||||
expr mk_nat_le_fn();
|
expr mk_nat_le_fn();
|
||||||
inline expr nLe(expr const & e1, expr const & e2) { return mk_app(mk_nat_le_fn(), e1, e2); }
|
inline expr nLe(expr const & e1, expr const & e2) { return mk_app(mk_nat_le_fn(), e1, e2); }
|
||||||
|
|
||||||
|
/** \brief Nat::ge : Nat -> Nat -> Bool */
|
||||||
expr mk_nat_ge_fn();
|
expr mk_nat_ge_fn();
|
||||||
inline expr nGe(expr const & e1, expr const & e2) { return mk_app(mk_nat_ge_fn(), e1, e2); }
|
inline expr nGe(expr const & e1, expr const & e2) { return mk_app(mk_nat_ge_fn(), e1, e2); }
|
||||||
|
|
||||||
|
/** \brief Nat::lt : Nat -> Nat -> Bool */
|
||||||
expr mk_nat_lt_fn();
|
expr mk_nat_lt_fn();
|
||||||
inline expr nLt(expr const & e1, expr const & e2) { return mk_app(mk_nat_lt_fn(), e1, e2); }
|
inline expr nLt(expr const & e1, expr const & e2) { return mk_app(mk_nat_lt_fn(), e1, e2); }
|
||||||
|
|
||||||
|
/** \brief Nat::gt : Nat -> Nat -> Bool */
|
||||||
expr mk_nat_gt_fn();
|
expr mk_nat_gt_fn();
|
||||||
inline expr nGt(expr const & e1, expr const & e2) { return mk_app(mk_nat_gt_fn(), e1, e2); }
|
inline expr nGt(expr const & e1, expr const & e2) { return mk_app(mk_nat_gt_fn(), e1, e2); }
|
||||||
|
|
||||||
|
|
|
@ -56,12 +56,12 @@ format formatter::operator()(kernel_exception const & ex, options const & opts)
|
||||||
}
|
}
|
||||||
format arg_type_msg;
|
format arg_type_msg;
|
||||||
if (arg_types.size() > 2)
|
if (arg_types.size() > 2)
|
||||||
arg_type_msg = format("arguments types");
|
arg_type_msg = format("Arguments types:");
|
||||||
else
|
else
|
||||||
arg_type_msg = format("argument type");
|
arg_type_msg = format("Argument type:");
|
||||||
return format({format("type mismatch at application"),
|
return format({format("type mismatch at application"),
|
||||||
nest(indent, compose(line(), app_f)),
|
nest(indent, compose(line(), app_f)),
|
||||||
line(), format("function type"),
|
line(), format("Function type:"),
|
||||||
nest(indent, compose(line(), f_type_fmt)),
|
nest(indent, compose(line(), f_type_fmt)),
|
||||||
line(), arg_type_msg,
|
line(), arg_type_msg,
|
||||||
arg_types_fmt});
|
arg_types_fmt});
|
||||||
|
@ -82,7 +82,7 @@ format formatter::operator()(kernel_exception const & ex, options const & opts)
|
||||||
format value_f = operator()(_ex->get_value_type(), opts);
|
format value_f = operator()(_ex->get_value_type(), opts);
|
||||||
return format({format("type mismatch at definition '"), name_f, format("', expected type"),
|
return format({format("type mismatch at definition '"), name_f, format("', expected type"),
|
||||||
nest(indent, compose(line(), type_f)),
|
nest(indent, compose(line(), type_f)),
|
||||||
line(), format("given type"),
|
line(), format("Given type:"),
|
||||||
nest(indent, compose(line(), value_f))});
|
nest(indent, compose(line(), value_f))});
|
||||||
} else {
|
} else {
|
||||||
return format(ex.what());
|
return format(ex.what());
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
Set pp::colors false
|
||||||
Check 10 + 20
|
Check 10 + 20
|
||||||
Check 10
|
Check 10
|
||||||
Check 10 - 20
|
Check 10 - 20
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
Set: pp::colors
|
||||||
Nat
|
Nat
|
||||||
Nat
|
Nat
|
||||||
Int
|
Int
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
Set pp::colors false
|
||||||
Eval 8 mod 3
|
Eval 8 mod 3
|
||||||
Eval 8 div 4
|
Eval 8 div 4
|
||||||
Eval 7 div 3
|
Eval 7 div 3
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
|
Set: pp::colors
|
||||||
2
|
2
|
||||||
2
|
2
|
||||||
2
|
2
|
||||||
1
|
1
|
||||||
- 8 mod 3
|
- 8 mod 3
|
||||||
Set: lean::pp::notation
|
Set: lean::pp::notation
|
||||||
Int::mod (Int::neg 8) 3
|
Int::mod (Nat::neg 8) 3
|
||||||
-2
|
-2
|
||||||
-8
|
-8
|
||||||
|
|
|
@ -9,9 +9,9 @@ and a b
|
||||||
Assumed: A
|
Assumed: A
|
||||||
Error (line: 12, pos: 11) type mismatch at application
|
Error (line: 12, pos: 11) type mismatch at application
|
||||||
and a A
|
and a A
|
||||||
function type
|
Function type:
|
||||||
Bool -> Bool -> Bool
|
Bool -> Bool -> Bool
|
||||||
arguments types
|
Arguments types:
|
||||||
Bool
|
Bool
|
||||||
Type
|
Type
|
||||||
Variable A : Type
|
Variable A : Type
|
||||||
|
|
|
@ -5,9 +5,9 @@ myeq Bool ⊤ ⊥
|
||||||
Assumed: a
|
Assumed: a
|
||||||
Error (line: 6, pos: 6) type mismatch at application
|
Error (line: 6, pos: 6) type mismatch at application
|
||||||
myeq Bool ⊤ a
|
myeq Bool ⊤ a
|
||||||
function type
|
Function type:
|
||||||
Π (A : Type) (_ _ : A), Bool
|
Π (A : Type) (_ _ : A), Bool
|
||||||
arguments types
|
Arguments types:
|
||||||
Type
|
Type
|
||||||
Bool
|
Bool
|
||||||
T
|
T
|
||||||
|
@ -15,9 +15,9 @@ arguments types
|
||||||
Set: lean::pp::implicit
|
Set: lean::pp::implicit
|
||||||
Error (line: 10, pos: 15) type mismatch at application
|
Error (line: 10, pos: 15) type mismatch at application
|
||||||
myeq2::explicit Bool ⊤ a
|
myeq2::explicit Bool ⊤ a
|
||||||
function type
|
Function type:
|
||||||
Π (A : Type) (a b : A), Bool
|
Π (A : Type) (a b : A), Bool
|
||||||
arguments types
|
Arguments types:
|
||||||
Type
|
Type
|
||||||
Bool
|
Bool
|
||||||
T
|
T
|
||||||
|
|
20
tests/lean/overload2.lean
Normal file
20
tests/lean/overload2.lean
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
Show 1 + true
|
||||||
|
|
||||||
|
Variable R : Type
|
||||||
|
Variable T : Type
|
||||||
|
Variable r2t : R -> T
|
||||||
|
Coercion r2t
|
||||||
|
Variable t2r : T -> R
|
||||||
|
Coercion t2r
|
||||||
|
Variable f : T -> R -> T
|
||||||
|
Variable a : T
|
||||||
|
Variable b : R
|
||||||
|
Set lean::pp::coercion true
|
||||||
|
Set lean::pp::notation false
|
||||||
|
Show f a b
|
||||||
|
Show f b a
|
||||||
|
Variable g : R -> T -> R
|
||||||
|
Infix 10 ++ : f
|
||||||
|
Infix 10 ++ : g
|
||||||
|
Show a ++ b
|
||||||
|
Show b ++ a
|
30
tests/lean/overload2.lean.expected.out
Normal file
30
tests/lean/overload2.lean.expected.out
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
Error (line: 1, pos: 10) application type mismatch, none of the overloads can be used
|
||||||
|
Candidates:
|
||||||
|
Real::add : Real [33m→[0m Real [33m→[0m Real
|
||||||
|
Int::add : Int [33m→[0m Int [33m→[0m Int
|
||||||
|
Nat::add : Nat [33m→[0m Nat [33m→[0m Nat
|
||||||
|
Arguments:
|
||||||
|
1 : Nat
|
||||||
|
⊤ : Bool
|
||||||
|
Assumed: R
|
||||||
|
Assumed: T
|
||||||
|
Assumed: r2t
|
||||||
|
Coercion r2t
|
||||||
|
Assumed: t2r
|
||||||
|
Coercion t2r
|
||||||
|
Assumed: f
|
||||||
|
Assumed: a
|
||||||
|
Assumed: b
|
||||||
|
Set: lean::pp::coercion
|
||||||
|
Set: lean::pp::notation
|
||||||
|
f a b
|
||||||
|
f (r2t b) (t2r a)
|
||||||
|
Assumed: g
|
||||||
|
f a b
|
||||||
|
Error (line: 20, pos: 10) ambiguous overloads
|
||||||
|
Candidates:
|
||||||
|
g : R [33m->[0m T [33m->[0m R
|
||||||
|
f : T [33m->[0m R [33m->[0m T
|
||||||
|
Arguments:
|
||||||
|
b : R
|
||||||
|
a : T
|
|
@ -5,8 +5,8 @@
|
||||||
Assumed: a
|
Assumed: a
|
||||||
Error (line: 6, pos: 6) type mismatch at application
|
Error (line: 6, pos: 6) type mismatch at application
|
||||||
g ⊤ (f _ a a)
|
g ⊤ (f _ a a)
|
||||||
function type
|
Function type:
|
||||||
N → N → Bool
|
N → N → Bool
|
||||||
arguments types
|
Arguments types:
|
||||||
Bool
|
Bool
|
||||||
?M0
|
?M0
|
||||||
|
|
Loading…
Reference in a new issue