fix(library/unifier): missing occurs check

This commit is contained in:
Leonardo de Moura 2015-12-04 09:14:55 -08:00
parent 2edf91ce42
commit 769da9c95a
6 changed files with 16 additions and 12 deletions

View file

@ -305,16 +305,6 @@ level mk_result_level(environment const & env, buffer<level> const & r_lvls) {
} }
} }
bool occurs(level const & u, level const & l) {
bool found = false;
for_each(l, [&](level const & l) {
if (found) return false;
if (l == u) { found = true; return false; }
return true;
});
return found;
}
/** \brief Functional object for converting the universe metavariables in an expression in new universe parameters. /** \brief Functional object for converting the universe metavariables in an expression in new universe parameters.
The substitution is updated with the mapping metavar -> new param. The substitution is updated with the mapping metavar -> new param.
The set of parameter names m_params and the buffer m_new_params are also updated. The set of parameter names m_params and the buffer m_new_params are also updated.

View file

@ -78,8 +78,6 @@ expr Fun_as_is(buffer<expr> const & locals, expr const & e, parser & p);
expr Pi_as_is(buffer<expr> const & locals, expr const & e, parser & p); expr Pi_as_is(buffer<expr> const & locals, expr const & e, parser & p);
/** \brief Create the resultant universe level using the levels computed during introduction rule elaboration */ /** \brief Create the resultant universe level using the levels computed during introduction rule elaboration */
level mk_result_level(environment const & env, buffer<level> const & r_lvls); level mk_result_level(environment const & env, buffer<level> const & r_lvls);
/** \brief Return true if \c u occurs in \c l */
bool occurs(level const & u, level const & l);
/** \brief Convert the universe metavariables in \c e in new universe parameters. /** \brief Convert the universe metavariables in \c e in new universe parameters.
The substitution \c s is updated with the mapping metavar -> new param. The substitution \c s is updated with the mapping metavar -> new param.

View file

@ -418,6 +418,16 @@ level replace_level_fn::apply(level const & l) {
lean_unreachable(); // LCOV_EXCL_LINE lean_unreachable(); // LCOV_EXCL_LINE
} }
bool occurs(level const & u, level const & l) {
bool found = false;
for_each(l, [&](level const & l) {
if (found) return false;
if (l == u) { found = true; return false; }
return true;
});
return found;
}
optional<name> get_undef_param(level const & l, level_param_names const & ps) { optional<name> get_undef_param(level const & l, level_param_names const & ps) {
optional<name> r; optional<name> r;
for_each(l, [&](level const & l) { for_each(l, [&](level const & l) {

View file

@ -200,6 +200,9 @@ public:
}; };
template<typename F> level replace(level const & l, F const & f) { return replace_level_fn(f)(l); } template<typename F> level replace(level const & l, F const & f) { return replace_level_fn(f)(l); }
/** \brief Return true if \c u occurs in \c l */
bool occurs(level const & u, level const & l);
typedef list<name> level_param_names; typedef list<name> level_param_names;
/** \brief If \c l contains a global that is not in \c env, then return it. Otherwise, return none. */ /** \brief If \c l contains a global that is not in \c env, then return it. Otherwise, return none. */

View file

@ -74,6 +74,7 @@ void substitution::assign(name const & m, expr const & t, justification const &
} }
void substitution::assign(name const & m, level const & l, justification const & j) { void substitution::assign(name const & m, level const & l, justification const & j) {
lean_assert(!::lean::occurs(mk_meta_univ(m), l), m, l);
m_level_subst.insert(m, l); m_level_subst.insert(m, l);
if (!j.is_none()) if (!j.is_none())
m_level_jsts.insert(m, j); m_level_jsts.insert(m, j);

View file

@ -2504,6 +2504,8 @@ struct unifier_fn {
} }
if (!is_meta(m)) if (!is_meta(m))
return Continue; return Continue;
if (occurs(m, lhs))
return Continue;
if (assign(m, lhs, jst)) { if (assign(m, lhs, jst)) {
return Solved; return Solved;
} else { } else {