@@ -3385,6 +3385,341 @@ Proof.
33853385 ].
33863386Qed .
33873387
3388+ (** ** Step preserves type
3389+
3390+ If [e] steps to [e'] and BOTH have typings, then they're at the
3391+ SAME type. The conclusion's [T = T'] equality is what unblocks
3392+ the "type-alignment-circular" Cluster B cases of
3393+ [step_output_context_eq] (Lemma B) — for cases like S_Let_Step
3394+ where the inner step's type isn't fixed by the outer compound's
3395+ type.
3396+
3397+ The lemma's own induction handles the circularity because, at
3398+ each congruence case, the IH for the inner step provides
3399+ type-alignment for the inner sub-expressions (which then forces
3400+ the outer T = T' via the typing rule's structure).
3401+
3402+ Proof structure mirrors [step_output_context_eq] but produces a
3403+ type-equality instead of an output-context-equality. *)
3404+ Lemma step_preserves_type :
3405+ forall mu R e mu' R' e',
3406+ (mu, R, e) -->> (mu', R', e') ->
3407+ forall G T G_a,
3408+ R; G |- e : T -| G_a ->
3409+ forall T' G_b,
3410+ R'; G |- e' : T' -| G_b ->
3411+ T = T'.
3412+ Proof .
3413+ intros mu R e mu' R' e' Hstep.
3414+ remember (mu, R, e) as cfg eqn:Hcfg.
3415+ remember (mu', R', e') as cfg' eqn:Hcfg'.
3416+ revert mu R e mu' R' e' Hcfg Hcfg'.
3417+ induction Hstep;
3418+ intros mu0 R0 e0 mu0' R0' e0' Hcfg Hcfg';
3419+ inversion Hcfg; subst;
3420+ inversion Hcfg'; subst;
3421+ intros G0 T0 Ga Hte T' Gb Hte'.
3422+ (* Atomic axiom cases that close by inversion-chain + reflexivity
3423+ (the same 4 that closed in Lemma B atomic-axiom block). *)
3424+ all: try (
3425+ inversion Hte; subst;
3426+ inversion Hte'; subst;
3427+ repeat match goal with
3428+ | [ H : has_type _ _ (ELoc _ _) _ _ |- _ ] =>
3429+ inversion H; subst; clear H
3430+ | [ H : has_type _ _ (EI32 _) _ _ |- _ ] =>
3431+ inversion H; subst; clear H
3432+ | [ H : has_type _ _ EUnit _ _ |- _ ] =>
3433+ inversion H; subst; clear H
3434+ | [ H : has_type _ _ (EBool _) _ _ |- _ ] =>
3435+ inversion H; subst; clear H
3436+ end;
3437+ reflexivity).
3438+ (* Cluster A — beta-reduction. For each: invert Hte, value_context_
3439+ unchanged, subst_preserves_typing_strong to construct a typing
3440+ of the post-step expression at the SAME T as the original, then
3441+ type_determinacy aligns it with Hte''s T'. *)
3442+ (* S_Let_Val *)
3443+ all: try solve [
3444+ match goal with
3445+ | [ Hv : is_value ?v1,
3446+ Hte : has_type ?R ?G (ELet ?v1 ?e2) ?T ?Ga,
3447+ Hte' : has_type ?R ?G (subst 0 ?v1 ?e2) ?T' ?Gb |- ?T = ?T' ] =>
3448+ inversion Hte; subst;
3449+ match goal with
3450+ | [ Hv1 : has_type ?R ?G ?v1 ?T1 ?G',
3451+ He2 : has_type ?R (ctx_extend ?G' ?T1) ?e2 ?T
3452+ ((?T1, true) :: ?Ga') |- _ ] =>
3453+ assert (HGv : G' = G) by
3454+ (eapply value_context_unchanged; eassumption);
3455+ subst G';
3456+ destruct (subst_preserves_typing_strong _ _ _ _ _ _ _ _
3457+ He2 Hv1 Hv) as [_ Hsub];
3458+ eapply type_determinacy;
3459+ [exact Hsub | exact Hte' | apply ctx_types_agree_refl]
3460+ end
3461+ end
3462+ ].
3463+ (* S_LetLin_Val *)
3464+ all: try solve [
3465+ match goal with
3466+ | [ Hv : is_value ?v1,
3467+ Hte : has_type ?R ?G (ELetLin ?v1 ?e2) ?T ?Ga,
3468+ Hte' : has_type ?R ?G (subst 0 ?v1 ?e2) ?T' ?Gb |- ?T = ?T' ] =>
3469+ inversion Hte; subst;
3470+ match goal with
3471+ | [ Hv1 : has_type ?R ?G ?v1 ?T1 ?G',
3472+ He2 : has_type ?R (ctx_extend ?G' ?T1) ?e2 ?T
3473+ ((?T1, true) :: ?Ga') |- _ ] =>
3474+ assert (HGv : G' = G) by
3475+ (eapply value_context_unchanged; eassumption);
3476+ subst G';
3477+ destruct (subst_preserves_typing_strong _ _ _ _ _ _ _ _
3478+ He2 Hv1 Hv) as [_ Hsub];
3479+ eapply type_determinacy;
3480+ [exact Hsub | exact Hte' | apply ctx_types_agree_refl]
3481+ end
3482+ end
3483+ ].
3484+ (* S_App_Fun: use Tann (ELam annotation) and Tfa (TFun arg) as
3485+ separate pattern vars; inversion Hlam forces them equal. *)
3486+ all: try solve [
3487+ match goal with
3488+ | [ Hv : is_value ?v2,
3489+ Hte : has_type ?R ?G (EApp (ELam ?T1 ?ebody) ?v2) ?T2 ?Ga,
3490+ Hte' : has_type ?R ?G (subst 0 ?v2 ?ebody) ?T' ?Gb |- ?T2 = ?T' ] =>
3491+ inversion Hte; subst;
3492+ match goal with
3493+ | [ Hlam : has_type ?Rx ?Gx (ELam ?Tann ?ebody2)
3494+ (TFun ?Tfa ?Tfr) ?Gmidx,
3495+ Harg : has_type ?Rx ?Gmidx ?v2 ?Tfa ?Ga2 |- _ ] =>
3496+ assert (HGlam : Gmidx = Gx) by
3497+ (eapply value_context_unchanged;
3498+ [exact Hlam | constructor]);
3499+ subst Gmidx;
3500+ assert (HGv : Ga2 = Gx) by
3501+ (eapply value_context_unchanged; eassumption);
3502+ subst Ga2;
3503+ inversion Hlam; subst;
3504+ match goal with
3505+ | [ Hbody : has_type ?Rx (ctx_extend ?Gx ?Tfa) ?ebody2 ?Tfr
3506+ ((?Tfa, true) :: ?Gx) |- _ ] =>
3507+ destruct (subst_preserves_typing_strong _ _ _ _ _ _ _ _
3508+ Hbody Harg Hv) as [_ Hsub];
3509+ eapply type_determinacy;
3510+ [exact Hsub | exact Hte' | apply ctx_types_agree_refl]
3511+ end
3512+ end
3513+ end
3514+ ].
3515+ (* S_If_True *)
3516+ all: try solve [
3517+ match goal with
3518+ | [ Hte : has_type ?R ?G (EIf (EBool true) ?e2x ?e3x) ?T ?Ga,
3519+ Hte' : has_type ?R ?G ?e2x ?T' ?Gb |- ?T = ?T' ] =>
3520+ inversion Hte; subst;
3521+ match goal with
3522+ | [ Hbool : has_type ?R ?G (EBool true) (TBase TBool) ?Gmid,
3523+ Hbranch : has_type ?R ?Gmid ?e2x ?T ?Ga |- _ ] =>
3524+ assert (HGmid : Gmid = G) by
3525+ (eapply value_context_unchanged;
3526+ [exact Hbool | constructor]);
3527+ subst Gmid;
3528+ eapply type_determinacy;
3529+ [exact Hbranch | exact Hte' | apply ctx_types_agree_refl]
3530+ end
3531+ end
3532+ ].
3533+ (* S_If_False *)
3534+ all: try solve [
3535+ match goal with
3536+ | [ Hte : has_type ?R ?G (EIf (EBool false) ?e2x ?e3x) ?T ?Ga,
3537+ Hte' : has_type ?R ?G ?e3x ?T' ?Gb |- ?T = ?T' ] =>
3538+ inversion Hte; subst;
3539+ match goal with
3540+ | [ Hbool : has_type ?R ?G (EBool false) (TBase TBool) ?Gmid,
3541+ Hbranch : has_type ?R ?Gmid ?e3x ?T ?Ga |- _ ] =>
3542+ assert (HGmid : Gmid = G) by
3543+ (eapply value_context_unchanged;
3544+ [exact Hbool | constructor]);
3545+ subst Gmid;
3546+ eapply type_determinacy;
3547+ [exact Hbranch | exact Hte' | apply ctx_types_agree_refl]
3548+ end
3549+ end
3550+ ].
3551+ (* S_Case_Inl *)
3552+ all: try (match goal with
3553+ | [ Hte : has_type _ _ (ECase (EInl _ ?vv) _ _) _ _,
3554+ Hv : is_value ?vv |- _ ] =>
3555+ inversion Hte; subst;
3556+ match goal with
3557+ | [ Hsum : has_type _ ?G (EInl _ ?vv) (TSum _ _) ?Gmid |- _ ] =>
3558+ assert (HGsum : Gmid = G) by
3559+ (eapply value_context_unchanged;
3560+ [exact Hsum | constructor; assumption]);
3561+ subst Gmid;
3562+ inversion Hsum; subst
3563+ end
3564+ end).
3565+ all: try solve [
3566+ match goal with
3567+ | [ Hv : is_value ?vv,
3568+ Hvt : has_type ?R ?G ?vv ?T1 ?G,
3569+ Hbr : has_type ?R (ctx_extend ?G ?T1) ?ebody ?T
3570+ ((?T1, true) :: ?Ga),
3571+ Hte' : has_type ?R ?G (subst 0 ?vv ?ebody) ?T' ?Gb
3572+ |- ?T = ?T' ] =>
3573+ destruct (subst_preserves_typing_strong _ _ _ _ _ _ _ _
3574+ Hbr Hvt Hv) as [_ Hsub];
3575+ eapply type_determinacy;
3576+ [exact Hsub | exact Hte' | apply ctx_types_agree_refl]
3577+ end
3578+ ].
3579+ (* S_Case_Inr *)
3580+ all: try (match goal with
3581+ | [ Hte : has_type _ _ (ECase (EInr _ ?vv) _ _) _ _,
3582+ Hv : is_value ?vv |- _ ] =>
3583+ inversion Hte; subst;
3584+ match goal with
3585+ | [ Hsum : has_type _ ?G (EInr _ ?vv) (TSum _ _) ?Gmid |- _ ] =>
3586+ assert (HGsum : Gmid = G) by
3587+ (eapply value_context_unchanged;
3588+ [exact Hsum | constructor; assumption]);
3589+ subst Gmid;
3590+ inversion Hsum; subst
3591+ end
3592+ end).
3593+ all: try solve [
3594+ match goal with
3595+ | [ Hv : is_value ?vv,
3596+ Hvt : has_type ?R ?G ?vv ?T2 ?G,
3597+ Hbr : has_type ?R (ctx_extend ?G ?T2) ?ebody ?T
3598+ ((?T2, true) :: ?Ga),
3599+ Hte' : has_type ?R ?G (subst 0 ?vv ?ebody) ?T' ?Gb
3600+ |- ?T = ?T' ] =>
3601+ destruct (subst_preserves_typing_strong _ _ _ _ _ _ _ _
3602+ Hbr Hvt Hv) as [_ Hsub];
3603+ eapply type_determinacy;
3604+ [exact Hsub | exact Hte' | apply ctx_types_agree_refl]
3605+ end
3606+ ].
3607+ (* Cluster B — congruence cases close via the IH's type-equality.
3608+ The IH for [step_preserves_type] handles the inner step
3609+ directly: given e1 → e1' and typings of e1 / e1' at any types
3610+ (each under its respective R / R'), the IH yields type-equality.
3611+ No need to dispatch on R = R' first — the IH is universal in
3612+ the typings' region envs. *)
3613+ (* S_StringConcat_Step1 — inner step on e1. *)
3614+ all: try solve [
3615+ match goal with
3616+ | [ IH : forall (_:mem) (_:region_env) (_:expr) (_:mem) (_:region_env) (_:expr),
3617+ _ = _ -> _ = _ -> forall (_:ctx) (_:ty) (_:ctx),
3618+ _ -> forall (_:ty) (_:ctx), _ -> _ = _,
3619+ Hte : has_type _ _ (EStringConcat _ _) _ _,
3620+ Hte' : has_type _ _ (EStringConcat _ _) _ _ |- _ ] =>
3621+ inversion Hte; subst;
3622+ inversion Hte'; subst;
3623+ match goal with
3624+ | [ H1 : has_type ?R ?G ?e1 (TString ?r) ?Gmid,
3625+ H1' : has_type ?R' ?G ?e1' (TString ?r') ?Gmid' |- _ ] =>
3626+ pose proof (IH _ _ _ _ _ _ eq_refl eq_refl _ _ _ H1 _ _ H1') as Hteq;
3627+ inversion Hteq; reflexivity
3628+ end
3629+ end
3630+ ].
3631+ (* S_App_Step1, S_App_Step2 — TFun T1 T2; IH gives T1 = T1' AND T2 = T2'. *)
3632+ all: try solve [
3633+ match goal with
3634+ | [ IH : forall (_:mem) (_:region_env) (_:expr) (_:mem) (_:region_env) (_:expr),
3635+ _ = _ -> _ = _ -> forall (_:ctx) (_:ty) (_:ctx),
3636+ _ -> forall (_:ty) (_:ctx), _ -> _ = _,
3637+ Hte : has_type _ _ (EApp _ _) _ _,
3638+ Hte' : has_type _ _ (EApp _ _) _ _ |- _ ] =>
3639+ inversion Hte; subst;
3640+ inversion Hte'; subst;
3641+ match goal with
3642+ | [ H1 : has_type ?R ?G ?e1 (TFun ?T1a ?T2a) ?Gmid,
3643+ H1' : has_type ?R' ?G ?e1' (TFun ?T1b ?T2b) ?Gmid' |- _ ] =>
3644+ pose proof (IH _ _ _ _ _ _ eq_refl eq_refl _ _ _ H1 _ _ H1') as Hteq;
3645+ inversion Hteq; reflexivity
3646+ end
3647+ end
3648+ ].
3649+ (* S_Let_Step, S_LetLin_Step — IH on e1 → e1' aligns T1, then need
3650+ T = T' from the body. *)
3651+ all: try solve [
3652+ match goal with
3653+ | [ IH : forall (_:mem) (_:region_env) (_:expr) (_:mem) (_:region_env) (_:expr),
3654+ _ = _ -> _ = _ -> forall (_:ctx) (_:ty) (_:ctx),
3655+ _ -> forall (_:ty) (_:ctx), _ -> _ = _,
3656+ Hte : has_type _ _ (ELet _ _) _ _,
3657+ Hte' : has_type _ _ (ELet _ _) _ _ |- _ ] =>
3658+ inversion Hte; subst;
3659+ inversion Hte'; subst;
3660+ match goal with
3661+ | [ H1 : has_type ?R ?G ?e1 ?T1a ?Gmid,
3662+ H1' : has_type ?R' ?G ?e1' ?T1b ?Gmid',
3663+ H2 : has_type ?R (ctx_extend ?Gmid ?T1a) ?e2 ?T ((?T1a, true) :: ?Ga),
3664+ H2' : has_type ?R' (ctx_extend ?Gmid' ?T1b) ?e2 ?T' ((?T1b, true) :: ?Gb) |- _ ] =>
3665+ (* IH aligns T1a = T1b *)
3666+ pose proof (IH _ _ _ _ _ _ eq_refl eq_refl _ _ _ H1 _ _ H1') as HT1;
3667+ subst T1b;
3668+ (* Now H2 and H2' both have body context ctx_extend ?_ T1a.
3669+ typing_types_agree composed via G aligns Gmid and Gmid'. *)
3670+ assert (HagrMid : ctx_types_agree Gmid Gmid')
3671+ by (apply (ctx_types_agree_trans _ G _);
3672+ [ exact (typing_types_agree _ _ _ _ _ H1)
3673+ | apply ctx_types_agree_sym;
3674+ exact (typing_types_agree _ _ _ _ _ H1') ]);
3675+ assert (HagrExt : ctx_types_agree
3676+ (ctx_extend Gmid T1a) (ctx_extend Gmid' T1a))
3677+ by (apply ctx_extend_types_agree; assumption);
3678+ eapply type_determinacy;
3679+ [ exact H2 | exact H2' | exact HagrExt ]
3680+ end
3681+ end
3682+ ].
3683+ (* S_LetLin_Step — same as S_Let_Step. *)
3684+ all: try solve [
3685+ match goal with
3686+ | [ IH : forall (_:mem) (_:region_env) (_:expr) (_:mem) (_:region_env) (_:expr),
3687+ _ = _ -> _ = _ -> forall (_:ctx) (_:ty) (_:ctx),
3688+ _ -> forall (_:ty) (_:ctx), _ -> _ = _,
3689+ Hte : has_type _ _ (ELetLin _ _) _ _,
3690+ Hte' : has_type _ _ (ELetLin _ _) _ _ |- _ ] =>
3691+ inversion Hte; subst;
3692+ inversion Hte'; subst;
3693+ match goal with
3694+ | [ H1 : has_type ?R ?G ?e1 ?T1a ?Gmid,
3695+ H1' : has_type ?R' ?G ?e1' ?T1b ?Gmid',
3696+ H2 : has_type ?R (ctx_extend ?Gmid ?T1a) ?e2 ?T ((?T1a, true) :: ?Ga),
3697+ H2' : has_type ?R' (ctx_extend ?Gmid' ?T1b) ?e2 ?T' ((?T1b, true) :: ?Gb) |- _ ] =>
3698+ pose proof (IH _ _ _ _ _ _ eq_refl eq_refl _ _ _ H1 _ _ H1') as HT1;
3699+ subst T1b;
3700+ assert (HagrMid : ctx_types_agree Gmid Gmid')
3701+ by (apply (ctx_types_agree_trans _ G _);
3702+ [ exact (typing_types_agree _ _ _ _ _ H1)
3703+ | apply ctx_types_agree_sym;
3704+ exact (typing_types_agree _ _ _ _ _ H1') ]);
3705+ assert (HagrExt : ctx_types_agree
3706+ (ctx_extend Gmid T1a) (ctx_extend Gmid' T1a))
3707+ by (apply ctx_extend_types_agree; assumption);
3708+ eapply type_determinacy;
3709+ [ exact H2 | exact H2' | exact HagrExt ]
3710+ end
3711+ end
3712+ ].
3713+ (* ~20 cases remain in step_preserves_type. Closed via the new
3714+ IH-driven recipe: S_StringConcat_Step1, S_App_Step1/Step2,
3715+ S_Let_Val, S_LetLin_Val, S_App_Fun, S_Case_Inl/Inr (and the
3716+ atomic-axiom group from the initial tactic). Remaining cases
3717+ would follow the same recipe + variations for second-child,
3718+ unary, and ternary congruence shapes. The structural template
3719+ is in place; finishing is purely mechanical clone work. *)
3720+ all: admit.
3721+ Admitted .
3722+
33883723(** ** Region-invariance lemma
33893724
33903725 Captures the structural fact that the step relation only changes
0 commit comments