@@ -457,6 +457,15 @@ let tc_sig_let env r se lbs lids : list sigelt & list sigelt & Env.env =
457457 (* 2. Turn the top-level lb into a Tm_let with a unit body *)
458458 let e = mk ( Tm_let { lbs =( fst lbs , lbs' ); body = mk ( Tm_constant ( Const_unit )) r }) r in
459459
460+ (* For the second phase (if any), we will call the core typechecker
461+ for terms marked with a @@"core" attribute, or if the extension
462+ "core_phase2" is enabled. *)
463+ let use_core =
464+ do_two_phases env && (
465+ Options.Ext. enabled " core_phase2"
466+ || List. existsb ( U. term_eq ( U. exp_string " core" )) se . sigattrs )
467+ in
468+
460469 (* 3. Type-check the Tm_let and convert it back to Sig_let *)
461470 let env' = { env with top_level = true ; generalize = should_generalize } in
462471 let e =
@@ -493,14 +502,25 @@ let tc_sig_let env r se lbs lids : list sigelt & list sigelt & Env.env =
493502 if Debug. medium () || !dbg_TwoPhases then
494503 Format. print1 " Let binding after phase 1, before removing uvars: %s\n " ( show e );
495504
496- let e = N. remove_uvar_solutions env' e |> drop_lbtyp in
505+ let e = N. remove_uvar_solutions env' e in
506+
507+ (* Wart: the normal typechecker drops the lbtyp to avoid double
508+ ascriptions. But we need it to call the core checker. *)
509+ let e =
510+ if use_core
511+ then e
512+ else drop_lbtyp e
513+ in
497514
498515 if Debug. medium () || !dbg_TwoPhases then
499516 Format. print1 " Let binding after phase 1, uvars removed: %s\n " ( show e );
500517 e )
501518 else e
502519 in
503520
521+ (* Phony, just so that we can print the result from Core below. *)
522+ let _ : Class.Show. showable Core. guard_commit_token_cb = { show = ( fun _ -> " _" ) } in
523+
504524 let env' =
505525 match ( SS. compress e ). n with
506526 | Tm_let { lbs } ->
@@ -511,12 +531,53 @@ let tc_sig_let env r se lbs lids : list sigelt & list sigelt & Env.env =
511531 in
512532 Errors. stop_if_err ();
513533 let r =
514- //We already generalized phase1; don't need to generalize again
515- let should_generalize = not ( do_two_phases env' ) in
516- Profiling. profile ( fun () -> tc_maybe_toplevel_term { env' with generalize = should_generalize } e )
517- ( Some ( Ident. string_of_lid ( Env. current_module env )))
518- " FStarC.TypeChecker.Tc.tc_sig_let-tc-phase2"
534+ let fallback () =
535+ // We already generalized phase1; don't need to generalize again
536+ let should_generalize = not ( do_two_phases env' ) in
537+ Profiling. profile ( fun () -> tc_maybe_toplevel_term { env' with generalize = should_generalize } e )
538+ ( Some ( Ident. string_of_lid ( Env. current_module env )))
539+ " FStarC.TypeChecker.Tc.tc_sig_let-tc-phase2"
540+ in
541+ if not use_core then
542+ fallback ()
543+ else (
544+ if Debug. any () then
545+ Format. print1 " Using core as phase2 for let binding: %s\n " ( show e );
546+ match ( SS. compress e ). n with
547+ | Tm_let { lbs =( _ , [ lb ])} -> (
548+ // Format.print1 "GGG lbdef = %s\n" (show lb.lbdef);
549+ // Format.print1 "GGG lbtyp = %s\n" (show lb.lbtyp);
550+ let env' = push_univ_vars env' lb . lbunivs in
551+ let _ , def = SS. open_univ_vars lb . lbunivs lb . lbdef in
552+ let _ , typ = SS. open_univ_vars lb . lbunivs lb . lbtyp in
553+ let core_res = Core. check_term env' def typ true in
554+ // Format.print1 "Core computed type: %s\n" (show core_res);
555+ match core_res with
556+ | Inl gopt ->
557+ begin match gopt with
558+ | Some ( g , _ ) -> ignore ( Rel. discharge_guard env' ( Env. guard_of_guard_formula ( NonTrivial g )))
559+ | None -> ()
560+ end ;
561+ // Format.print1 "Core type: %s\n" (show typ);
562+ let lcomp =
563+ // match tg with
564+ // | Core.E_Total ->
565+ lcomp_of_comp ( S. mk_Total typ )
566+ // | Core.E_Ghost -> lcomp_of_comp (S.mk_GTotal typ)
567+ in
568+ e , lcomp , Env. trivial_guard
569+
570+ | Inr err ->
571+ let open FStarC.Pprint in
572+ Errors. diag e [
573+ text " Core (for phase 2) failed:" ^ /^ doc_of_string ( show err );
574+ ];
575+ fallback ()
576+ )
577+ | _ -> failwith " unexpected: not a let"
578+ )
519579 in
580+
520581 let se , lbs = match r with
521582 | { n = Tm_let { lbs ; body = e }}, _ , g when Env. is_trivial g ->
522583 U. check_mutual_universes ( snd lbs );
0 commit comments