format pp(level l, bool unicode, unsigned indent) { if (is_explicit(l)) { lean_assert(get_depth(l) > 0); return format(get_depth(l) - 1); } else { switch (kind(l)) { case level_kind::Zero: lean_unreachable(); // LCOV_EXCL_LINE case level_kind::Param: case level_kind::Global: return format(to_param_core(l).m_id); case level_kind::Meta: return format("?") + format(meta_id(l)); case level_kind::Succ: { auto p = to_offset(l); return pp_child(p.first, unicode, indent) + format("+") + format(p.second); } case level_kind::Max: case level_kind::IMax: { format r = format(is_max(l) ? "max" : "imax"); r += nest(indent, compose(line(), pp_child(to_max_core(l).m_lhs, unicode, indent))); // max and imax are right associative while (kind(to_max_core(l).m_rhs) == kind(l)) { l = to_max_core(l).m_rhs; r += nest(indent, compose(line(), pp_child(to_max_core(l).m_lhs, unicode, indent))); } r += nest(indent, compose(line(), pp_child(to_max_core(l).m_rhs, unicode, indent))); return group(r); }} lean_unreachable(); // LCOV_EXCL_LINE } }
// Monotonic total order on universe level terms. bool is_lt(level const & a, level const & b, bool use_hash) { if (is_eqp(a, b)) return false; unsigned da = get_depth(a); unsigned db = get_depth(b); if (da < db) return true; if (da > db) return false; if (kind(a) != kind(b)) return kind(a) < kind(b); if (use_hash) { if (hash(a) < hash(b)) return true; if (hash(a) > hash(b)) return false; } if (a == b) return false; switch (kind(a)) { case level_kind::Zero: lean_unreachable(); // LCOV_EXCL_LINE case level_kind::Param: case level_kind::Global: case level_kind::Meta: return to_param_core(a).m_id < to_param_core(b).m_id; case level_kind::Max: case level_kind::IMax: if (to_max_core(a).m_lhs != to_max_core(b).m_lhs) return is_lt(to_max_core(a).m_lhs, to_max_core(b).m_lhs, use_hash); else return is_lt(to_max_core(a).m_rhs, to_max_core(b).m_rhs, use_hash); case level_kind::Succ: return is_lt(succ_of(a), succ_of(b), use_hash); } lean_unreachable(); // LCOV_EXCL_LINE }
bool operator==(level const & l1, level const & l2) { if (kind(l1) != kind(l2)) return false; if (hash(l1) != hash(l2)) return false; if (is_eqp(l1, l2)) return true; switch (kind(l1)) { case level_kind::Zero: return true; case level_kind::Param: case level_kind::Global: case level_kind::Meta: return to_param_core(l1).m_id == to_param_core(l2).m_id; case level_kind::Max: case level_kind::IMax: case level_kind::Succ: if (to_composite(l1).m_depth != to_composite(l2).m_depth) return false; break; } switch (kind(l1)) { case level_kind::Zero: case level_kind::Param: case level_kind::Global: case level_kind::Meta: lean_unreachable(); // LCOV_EXCL_LINE case level_kind::Max: case level_kind::IMax: return to_max_core(l1).m_lhs == to_max_core(l2).m_lhs && to_max_core(l1).m_rhs == to_max_core(l2).m_rhs; case level_kind::Succ: if (is_explicit(l1) != is_explicit(l2)) { return false; } else if (is_explicit(l1)) { lean_assert(get_depth(l1) == get_depth(l2)); // the depths are equal, then l1 and l2 must be the same universe return true; } else { return succ_of(l1) == succ_of(l2); } } lean_unreachable(); // LCOV_EXCL_LINE }
void forward_branch_extension::index_expr(expr const & e) { // TODO(dhs): index the target when it gets updated if (auto head_idx = to_head_index(e)) { m_index.insert(head_index(e), e); } switch (e.kind()) { case expr_kind::Var: lean_unreachable(); // LCOV_EXCL_LINE case expr_kind::Local: case expr_kind::Meta: case expr_kind::Sort: case expr_kind::Constant: case expr_kind::Macro: // TODO(dhs): do I unfold macros? break; case expr_kind::Lambda: case expr_kind::Pi: // TODO(dhs): confirm that I only index quantified-free hypotheses break; case expr_kind::Let: // Let-expressions must be unfolded before invoking this method lean_unreachable(); case expr_kind::App: index_expr(app_fn(e)); index_expr(app_arg(e)); break; } }
bool is_lt_no_level_params(level const & a, level const & b) { if (is_eqp(a, b)) return false; if (kind(a) != kind(b)) { if (kind(a) == level_kind::Param || kind(b) == level_kind::Param) return false; return kind(a) < kind(b); } switch (kind(a)) { case level_kind::Zero: lean_unreachable(); // LCOV_EXCL_LINE case level_kind::Param: return false; case level_kind::Global: return global_id(a) < global_id(b); case level_kind::Meta: return meta_id(a) < meta_id(b); case level_kind::Max: if (is_lt_no_level_params(max_lhs(a), max_lhs(b))) return true; else if (is_lt_no_level_params(max_lhs(b), max_lhs(a))) return false; else return is_lt_no_level_params(max_rhs(a), max_rhs(b)); case level_kind::IMax: if (is_lt_no_level_params(imax_lhs(a), imax_lhs(b))) return true; else if (is_lt_no_level_params(imax_lhs(b), imax_lhs(a))) return false; else return is_lt_no_level_params(imax_rhs(a), imax_rhs(b)); case level_kind::Succ: return is_lt_no_level_params(succ_of(a), succ_of(b)); } lean_unreachable(); }
expr visit(expr const & e) { switch (e.kind()) { case expr_kind::Sort: case expr_kind::Constant: case expr_kind::Var: case expr_kind::Meta: case expr_kind::Local: return e; default: break; } check_system("unfold macros"); auto it = m_cache.find(e); if (it != m_cache.end()) return it->second; switch (e.kind()) { case expr_kind::Sort: case expr_kind::Constant: case expr_kind::Var: case expr_kind::Meta: case expr_kind::Local: lean_unreachable(); case expr_kind::Macro: return save_result(e, visit_macro(e)); case expr_kind::App: return save_result(e, visit_app(e)); case expr_kind::Lambda: case expr_kind::Pi: return save_result(e, visit_binding(e)); } lean_unreachable(); }
bool apply(expr const & a, expr const & b) { if (is_eqp(a, b)) return true; if (a.hash() != b.hash()) return false; if (a.kind() != b.kind()) return false; if (is_var(a)) return var_idx(a) == var_idx(b); if (m_cache.check(a, b)) return true; switch (a.kind()) { case expr_kind::Var: lean_unreachable(); // LCOV_EXCL_LINE case expr_kind::Constant: return const_name(a) == const_name(b) && compare(const_levels(a), const_levels(b), [](level const & l1, level const & l2) { return l1 == l2; }); case expr_kind::Meta: return mlocal_name(a) == mlocal_name(b) && apply(mlocal_type(a), mlocal_type(b)); case expr_kind::Local: return mlocal_name(a) == mlocal_name(b) && apply(mlocal_type(a), mlocal_type(b)) && (!CompareBinderInfo || local_pp_name(a) == local_pp_name(b)) && (!CompareBinderInfo || local_info(a) == local_info(b)); case expr_kind::App: check_system(); return apply(app_fn(a), app_fn(b)) && apply(app_arg(a), app_arg(b)); case expr_kind::Lambda: case expr_kind::Pi: check_system(); return apply(binding_domain(a), binding_domain(b)) && apply(binding_body(a), binding_body(b)) && (!CompareBinderInfo || binding_name(a) == binding_name(b)) && (!CompareBinderInfo || binding_info(a) == binding_info(b)); case expr_kind::Let: check_system(); return apply(let_type(a), let_type(b)) && apply(let_value(a), let_value(b)) && apply(let_body(a), let_body(b)) && (!CompareBinderInfo || let_name(a) == let_name(b)); case expr_kind::Sort: return sort_level(a) == sort_level(b); case expr_kind::Macro: check_system(); if (macro_def(a) != macro_def(b) || macro_num_args(a) != macro_num_args(b)) return false; for (unsigned i = 0; i < macro_num_args(a); i++) { if (!apply(macro_arg(a, i), macro_arg(b, i))) return false; } return true; } lean_unreachable(); // LCOV_EXCL_LINE }
bool expr_eq_fn::apply(expr const & a, expr const & b) { if (is_eqp(a, b)) return true; if (a.hash() != b.hash()) return false; if (a.kind() != b.kind()) return false; if (is_var(a)) return var_idx(a) == var_idx(b); if (m_counter >= LEAN_EQ_CACHE_THRESHOLD && is_shared(a) && is_shared(b)) { auto p = std::make_pair(a.raw(), b.raw()); if (!m_eq_visited) m_eq_visited.reset(new expr_cell_pair_set); if (m_eq_visited->find(p) != m_eq_visited->end()) return true; m_eq_visited->insert(p); } check_system("expression equality test"); switch (a.kind()) { case expr_kind::Var: lean_unreachable(); // LCOV_EXCL_LINE case expr_kind::Constant: return const_name(a) == const_name(b) && compare(const_levels(a), const_levels(b), [](level const & l1, level const & l2) { return l1 == l2; }); case expr_kind::Local: case expr_kind::Meta: return mlocal_name(a) == mlocal_name(b) && apply(mlocal_type(a), mlocal_type(b)); case expr_kind::App: m_counter++; return apply(app_fn(a), app_fn(b)) && apply(app_arg(a), app_arg(b)); case expr_kind::Lambda: case expr_kind::Pi: m_counter++; return apply(binding_domain(a), binding_domain(b)) && apply(binding_body(a), binding_body(b)) && (!m_compare_binder_info || binding_info(a) == binding_info(b)); case expr_kind::Sort: return sort_level(a) == sort_level(b); case expr_kind::Macro: m_counter++; if (macro_def(a) != macro_def(b) || macro_num_args(a) != macro_num_args(b)) return false; for (unsigned i = 0; i < macro_num_args(a); i++) { if (!apply(macro_arg(a, i), macro_arg(b, i))) return false; } return true; case expr_kind::Let: m_counter++; return apply(let_type(a), let_type(b)) && apply(let_value(a), let_value(b)) && apply(let_body(a), let_body(b)); } lean_unreachable(); // LCOV_EXCL_LINE }
unsigned abstract_expr_manager::hash(expr const & e) { unsigned h; switch (e.kind()) { case expr_kind::Constant: case expr_kind::Local: case expr_kind::Meta: case expr_kind::Sort: case expr_kind::Var: case expr_kind::Macro: return e.hash(); case expr_kind::Lambda: case expr_kind::Pi: h = hash(binding_domain(e)); // Remark binding_domain(e) may contain de-bruijn variables. // We can instantiate them eagerly as we do here, or lazily. // The lazy approach is potentially more efficient, but we would have // to use something more sophisticated than an instantiate_rev at expr_kind::App m_locals.push_back(instantiate_rev(m_tctx.mk_tmp_local(binding_domain(e)), m_locals.size(), m_locals.data())); h = ::lean::hash(h, hash(binding_body(e))); m_locals.pop_back(); return h; case expr_kind::Let: // Let-expressions must be unfolded before invoking this method lean_unreachable(); case expr_kind::App: buffer<expr> args; expr const & f = get_app_args(e, args); unsigned prefix_sz = m_congr_lemma_manager.get_specialization_prefix_size(instantiate_rev(f, m_locals.size(), m_locals.data()), args.size()); expr new_f = e; unsigned rest_sz = args.size() - prefix_sz; for (unsigned i = 0; i < rest_sz; i++) new_f = app_fn(new_f); new_f = instantiate_rev(new_f, m_locals.size(), m_locals.data()); optional<congr_lemma> congr = m_congr_lemma_manager.mk_congr(new_f, rest_sz); h = hash(new_f); if (!congr) { for (unsigned i = prefix_sz; i < args.size(); i++) { h = ::lean::hash(h, hash(args[i])); } } else { lean_assert(length(congr->get_arg_kinds()) == rest_sz); unsigned i = prefix_sz; for_each(congr->get_arg_kinds(), [&](congr_arg_kind const & c_kind) { if (c_kind != congr_arg_kind::Cast) { h = ::lean::hash(h, hash(args[i])); } i++; }); } return h; } lean_unreachable(); }
void visit(expr const & e) { switch (e.kind()) { case expr_kind::Sort: return; case expr_kind::Macro: visit_macro(e); return; case expr_kind::Constant: visit_constant(e); return; case expr_kind::Var: lean_unreachable(); case expr_kind::Meta: lean_unreachable(); case expr_kind::Local: return; case expr_kind::App: visit_app(e); return; case expr_kind::Lambda: visit_binding(e); return; case expr_kind::Pi: visit_binding(e); return; case expr_kind::Let: visit_let(e); return; } }
static void print(std::ostream & out, level l) { if (is_explicit(l)) { lean_assert(get_depth(l) > 0); out << get_depth(l) - 1; } else { switch (kind(l)) { case level_kind::Zero: lean_unreachable(); // LCOV_EXCL_LINE case level_kind::Param: case level_kind::Global: out << to_param_core(l).m_id; break; case level_kind::Meta: out << "?" << meta_id(l); break; case level_kind::Succ: out << "succ "; print_child(out, succ_of(l)); break; case level_kind::Max: case level_kind::IMax: if (is_max(l)) out << "max "; else out << "imax "; print_child(out, to_max_core(l).m_lhs); // max and imax are right associative while (kind(to_max_core(l).m_rhs) == kind(l)) { l = to_max_core(l).m_rhs; out << " "; print_child(out, to_max_core(l).m_lhs); } out << " "; print_child(out, to_max_core(l).m_rhs); break; } } }
bool mt_task_queue::check_deps(gtask const & t) { check_stack("mt_task_queue::check_deps"); lean_always_assert(get_data(t)); buffer<gtask> deps; try { get_data(t)->m_imp->get_dependencies(deps); } catch (...) {} auto prio = get_prio(t); for (auto & dep : deps) { if (dep) { submit_core(dep, prio); bump_prio(dep, prio); } } for (auto & dep : deps) { if (!dep) continue; switch (get_state(dep).load()) { case task_state::Waiting: case task_state::Queued: case task_state::Running: lean_always_assert(get_imp(dep)); get_sched_info(dep).m_reverse_deps.push_back(t); return false; case task_state::Success: break; case task_state::Failed: break; default: lean_unreachable(); } } return true; }
void mt_task_queue::bump_prio(gtask const & t, unsigned new_prio) { switch (get_state(t).load()) { case task_state::Queued: if (new_prio < get_prio(t)) { auto prio = get_prio(t); auto &q = m_queue[prio]; auto it = std::find(q.begin(), q.end(), t); lean_always_assert(it != q.end()); q.erase(it); if (q.empty()) m_queue.erase(prio); get_prio(t) = std::min(get_prio(t), new_prio); check_deps(t); enqueue(t); } break; case task_state::Waiting: if (new_prio < get_prio(t)) { get_prio(t) = std::min(get_prio(t), new_prio); check_deps(t); } break; case task_state::Running: case task_state::Failed: case task_state::Success: break; default: lean_unreachable(); } }
bool action::is_equal(action const & a) const { if (kind() != a.kind()) return false; switch (kind()) { case action_kind::Skip: return true; case action_kind::Binder: case action_kind::Binders: case action_kind::Expr: return rbp() == a.rbp(); case action_kind::Ext: return m_ptr == a.m_ptr; case action_kind::LuaExt: return get_lua_fn() == a.get_lua_fn(); case action_kind::Exprs: return rbp() == a.rbp() && get_sep() == a.get_sep() && get_rec() == a.get_rec() && get_initial() == a.get_initial() && get_terminator() == a.get_terminator() && is_fold_right() == a.is_fold_right(); case action_kind::ScopedExpr: return rbp() == a.rbp() && get_rec() == a.get_rec(); } lean_unreachable(); // LCOV_EXCL_LINE }
serializer & operator<<(serializer & s, action const & a) { s << static_cast<char>(a.kind()); switch (a.kind()) { case action_kind::Skip: break; case action_kind::Expr: case action_kind::Binder: case action_kind::Binders: s << a.rbp(); break; case action_kind::Exprs: s << a.get_sep() << a.get_rec(); if (a.get_initial()) s << true << *a.get_initial(); else s << false; s << a.is_fold_right() << a.rbp(); if (auto t = a.get_terminator()) { s << true << *t; } else { s << false; } break; case action_kind::ScopedExpr: s << a.get_rec() << a.rbp() << a.use_lambda_abstraction(); break; case action_kind::LuaExt: s << a.get_lua_fn(); break; case action_kind::Ext: lean_unreachable(); } return s; }
expr replace_visitor::visit(expr const & e) { check_system("expression replacer"); bool shared = false; if (is_shared(e)) { shared = true; auto it = m_cache.find(e); if (it != m_cache.end()) return it->second; } switch (e.kind()) { case expr_kind::Sort: return save_result(e, visit_sort(e), shared); case expr_kind::Macro: return save_result(e, visit_macro(e), shared); case expr_kind::Constant: return save_result(e, visit_constant(e), shared); case expr_kind::Var: return save_result(e, visit_var(e), shared); case expr_kind::Meta: return save_result(e, visit_meta(e), shared); case expr_kind::Local: return save_result(e, visit_local(e), shared); case expr_kind::App: return save_result(e, visit_app(e), shared); case expr_kind::Lambda: return save_result(e, visit_lambda(e), shared); case expr_kind::Pi: return save_result(e, visit_pi(e), shared); case expr_kind::Let: return save_result(e, visit_let(e), shared); } lean_unreachable(); // LCOV_EXCL_LINE }
static name const & to_prefix(expr_placeholder_kind k) { switch (k) { case expr_placeholder_kind::Implicit: return *g_implicit_placeholder_name; case expr_placeholder_kind::StrictImplicit: return *g_strict_placeholder_name; case expr_placeholder_kind::Explicit: return *g_explicit_placeholder_name; } lean_unreachable(); // LCOV_EXCL_LINE }
json json_of_severity(message_severity sev) { switch (sev) { case INFORMATION: return "information"; case WARNING: return "warning"; case ERROR: return "error"; default: lean_unreachable(); } }
parse_table & led(notation_entry_group g) { switch (g) { case notation_entry_group::Main: return m_led; case notation_entry_group::Reserve: return m_reserved_led; case notation_entry_group::Tactic: return m_tactic_led; } lean_unreachable(); }
bool is_lt(expr const & a, expr const & b, bool use_hash) { if (is_eqp(a, b)) return false; unsigned wa = get_weight(a); unsigned wb = get_weight(b); if (wa < wb) return true; if (wa > wb) return false; if (a.kind() != b.kind()) return a.kind() < b.kind(); if (use_hash) { if (a.hash() < b.hash()) return true; if (a.hash() > b.hash()) return false; } if (a == b) return false; switch (a.kind()) { case expr_kind::Var: return var_idx(a) < var_idx(b); case expr_kind::Constant: if (const_name(a) != const_name(b)) return const_name(a) < const_name(b); else return is_lt(const_levels(a), const_levels(b), use_hash); case expr_kind::App: if (app_fn(a) != app_fn(b)) return is_lt(app_fn(a), app_fn(b), use_hash); else return is_lt(app_arg(a), app_arg(b), use_hash); case expr_kind::Lambda: case expr_kind::Pi: if (binding_domain(a) != binding_domain(b)) return is_lt(binding_domain(a), binding_domain(b), use_hash); else return is_lt(binding_body(a), binding_body(b), use_hash); case expr_kind::Let: if (let_type(a) != let_type(b)) return is_lt(let_type(a), let_type(b), use_hash); else if (let_value(a) != let_value(b)) return is_lt(let_value(a), let_value(b), use_hash); else return is_lt(let_body(a), let_body(b), use_hash); case expr_kind::Sort: return is_lt(sort_level(a), sort_level(b), use_hash); case expr_kind::Local: case expr_kind::Meta: if (mlocal_name(a) != mlocal_name(b)) return mlocal_name(a) < mlocal_name(b); else return is_lt(mlocal_type(a), mlocal_type(b), use_hash); case expr_kind::Macro: if (macro_def(a) != macro_def(b)) return macro_def(a) < macro_def(b); if (macro_num_args(a) != macro_num_args(b)) return macro_num_args(a) < macro_num_args(b); for (unsigned i = 0; i < macro_num_args(a); i++) { if (macro_arg(a, i) != macro_arg(b, i)) return is_lt(macro_arg(a, i), macro_arg(b, i), use_hash); } return false; } lean_unreachable(); // LCOV_EXCL_LINE }
unsigned get_depth(level const & l) { switch (kind(l)) { case level_kind::Zero: case level_kind::Param: case level_kind::Global: case level_kind::Meta: return 1; case level_kind::Succ: case level_kind::Max: case level_kind::IMax: return to_composite(l).m_depth; } lean_unreachable(); // LCOV_EXCL_LINE }
/* For debugging purposes, check whether all hypotheses in Hs are in the local context for mvar */ bool check_hypotheses_in_context(expr const & mvar, list<optional<name>> const & Hs) { local_context lctx = m_mctx.get_metavar_decl(mvar).get_context(); for (optional<name> const & H : Hs) { if (H && !lctx.find_local_decl(*H)) { lean_unreachable(); return false; } } return true; }
template <typename V> V lar_solver::get_column_val(std::vector<V> & low_bound, std::vector<V> & upper_bound, non_basic_column_value_position pos_type, unsigned j) { switch (pos_type) { case at_low_bound: return low_bound[j]; case at_fixed: case at_upper_bound: return upper_bound[j]; case free_of_bounds: return zero_of_type<V>(); default: lean_unreachable(); } return zero_of_type<V>(); // it is unreachable }
unsigned get_weight(expr const & e) { switch (e.kind()) { case expr_kind::Var: case expr_kind::Constant: case expr_kind::Sort: case expr_kind::Meta: case expr_kind::Local: return 1; case expr_kind::Lambda: case expr_kind::Pi: case expr_kind::Macro: case expr_kind::App: case expr_kind::Let: return static_cast<expr_composite*>(e.raw())->m_weight; } lean_unreachable(); // LCOV_EXCL_LINE }
bool has_meta(level const & l) { switch (kind(l)) { case level_kind::Zero: case level_kind::Param: case level_kind::Global: return false; case level_kind::Meta: return true; case level_kind::Succ: case level_kind::Max: case level_kind::IMax: return to_composite(l).m_has_meta; } lean_unreachable(); // LCOV_EXCL_LINE }
bool is_explicit(level const & l) { switch (kind(l)) { case level_kind::Zero: return true; case level_kind::Param: case level_kind::Global: case level_kind::Meta: case level_kind::Max: case level_kind::IMax: return false; case level_kind::Succ: return to_level_succ(l).m_explicit; } lean_unreachable(); // LCOV_EXCL_LINE }
action replace(action const & a, std::function<expr(expr const &)> const & f) { switch (a.kind()) { case action_kind::Skip: case action_kind::Binder: case action_kind::Binders: case action_kind::Ext: case action_kind::LuaExt: case action_kind::Expr: return a; case action_kind::Exprs: return mk_exprs_action(a.get_sep(), f(a.get_rec()), a.get_initial() ? some_expr(f(*a.get_initial())) : none_expr(), a.get_terminator(), a.is_fold_right(), a.rbp()); case action_kind::ScopedExpr: return mk_scoped_expr_action(f(a.get_rec()), a.rbp(), a.use_lambda_abstraction()); } lean_unreachable(); // LCOV_EXCL_LINE }
bool lar_solver::constraint_holds(const lar_constraint & constr, std::unordered_map<var_index, mpq> & var_map) { mpq left_side_val = get_left_side_val(constr, var_map); switch (constr.m_kind) { case LE: return left_side_val <= constr.m_right_side; case LT: return left_side_val <= constr.m_right_side; case GE: return left_side_val >= constr.m_right_side; case GT: return left_side_val >= constr.m_right_side; case EQ: return left_side_val == constr.m_right_side; default: lean_unreachable(); } return false; // it is unreachable }
lp_status lp_status_from_string(std::string status) { if (status == "UNKNOWN") return lp_status::UNKNOWN; if (status == "INFEASIBLE") return lp_status::INFEASIBLE; if (status == "UNBOUNDED") return lp_status::UNBOUNDED; if (status == "OPTIMAL") return lp_status::OPTIMAL; if (status == "FEASIBLE") return lp_status::FEASIBLE; if (status == "FLOATING_POINT_ERROR") return lp_status::FLOATING_POINT_ERROR; if (status == "TIME_EXHAUSTED") return lp_status::TIME_EXHAUSTED; if (status == "ITERATIONS_EXHAUSTED") return lp_status::ITERATIONS_EXHAUSTED; if (status == "EMPTY") return lp_status::EMPTY; lean_unreachable(); return lp_status::UNKNOWN; // it is unreachable }
bool is_not_zero(level const & l) { switch (kind(l)) { case level_kind::Zero: case level_kind::Param: case level_kind::Global: case level_kind::Meta: return false; case level_kind::Succ: return true; case level_kind::Max: return is_not_zero(max_lhs(l)) || is_not_zero(max_rhs(l)); case level_kind::IMax: return is_not_zero(imax_rhs(l)); } lean_unreachable(); // LCOV_EXCL_LINE }