environment mk_rec_on(environment const & env, name const & n) { if (!inductive::is_inductive_decl(env, n)) throw exception(sstream() << "error in 'rec_on' generation, '" << n << "' is not an inductive datatype"); name rec_on_name(n, "rec_on"); name_generator ngen; declaration rec_decl = env.get(inductive::get_elim_name(n)); buffer<expr> locals; expr rec_type = rec_decl.get_type(); while (is_pi(rec_type)) { expr local = mk_local(ngen.next(), binding_name(rec_type), binding_domain(rec_type), binding_info(rec_type)); rec_type = instantiate(binding_body(rec_type), local); locals.push_back(local); } // locals order // A C minor_premises indices major-premise // new_locals order // A C indices major-premise minor-premises buffer<expr> new_locals; unsigned idx_major_sz = *inductive::get_num_indices(env, n) + 1; unsigned minor_sz = *inductive::get_num_minor_premises(env, n); unsigned AC_sz = locals.size() - minor_sz - idx_major_sz; for (unsigned i = 0; i < AC_sz; i++) new_locals.push_back(locals[i]); for (unsigned i = 0; i < idx_major_sz; i++) new_locals.push_back(locals[AC_sz + minor_sz + i]); unsigned rec_on_major_idx = new_locals.size() - 1; for (unsigned i = 0; i < minor_sz; i++) new_locals.push_back(locals[AC_sz + i]); expr rec_on_type = Pi(new_locals, rec_type); levels ls = param_names_to_levels(rec_decl.get_univ_params()); expr rec = mk_constant(rec_decl.get_name(), ls); expr rec_on_val = Fun(new_locals, mk_app(rec, locals)); bool use_conv_opt = true; environment new_env = module::add(env, check(env, mk_definition(env, rec_on_name, rec_decl.get_univ_params(), rec_on_type, rec_on_val, use_conv_opt))); new_env = set_reducible(new_env, rec_on_name, reducible_status::Reducible); new_env = add_unfold_hint(new_env, rec_on_name, rec_on_major_idx); new_env = add_aux_recursor(new_env, rec_on_name); return add_protected(new_env, rec_on_name); }
static environment mk_below(environment const & env, name const & n, bool ibelow) { if (!is_recursive_datatype(env, n)) return env; if (is_inductive_predicate(env, n)) return env; inductive::inductive_decls decls = *inductive::is_inductive_decl(env, n); type_checker tc(env); name_generator ngen; unsigned nparams = std::get<1>(decls); declaration ind_decl = env.get(n); declaration rec_decl = env.get(inductive::get_elim_name(n)); unsigned nindices = *inductive::get_num_indices(env, n); unsigned nminors = *inductive::get_num_minor_premises(env, n); unsigned ntypeformers = length(std::get<2>(decls)); level_param_names lps = rec_decl.get_univ_params(); bool is_reflexive = is_reflexive_datatype(tc, n); level lvl = mk_param_univ(head(lps)); levels lvls = param_names_to_levels(tail(lps)); level_param_names blvls; // universe level parameters of ibelow/below level rlvl; // universe level of the resultant type // The arguments of below (ibelow) are the ones in the recursor - minor premises. // The universe we map to is also different (l+1 for below of reflexive types) and (0 fo ibelow). expr ref_type; expr Type_result; if (ibelow) { // we are eliminating to Prop blvls = tail(lps); rlvl = mk_level_zero(); ref_type = instantiate_univ_param(rec_decl.get_type(), param_id(lvl), mk_level_zero()); } else if (is_reflexive) { blvls = lps; rlvl = get_datatype_level(ind_decl.get_type()); // if rlvl is of the form (max 1 l), then rlvl <- l if (is_max(rlvl) && is_one(max_lhs(rlvl))) rlvl = max_rhs(rlvl); rlvl = mk_max(mk_succ(lvl), rlvl); ref_type = instantiate_univ_param(rec_decl.get_type(), param_id(lvl), mk_succ(lvl)); } else { // we can simplify the universe levels for non-reflexive datatypes blvls = lps; rlvl = mk_max(mk_level_one(), lvl); ref_type = rec_decl.get_type(); } Type_result = mk_sort(rlvl); buffer<expr> ref_args; to_telescope(ngen, ref_type, ref_args); if (ref_args.size() != nparams + ntypeformers + nminors + nindices + 1) throw_corrupted(n); // args contains the below/ibelow arguments buffer<expr> args; buffer<name> typeformer_names; // add parameters and typeformers for (unsigned i = 0; i < nparams; i++) args.push_back(ref_args[i]); for (unsigned i = nparams; i < nparams + ntypeformers; i++) { args.push_back(ref_args[i]); typeformer_names.push_back(mlocal_name(ref_args[i])); } // we ignore minor premises in below/ibelow for (unsigned i = nparams + ntypeformers + nminors; i < ref_args.size(); i++) args.push_back(ref_args[i]); // We define below/ibelow using the recursor for this type levels rec_lvls = cons(mk_succ(rlvl), lvls); expr rec = mk_constant(rec_decl.get_name(), rec_lvls); for (unsigned i = 0; i < nparams; i++) rec = mk_app(rec, args[i]); // add type formers for (unsigned i = nparams; i < nparams + ntypeformers; i++) { buffer<expr> targs; to_telescope(ngen, mlocal_type(args[i]), targs); rec = mk_app(rec, Fun(targs, Type_result)); } // add minor premises for (unsigned i = nparams + ntypeformers; i < nparams + ntypeformers + nminors; i++) { expr minor = ref_args[i]; expr minor_type = mlocal_type(minor); buffer<expr> minor_args; minor_type = to_telescope(ngen, minor_type, minor_args); buffer<expr> prod_pairs; for (expr & minor_arg : minor_args) { buffer<expr> minor_arg_args; expr minor_arg_type = to_telescope(tc, mlocal_type(minor_arg), minor_arg_args); if (is_typeformer_app(typeformer_names, minor_arg_type)) { expr fst = mlocal_type(minor_arg); minor_arg = update_mlocal(minor_arg, Pi(minor_arg_args, Type_result)); expr snd = Pi(minor_arg_args, mk_app(minor_arg, minor_arg_args)); prod_pairs.push_back(mk_prod(tc, fst, snd, ibelow)); } } expr new_arg = foldr([&](expr const & a, expr const & b) { return mk_prod(tc, a, b, ibelow); }, [&]() { return mk_unit(rlvl, ibelow); }, prod_pairs.size(), prod_pairs.data()); rec = mk_app(rec, Fun(minor_args, new_arg)); } // add indices and major premise for (unsigned i = nparams + ntypeformers; i < args.size(); i++) { rec = mk_app(rec, args[i]); } name below_name = ibelow ? name{n, "ibelow"} : name{n, "below"}; expr below_type = Pi(args, Type_result); expr below_value = Fun(args, rec); bool use_conv_opt = true; declaration new_d = mk_definition(env, below_name, blvls, below_type, below_value, use_conv_opt); environment new_env = module::add(env, check(env, new_d)); new_env = set_reducible(new_env, below_name, reducible_status::Reducible); if (!ibelow) new_env = add_unfold_hint(new_env, below_name, nparams + nindices + ntypeformers); return add_protected(new_env, below_name); }
static environment mk_brec_on(environment const & env, name const & n, bool ind) { if (!is_recursive_datatype(env, n)) return env; if (is_inductive_predicate(env, n)) return env; inductive::inductive_decls decls = *inductive::is_inductive_decl(env, n); type_checker tc(env); name_generator ngen; unsigned nparams = std::get<1>(decls); declaration ind_decl = env.get(n); declaration rec_decl = env.get(inductive::get_elim_name(n)); // declaration below_decl = env.get(name(n, ind ? "ibelow" : "below")); unsigned nindices = *inductive::get_num_indices(env, n); unsigned nminors = *inductive::get_num_minor_premises(env, n); unsigned ntypeformers = length(std::get<2>(decls)); level_param_names lps = rec_decl.get_univ_params(); bool is_reflexive = is_reflexive_datatype(tc, n); level lvl = mk_param_univ(head(lps)); levels lvls = param_names_to_levels(tail(lps)); level rlvl; level_param_names blps; levels blvls; // universe level parameters of brec_on/binduction_on // The arguments of brec_on (binduction_on) are the ones in the recursor - minor premises. // The universe we map to is also different (l+1 for below of reflexive types) and (0 fo ibelow). expr ref_type; if (ind) { // we are eliminating to Prop blps = tail(lps); blvls = lvls; rlvl = mk_level_zero(); ref_type = instantiate_univ_param(rec_decl.get_type(), param_id(lvl), mk_level_zero()); } else if (is_reflexive) { blps = lps; blvls = cons(lvl, lvls); rlvl = get_datatype_level(ind_decl.get_type()); // if rlvl is of the form (max 1 l), then rlvl <- l if (is_max(rlvl) && is_one(max_lhs(rlvl))) rlvl = max_rhs(rlvl); rlvl = mk_max(mk_succ(lvl), rlvl); // inner_prod, inner_prod_intro, pr1, pr2 do not use the same universe levels for // reflective datatypes. ref_type = instantiate_univ_param(rec_decl.get_type(), param_id(lvl), mk_succ(lvl)); } else { // we can simplify the universe levels for non-reflexive datatypes blps = lps; blvls = cons(lvl, lvls); rlvl = mk_max(mk_level_one(), lvl); ref_type = rec_decl.get_type(); } buffer<expr> ref_args; to_telescope(ngen, ref_type, ref_args); if (ref_args.size() != nparams + ntypeformers + nminors + nindices + 1) throw_corrupted(n); // args contains the brec_on/binduction_on arguments buffer<expr> args; buffer<name> typeformer_names; // add parameters and typeformers for (unsigned i = 0; i < nparams; i++) args.push_back(ref_args[i]); for (unsigned i = nparams; i < nparams + ntypeformers; i++) { args.push_back(ref_args[i]); typeformer_names.push_back(mlocal_name(ref_args[i])); } // add indices and major premise for (unsigned i = nparams + ntypeformers + nminors; i < ref_args.size(); i++) args.push_back(ref_args[i]); // create below terms (one per datatype) // (below.{lvls} params type-formers) // Remark: it also creates the result type buffer<expr> belows; expr result_type; unsigned k = 0; for (auto const & decl : std::get<2>(decls)) { name const & n1 = inductive::inductive_decl_name(decl); if (n1 == n) { result_type = ref_args[nparams + k]; for (unsigned i = nparams + ntypeformers + nminors; i < ref_args.size(); i++) result_type = mk_app(result_type, ref_args[i]); } k++; name bname = name(n1, ind ? "ibelow" : "below"); expr below = mk_constant(bname, blvls); for (unsigned i = 0; i < nparams; i++) below = mk_app(below, ref_args[i]); for (unsigned i = nparams; i < nparams + ntypeformers; i++) below = mk_app(below, ref_args[i]); belows.push_back(below); } // create functionals (one for each type former) // Pi idxs t, below idxs t -> C idxs t buffer<expr> Fs; name F_name("F"); for (unsigned i = nparams, j = 0; i < nparams + ntypeformers; i++, j++) { expr const & C = ref_args[i]; buffer<expr> F_args; to_telescope(ngen, mlocal_type(C), F_args); expr F_result = mk_app(C, F_args); expr F_below = mk_app(belows[j], F_args); F_args.push_back(mk_local(ngen.next(), "f", F_below, binder_info())); expr F_type = Pi(F_args, F_result); expr F = mk_local(ngen.next(), F_name.append_after(j+1), F_type, binder_info()); Fs.push_back(F); args.push_back(F); } // We define brec_on/binduction_on using the recursor for this type levels rec_lvls = cons(rlvl, lvls); expr rec = mk_constant(rec_decl.get_name(), rec_lvls); // add parameters to rec for (unsigned i = 0; i < nparams; i++) rec = mk_app(rec, ref_args[i]); // add type formers to rec // Pi indices t, prod (C ... t) (below ... t) for (unsigned i = nparams, j = 0; i < nparams + ntypeformers; i++, j++) { expr const & C = ref_args[i]; buffer<expr> C_args; to_telescope(ngen, mlocal_type(C), C_args); expr C_t = mk_app(C, C_args); expr below_t = mk_app(belows[j], C_args); expr prod = mk_prod(tc, C_t, below_t, ind); rec = mk_app(rec, Fun(C_args, prod)); } // add minor premises to rec for (unsigned i = nparams + ntypeformers, j = 0; i < nparams + ntypeformers + nminors; i++, j++) { expr minor = ref_args[i]; expr minor_type = mlocal_type(minor); buffer<expr> minor_args; minor_type = to_telescope(ngen, minor_type, minor_args); buffer<expr> pairs; for (expr & minor_arg : minor_args) { buffer<expr> minor_arg_args; expr minor_arg_type = to_telescope(tc, mlocal_type(minor_arg), minor_arg_args); if (auto k = is_typeformer_app(typeformer_names, minor_arg_type)) { buffer<expr> C_args; get_app_args(minor_arg_type, C_args); expr new_minor_arg_type = mk_prod(tc, minor_arg_type, mk_app(belows[*k], C_args), ind); minor_arg = update_mlocal(minor_arg, Pi(minor_arg_args, new_minor_arg_type)); if (minor_arg_args.empty()) { pairs.push_back(minor_arg); } else { expr r = mk_app(minor_arg, minor_arg_args); expr r_1 = Fun(minor_arg_args, mk_pr1(tc, r, ind)); expr r_2 = Fun(minor_arg_args, mk_pr2(tc, r, ind)); pairs.push_back(mk_pair(tc, r_1, r_2, ind)); } } } expr b = foldr([&](expr const & a, expr const & b) { return mk_pair(tc, a, b, ind); }, [&]() { return mk_unit_mk(rlvl, ind); }, pairs.size(), pairs.data()); unsigned F_idx = *is_typeformer_app(typeformer_names, minor_type); expr F = Fs[F_idx]; buffer<expr> F_args; get_app_args(minor_type, F_args); F_args.push_back(b); expr new_arg = mk_pair(tc, mk_app(F, F_args), b, ind); rec = mk_app(rec, Fun(minor_args, new_arg)); } // add indices and major to rec for (unsigned i = nparams + ntypeformers + nminors; i < ref_args.size(); i++) rec = mk_app(rec, ref_args[i]); name brec_on_name = name(n, ind ? "binduction_on" : "brec_on"); expr brec_on_type = Pi(args, result_type); expr brec_on_value = Fun(args, mk_pr1(tc, rec, ind)); bool use_conv_opt = true; declaration new_d = mk_definition(env, brec_on_name, blps, brec_on_type, brec_on_value, use_conv_opt); environment new_env = module::add(env, check(env, new_d)); new_env = set_reducible(new_env, brec_on_name, reducible_status::Reducible); if (!ind) new_env = add_unfold_hint(new_env, brec_on_name, nparams + nindices + ntypeformers); return add_protected(new_env, brec_on_name); }
optional<environment> mk_no_confusion_type(environment const & env, name const & n) { optional<inductive::inductive_decls> decls = inductive::is_inductive_decl(env, n); if (!decls) throw exception(sstream() << "error in 'no_confusion' generation, '" << n << "' is not an inductive datatype"); if (is_inductive_predicate(env, n)) return optional<environment>(); // type is a proposition name_generator ngen; unsigned nparams = std::get<1>(*decls); declaration ind_decl = env.get(n); declaration cases_decl = env.get(name(n, "cases_on")); level_param_names lps = cases_decl.get_univ_params(); level rlvl = mk_param_univ(head(lps)); levels ilvls = param_names_to_levels(tail(lps)); if (length(ilvls) != length(ind_decl.get_univ_params())) return optional<environment>(); // type does not have only a restricted eliminator expr ind_type = instantiate_type_univ_params(ind_decl, ilvls); name eq_name("eq"); name heq_name("heq"); // All inductive datatype parameters and indices are arguments buffer<expr> args; ind_type = to_telescope(ngen, ind_type, args, some(mk_implicit_binder_info())); if (!is_sort(ind_type) || args.size() < nparams) throw_corrupted(n); lean_assert(!(env.impredicative() && is_zero(sort_level(ind_type)))); unsigned nindices = args.size() - nparams; // Create inductive datatype expr I = mk_app(mk_constant(n, ilvls), args); // Add (P : Type) expr P = mk_local(ngen.next(), "P", mk_sort(rlvl), binder_info()); args.push_back(P); // add v1 and v2 elements of the inductive type expr v1 = mk_local(ngen.next(), "v1", I, binder_info()); expr v2 = mk_local(ngen.next(), "v2", I, binder_info()); args.push_back(v1); args.push_back(v2); expr R = mk_sort(rlvl); name no_confusion_type_name{n, "no_confusion_type"}; expr no_confusion_type_type = Pi(args, R); // Create type former buffer<expr> type_former_args; for (unsigned i = nparams; i < nparams + nindices; i++) type_former_args.push_back(args[i]); type_former_args.push_back(v1); expr type_former = Fun(type_former_args, R); // Create cases_on levels clvls = levels(mk_succ(rlvl), ilvls); expr cases_on = mk_app(mk_app(mk_constant(cases_decl.get_name(), clvls), nparams, args.data()), type_former); cases_on = mk_app(cases_on, nindices, args.data() + nparams); expr cases_on1 = mk_app(cases_on, v1); expr cases_on2 = mk_app(cases_on, v2); type_checker tc(env); expr t1 = tc.infer(cases_on1).first; expr t2 = tc.infer(cases_on2).first; buffer<expr> outer_cases_on_args; unsigned idx1 = 0; while (is_pi(t1)) { buffer<expr> minor1_args; expr minor1 = to_telescope(tc, binding_domain(t1), minor1_args); expr curr_t2 = t2; buffer<expr> inner_cases_on_args; unsigned idx2 = 0; while (is_pi(curr_t2)) { buffer<expr> minor2_args; expr minor2 = to_telescope(tc, binding_domain(curr_t2), minor2_args); if (idx1 != idx2) { // infeasible case, constructors do not match inner_cases_on_args.push_back(Fun(minor2_args, P)); } else { if (minor1_args.size() != minor2_args.size()) throw_corrupted(n); buffer<expr> rtype_hyp; // add equalities for (unsigned i = 0; i < minor1_args.size(); i++) { expr lhs = minor1_args[i]; expr rhs = minor2_args[i]; expr lhs_type = mlocal_type(lhs); expr rhs_type = mlocal_type(rhs); level l = sort_level(tc.ensure_type(lhs_type).first); expr h_type; if (tc.is_def_eq(lhs_type, rhs_type).first) { h_type = mk_app(mk_constant(eq_name, to_list(l)), lhs_type, lhs, rhs); } else { h_type = mk_app(mk_constant(heq_name, to_list(l)), lhs_type, lhs, rhs_type, rhs); } rtype_hyp.push_back(mk_local(ngen.next(), local_pp_name(lhs).append_after("_eq"), h_type, binder_info())); } inner_cases_on_args.push_back(Fun(minor2_args, mk_arrow(Pi(rtype_hyp, P), P))); } idx2++; curr_t2 = binding_body(curr_t2); } outer_cases_on_args.push_back(Fun(minor1_args, mk_app(cases_on2, inner_cases_on_args))); idx1++; t1 = binding_body(t1); } expr no_confusion_type_value = Fun(args, mk_app(cases_on1, outer_cases_on_args)); bool opaque = false; bool use_conv_opt = true; declaration new_d = mk_definition(env, no_confusion_type_name, lps, no_confusion_type_type, no_confusion_type_value, opaque, ind_decl.get_module_idx(), use_conv_opt); environment new_env = module::add(env, check(env, new_d)); return some(add_protected(new_env, no_confusion_type_name)); }
environment mk_no_confusion(environment const & env, name const & n) { optional<environment> env1 = mk_no_confusion_type(env, n); if (!env1) return env; environment new_env = *env1; type_checker tc(new_env); inductive::inductive_decls decls = *inductive::is_inductive_decl(new_env, n); unsigned nparams = std::get<1>(decls); name_generator ngen; declaration no_confusion_type_decl = new_env.get(name{n, "no_confusion_type"}); declaration cases_decl = new_env.get(name(n, "cases_on")); level_param_names lps = no_confusion_type_decl.get_univ_params(); levels ls = param_names_to_levels(lps); expr no_confusion_type_type = instantiate_type_univ_params(no_confusion_type_decl, ls); name eq_name("eq"); name heq_name("heq"); name eq_refl_name{"eq", "refl"}; name heq_refl_name{"heq", "refl"}; buffer<expr> args; expr type = no_confusion_type_type; type = to_telescope(ngen, type, args, some(mk_implicit_binder_info())); lean_assert(args.size() >= nparams + 3); unsigned nindices = args.size() - nparams - 3; // 3 is for P v1 v2 expr range = mk_app(mk_constant(no_confusion_type_decl.get_name(), ls), args); expr P = args[args.size()-3]; expr v1 = args[args.size()-2]; expr v2 = args[args.size()-1]; expr v_type = mlocal_type(v1); level v_lvl = sort_level(tc.ensure_type(v_type).first); expr eq_v = mk_app(mk_constant(eq_name, to_list(v_lvl)), v_type); expr H12 = mk_local(ngen.next(), "H12", mk_app(eq_v, v1, v2), binder_info()); args.push_back(H12); name no_confusion_name{n, "no_confusion"}; expr no_confusion_ty = Pi(args, range); // The gen proof is of the form // (fun H11 : v1 = v1, cases_on Params (fun Indices v1, no_confusion_type Params Indices P v1 v1) Indices v1 // <for-each case> // (fun H : (equations -> P), H (refl) ... (refl)) // ... // ) // H11 is for creating the generalization expr H11 = mk_local(ngen.next(), "H11", mk_app(eq_v, v1, v1), binder_info()); // Create the type former (fun Indices v1, no_confusion_type Params Indices P v1 v1) buffer<expr> type_former_args; for (unsigned i = nparams; i < nparams + nindices; i++) type_former_args.push_back(args[i]); type_former_args.push_back(v1); buffer<expr> no_confusion_type_args; for (unsigned i = 0; i < nparams + nindices; i++) no_confusion_type_args.push_back(args[i]); no_confusion_type_args.push_back(P); no_confusion_type_args.push_back(v1); no_confusion_type_args.push_back(v1); expr no_confusion_type_app = mk_app(mk_constant(no_confusion_type_decl.get_name(), ls), no_confusion_type_args); expr type_former = Fun(type_former_args, no_confusion_type_app); // create cases_on levels clvls = ls; expr cases_on = mk_app(mk_app(mk_constant(cases_decl.get_name(), clvls), nparams, args.data()), type_former); cases_on = mk_app(mk_app(cases_on, nindices, args.data() + nparams), v1); expr cot = tc.infer(cases_on).first; while (is_pi(cot)) { buffer<expr> minor_args; expr minor = to_telescope(tc, binding_domain(cot), minor_args); lean_assert(!minor_args.empty()); expr H = minor_args.back(); expr Ht = mlocal_type(H); buffer<expr> refl_args; while (is_pi(Ht)) { buffer<expr> eq_args; expr eq_fn = get_app_args(binding_domain(Ht), eq_args); if (const_name(eq_fn) == eq_name) { refl_args.push_back(mk_app(mk_constant(eq_refl_name, const_levels(eq_fn)), eq_args[0], eq_args[1])); } else { refl_args.push_back(mk_app(mk_constant(heq_refl_name, const_levels(eq_fn)), eq_args[0], eq_args[1])); } Ht = binding_body(Ht); } expr pr = mk_app(H, refl_args); cases_on = mk_app(cases_on, Fun(minor_args, pr)); cot = binding_body(cot); } expr gen = Fun(H11, cases_on); // Now, we use gen to build the final proof using eq.rec // // eq.rec InductiveType v1 (fun (a : InductiveType), v1 = a -> no_confusion_type Params Indices v1 a) gen v2 H12 H12 // name eq_rec_name{"eq", "rec"}; expr eq_rec = mk_app(mk_constant(eq_rec_name, {head(ls), v_lvl}), v_type, v1); // create eq_rec type_former // (fun (a : InductiveType), v1 = a -> no_confusion_type Params Indices v1 a) expr a = mk_local(ngen.next(), "a", v_type, binder_info()); expr H1a = mk_local(ngen.next(), "H1a", mk_app(eq_v, v1, a), binder_info()); // reusing no_confusion_type_args... we just replace the last argument with a no_confusion_type_args.pop_back(); no_confusion_type_args.push_back(a); expr no_confusion_type_app_1a = mk_app(mk_constant(no_confusion_type_decl.get_name(), ls), no_confusion_type_args); expr rec_type_former = Fun(a, Pi(H1a, no_confusion_type_app_1a)); // finalize eq_rec eq_rec = mk_app(mk_app(eq_rec, rec_type_former, gen, v2, H12), H12); // expr no_confusion_val = Fun(args, eq_rec); bool opaque = false; bool use_conv_opt = true; declaration new_d = mk_definition(new_env, no_confusion_name, lps, no_confusion_ty, no_confusion_val, opaque, no_confusion_type_decl.get_module_idx(), use_conv_opt); new_env = module::add(new_env, check(new_env, new_d)); return add_protected(new_env, no_confusion_name); }