feat(frontends/lean/elaborator): report an error when Type becomes a Prop after elaboration, closes #208

This commit is contained in:
Leonardo de Moura 2014-09-29 08:18:10 -07:00
parent fbbd1d25cd
commit 9c55bbb871
3 changed files with 37 additions and 5 deletions

View file

@ -161,12 +161,12 @@ congruence.mk (λx y H, H)
-- Relations that can be coerced to functions / implications
-- ---------------------------------------------------------
inductive mp_like {R : Type → Type → Prop} {a b : Type} (H : R a b) : Prop :=
inductive mp_like {R : Type → Type → Prop} {a b : Type} (H : R a b) : Type :=
mk {} : (a → b) → @mp_like R a b H
namespace mp_like
definition app {R : Type → Type → Prop} {a : Type} {b : Type} {H : R a b}
definition app.{l} {R : Type → Type → Prop} {a : Type} {b : Type} {H : R a b}
(C : mp_like H) : a → b := rec (λx, x) C
definition infer ⦃R : Type → Type → Prop⦄ {a : Type} {b : Type} (H : R a b)

View file

@ -75,7 +75,7 @@ typedef name_map<expr> mvar2meta;
class elaborator : public coercion_info_manager {
typedef name_map<expr> local_tactic_hints;
typedef rb_map<expr, pair<expr, constraint_seq>, expr_quick_cmp> cache;
typedef std::vector<pair<expr, expr>> to_check_sorts;
elaborator_context & m_env;
name_generator m_ngen;
type_checker_ptr m_tc[2];
@ -85,6 +85,9 @@ class elaborator : public coercion_info_manager {
local_context m_full_context; // superset of m_context, it also contains non-contextual locals.
mvar2meta m_mvar2meta;
cache m_cache;
// The following vector contains sorts that we should check
// whether the computed universe is too specific or not.
to_check_sorts m_to_check_sorts;
// mapping from metavariable name ?m to tactic expression that should be used to solve it.
// this mapping is populated by the 'by tactic-expr' expression.
@ -598,7 +601,10 @@ public:
}
expr visit_sort(expr const & e) {
return update_sort(e, replace_univ_placeholder(sort_level(e)));
expr r = update_sort(e, replace_univ_placeholder(sort_level(e)));
if (is_placeholder(sort_level(e)))
m_to_check_sorts.emplace_back(e, r);
return r;
}
expr visit_macro(expr const & e, constraint_seq & cs) {
@ -984,6 +990,30 @@ public:
}
}
/** \brief Check whether the solution found by the elaborator is producing too specific
universes.
\remark For now, we only check if a term Type.{?u} was solved by assigning ?u to 0.
In this case, the user should write Prop instead of Type.
*/
void check_sort_assignments(substitution const & s) {
for (auto const & p : m_to_check_sorts) {
expr pre = p.first;
expr post = p.second;
lean_assert(is_sort(post));
level u = sort_level(post);
lean_assert(is_meta(u));
if (s.is_assigned(u)) {
level r = *s.get_level(u);
if (is_zero(r)) {
throw_kernel_exception(env(), pre, [=](formatter const &) {
return format("solution computed by the elaborator forces Type to be Prop");
});
}
}
}
}
/** \brief Apply substitution and solve remaining metavariables using tactics. */
expr apply(substitution & s, expr const & e, name_set & univ_params, buffer<name> & new_params) {
expr r = s.instantiate(e);
@ -1013,6 +1043,7 @@ public:
auto p = solve(cs).pull();
lean_assert(p);
substitution s = p->first.first;
check_sort_assignments(s);
auto result = apply(s, r);
copy_info_to_manager(s);
return result;
@ -1038,6 +1069,7 @@ public:
auto p = solve(cs).pull();
lean_assert(p);
substitution s = p->first.first;
check_sort_assignments(s);
name_set univ_params = collect_univ_params(r_v, collect_univ_params(r_t));
buffer<name> new_params;
expr new_r_t = apply(s, r_t, univ_params, new_params);

View file

@ -11,7 +11,7 @@ open function
namespace congruence
-- TODO: move this somewhere else
definition reflexive {T : Type} (R : T → T → Type) : Prop := ∀x, R x x
definition reflexive {T : Type} (R : T → T → Prop) : Prop := ∀x, R x x
-- Congruence classes for unary and binary functions
-- -------------------------------------------------