profile
viewpoint

japaric/xargo 790

The sysroot manager that lets you build and customize `std`

Gilnaa/memoffset 84

offsetof for Rust

opatut/dudel 29

This used to be a webapp for scheduling meetings easily. Now it's no longer maintained. Have a look at Bitpoll instead:

Diggsey/rust-field-offset 23

Safe pointer-to-member functionality for rust

RalfJung/ansible 1

ansible playbooks for my servers

freifunk-saar/tunneldigger 0

Client and broker for our custom L2TPv3 NAT-traversing tunnel setup protocol based on L2TPv3 support in the Linux kernel.

hacksaar/Firmware 0

ESP32 firmware for the SHA2017 badge

hacksaar/micropython-esp32 0

MicroPython ported to the SHA2017 badge

pull request commentrust-lang/const-eval

RFC for const-UB

Now I am confused, I was going to update the RFC to incorporate what we discussed.^^

RalfJung

comment created time in 3 hours

Pull request review commentrust-lang/const-eval

RFC for const-UB

+- Feature Name: `const_ub`+- Start Date: 2020-10-10+- RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/0000)+- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000)++# Summary+[summary]: #summary++Define UB during const evaluation to lead to an unspecified result for the affected CTFE query, but not otherwise infect the compilation process.++# Motivation+[motivation]: #motivation++So far, nothing is specified about what happens when `unsafe` code leads to UB during CTFE.+This is a major blocker for stabilizing `unsafe` operations in const-contexts.++# Guide-level explanation+[guide-level-explanation]: #guide-level-explanation++There are some values that Rust needs to compute at compile-time.+This includes the initial value of a `const`/`static`, and array lengths (and more general, const generics).+Computing these initial values is called compile-time function evaluation (CTFE).+CTFE in Rust is very powerful and permits running almost arbitrary Rust code.+This begs the question, what happens when there is `unsafe` code and it causes Undefined Behavior (UB)?++The answer is that in this case, the final value that is currently being executed is arbitrary.+For example, when UB arises while computing an array length, then the final array length can be any `usize`, or it can be (partially) uninitialized memory.+No guarantees are made about this final value, and it can be different depending on host and target architecture, compiler flags, and more.+However, UB will not otherwise adversely affect the currently running compiler; type-checking and lints and everything else will work correctly given whatever the result of the CTFE computation is.++Note, however, that this means compile-time UB can later cause runtime UB when the program is actually executed:+for example, if there is UB while computing the initial value of a `Vec<i32>`, the result might be a completely invalid vector that causes UB at runtime when used in the program.++Sometimes, the compiler might be able to detect such problems and show an error or warning about CTFE computation having gone wrong (for example, the compiler might detect when the array length ends up being uninitialized).+But other times, this might not be the case -- UB is not reliably detected during CTFE.+This can change from compiler version to compiler version: CTFE code that causes UB could build fine with one compiler and fail to build with another.+(This is in accordance with the general policy that unsound code is not subject to strict stability guarantees.)++# Reference-level explanation+[reference-level-explanation]: #reference-level-explanation++When UB arises as part of CTFE, the result of this evaluation is an unspecified constant.+The compiler might be able to detect that UB occurred and raise an error or a warning, but this is not mandated, and absence of lints does not imply absence of UB.

This RFC was at least mentioned at the last meeting so I feel it is fine to be doing it in parallel. We'd still need this even after they signed off the road-map so I do not see a dependency either way here.

RalfJung

comment created time in 4 hours

PullRequestReviewEvent

pull request commentrust-lang/rust

Stabilize the backtrace feature.

@KodrAus FYI, @bjorn3 left a hint at https://github.com/rust-lang/rust/issues/71706#issuecomment-713403545.

withoutboats

comment created time in 4 hours

push eventRalfJung/rust

Ralf Jung

commit sha 8ab831973fb81eed53fb98ddd0efcc4227e954ac

improve formatting

view details

push time in 4 hours

Pull request review commentrust-lang/rust

consider assignments of union field of ManuallyDrop type safe

 impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {                     UnsafetyViolationKind::GeneralAndConstFn,                     UnsafetyViolationDetails::DerefOfRawPointer,                 ),-                ty::Adt(adt, _) => {-                    if adt.is_union() {-                        if context == PlaceContext::MutatingUse(MutatingUseContext::Store)-                            || context == PlaceContext::MutatingUse(MutatingUseContext::Drop)-                            || context == PlaceContext::MutatingUse(MutatingUseContext::AsmOutput)-                        {-                            let elem_ty = match elem {-                                ProjectionElem::Field(_, ty) => ty,-                                _ => span_bug!(-                                    self.source_info.span,-                                    "non-field projection {:?} from union?",-                                    place-                                ),-                            };-                            if !elem_ty.is_copy_modulo_regions(+                ty::Adt(adt, _) if adt.is_union() => {+                    let assign_to_field = context+                        == PlaceContext::MutatingUse(MutatingUseContext::Store)

Your proposal is formatted slightly better:

let assign_to_field = matches!(
                        context,
                        PlaceContext::MutatingUse(
                            MutatingUseContext::Store
                                | MutatingUseContext::Drop
                                | MutatingUseContext::AsmOutput
                        )
                    );

Still not great, but the three alternatives do not fit on one line so it is not easy to make this nice.

RalfJung

comment created time in 4 hours

PullRequestReviewEvent

Pull request review commentrust-lang/rust

consider assignments of union field of ManuallyDrop type safe

 impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {                     UnsafetyViolationKind::GeneralAndConstFn,                     UnsafetyViolationDetails::DerefOfRawPointer,                 ),-                ty::Adt(adt, _) => {-                    if adt.is_union() {-                        if context == PlaceContext::MutatingUse(MutatingUseContext::Store)-                            || context == PlaceContext::MutatingUse(MutatingUseContext::Drop)-                            || context == PlaceContext::MutatingUse(MutatingUseContext::AsmOutput)-                        {-                            let elem_ty = match elem {-                                ProjectionElem::Field(_, ty) => ty,-                                _ => span_bug!(-                                    self.source_info.span,-                                    "non-field projection {:?} from union?",-                                    place-                                ),-                            };-                            if !elem_ty.is_copy_modulo_regions(+                ty::Adt(adt, _) if adt.is_union() => {+                    let assign_to_field = context+                        == PlaceContext::MutatingUse(MutatingUseContext::Store)

I reported this against rustfmt: https://github.com/rust-lang/rustfmt/issues/4492

RalfJung

comment created time in 4 hours

PullRequestReviewEvent

delete branch RalfJung/rust

delete branch : miri

delete time in 4 hours

PullRequestReviewEvent

Pull request review commentrust-lang/const-eval

RFC for const-UB

+- Feature Name: `const_ub`+- Start Date: 2020-10-10+- RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/0000)+- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000)++# Summary+[summary]: #summary++Define UB during const evaluation to lead to an unspecified result for the affected CTFE query, but not otherwise infect the compilation process.++# Motivation+[motivation]: #motivation++So far, nothing is specified about what happens when `unsafe` code leads to UB during CTFE.+This is a major blocker for stabilizing `unsafe` operations in const-contexts.++# Guide-level explanation+[guide-level-explanation]: #guide-level-explanation++There are some values that Rust needs to compute at compile-time.+This includes the initial value of a `const`/`static`, and array lengths (and more general, const generics).+Computing these initial values is called compile-time function evaluation (CTFE).+CTFE in Rust is very powerful and permits running almost arbitrary Rust code.+This begs the question, what happens when there is `unsafe` code and it causes Undefined Behavior (UB)?++The answer is that in this case, the final value that is currently being executed is arbitrary.+For example, when UB arises while computing an array length, then the final array length can be any `usize`, or it can be (partially) uninitialized memory.+No guarantees are made about this final value, and it can be different depending on host and target architecture, compiler flags, and more.+However, UB will not otherwise adversely affect the currently running compiler; type-checking and lints and everything else will work correctly given whatever the result of the CTFE computation is.++Note, however, that this means compile-time UB can later cause runtime UB when the program is actually executed:+for example, if there is UB while computing the initial value of a `Vec<i32>`, the result might be a completely invalid vector that causes UB at runtime when used in the program.++Sometimes, the compiler might be able to detect such problems and show an error or warning about CTFE computation having gone wrong (for example, the compiler might detect when the array length ends up being uninitialized).+But other times, this might not be the case -- UB is not reliably detected during CTFE.+This can change from compiler version to compiler version: CTFE code that causes UB could build fine with one compiler and fail to build with another.+(This is in accordance with the general policy that unsound code is not subject to strict stability guarantees.)++# Reference-level explanation+[reference-level-explanation]: #reference-level-explanation++When UB arises as part of CTFE, the result of this evaluation is an unspecified constant.+The compiler might be able to detect that UB occurred and raise an error or a warning, but this is not mandated, and absence of lints does not imply absence of UB.

Should we? Not sure how the blog post would block even proposing the RFC.

RalfJung

comment created time in 4 hours

push eventmit-pdos/perennial

Ralf Jung

commit sha 83218f55ebbd4a73a06b0d419dbadb36d630ac43

strengthen common_proof lemmas to be Iris-level entailments

view details

push time in 5 hours

issue commentrust-lang/rust

Tracking issue for `&mut T` in const fn

Sometime between nightly-2020-06-03 and nightly-2020-10-25 the compiler changed such that code that previously worked with only a const_fn feature now also requires const_mut_refs (see tock/tock#2175)

Yes, there is work going on towards removing the general const_fn feature and having more specific sub-features instead. In fact, just the const_mut_refs feature should be enough.

So, there is not really a new restriction; this is just the old restriction under a more specific name.

ExpHP

comment created time in 5 hours

push eventmit-pdos/perennial

Ralf Jung

commit sha b2e3c8b9b674b451aff430e4d5c88a6a7e682afc

avoid some \later

view details

push time in 6 hours

issue commentcoq/coq

More setoid_rewrite failures with name mangling

@coqbot: minimize

opam repo add iris-dev https://gitlab.mpi-sws.org/iris/opam.git
opam install -y coq-iris.dev.2020-10-22.1.cfbdb375
eval $(opam env)
mkdir temp
cd temp
cat >bug.v <<EOF
Global Set Mangle Names.

From stdpp Require Import coPset.
From iris.bi Require Import bi.
From iris Require Import options.

(** Definitions. *)
Structure biIndex :=
  BiIndex
    { bi_index_type :> Type;
      bi_index_inhabited : Inhabited bi_index_type;
      bi_index_rel : SqSubsetEq bi_index_type;
      bi_index_rel_preorder : PreOrder (⊑@{bi_index_type}) }.
Existing Instances bi_index_inhabited bi_index_rel bi_index_rel_preorder.

(* We may want to instantiate monPred with the reflexivity relation in
   the case where there is no relevent order. In that case, there is
   no bottom element, so that we do not want to force any BI index to
   have one. *)
Class BiIndexBottom {I : biIndex} (bot : I) :=
  bi_index_bot i : bot ⊑ i.

Section Ofe_Cofe.
Context {I : biIndex} {PROP : bi}.
Implicit Types i : I.

Record monPred :=
  MonPred { monPred_at :> I → PROP;
            monPred_mono : Proper ((⊑) ==> (⊢)) monPred_at }.
Local Existing Instance monPred_mono.

Declare Scope monPred.
Bind Scope monPred with bi.

Implicit Types P Q : monPred.

(** Ofe + Cofe instances  *)

Section Ofe_Cofe_def.
  Inductive monPred_equiv' P Q : Prop :=
    { monPred_in_equiv i : P i ≡ Q i } .
  Instance monPred_equiv : Equiv monPred := monPred_equiv'.
  Inductive monPred_dist' (n : nat) (P Q : monPred) : Prop :=
    { monPred_in_dist i : P i ≡{n}≡ Q i }.
  Instance monPred_dist : Dist monPred := monPred_dist'.

  Definition monPred_sig P : { f : I -d> PROP | Proper ((⊑) ==> (⊢)) f } :=
    exist _ (monPred_at P) (monPred_mono P).

  Definition sig_monPred (P' : { f : I -d> PROP | Proper ((⊑) ==> (⊢)) f })
    : monPred :=
    MonPred (proj1_sig P') (proj2_sig P').

  (* These two lemma use the wrong Equiv and Dist instance for
    monPred. so we make sure they are not accessible outside of the
    section by using Let. *)
  Let monPred_sig_equiv:
    ∀ P Q, P ≡ Q ↔ monPred_sig P ≡ monPred_sig Q.
  Proof. by split; [intros []|]. Qed.
  Let monPred_sig_dist:
    ∀ n, ∀ P Q : monPred, P ≡{n}≡ Q ↔ monPred_sig P ≡{n}≡ monPred_sig Q.
  Proof. by split; [intros []|]. Qed.

  Definition monPred_ofe_mixin : OfeMixin monPred.
  Proof. by apply (iso_ofe_mixin monPred_sig monPred_sig_equiv monPred_sig_dist). Qed.

  Canonical Structure monPredO := OfeT monPred monPred_ofe_mixin.

  Global Instance monPred_cofe {_:Cofe PROP} : Cofe monPredO.
  Proof.
    unshelve refine (iso_cofe_subtype (A:=I-d>PROP) _ MonPred monPred_at _ _ _);
      [apply _|by apply monPred_sig_dist|done|].
    intros c i j Hij. apply @limit_preserving;
      [by apply bi.limit_preserving_entails; intros ??|]=>n. by rewrite Hij.
  Qed.
End Ofe_Cofe_def.

Lemma monPred_sig_monPred (P' : { f : I -d> PROP | Proper ((⊑) ==> (⊢)) f }) :
  monPred_sig (sig_monPred P') ≡ P'.
Proof. by change (P' ≡ P'). Qed.
Lemma sig_monPred_sig P : sig_monPred (monPred_sig P) ≡ P.
Proof. done. Qed.

Global Instance monPred_sig_ne : NonExpansive monPred_sig.
Proof. move=> ??? [?] ? //=. Qed.
Global Instance monPred_sig_proper : Proper ((≡) ==> (≡)) monPred_sig.
Proof. eapply (ne_proper _). Qed.
Global Instance sig_monPred_ne : NonExpansive (@sig_monPred).
Proof. split=>? //=. Qed.
Global Instance sig_monPred_proper : Proper ((≡) ==> (≡)) sig_monPred.
Proof. eapply (ne_proper _). Qed.

(* We generalize over the relation R which is morally the equivalence
   relation over B. That way, the BI index can use equality as an
   equivalence relation (and Coq is able to infer the Proper and
   Reflexive instances properly), or any other equivalence relation,
   provided it is compatible with (⊑). *)
Global Instance monPred_at_ne (R : relation I) :
  Proper (R ==> R ==> iff) (⊑) → Reflexive R →
  ∀ n, Proper (dist n ==> R ==> dist n) monPred_at.
Proof.
  intros ????? [Hd] ?? HR. rewrite Hd.
  apply equiv_dist, bi.equiv_spec; split; f_equiv; rewrite ->HR; done.
Qed.
Global Instance monPred_at_proper (R : relation I) :
  Proper (R ==> R ==> iff) (⊑) → Reflexive R →
  Proper ((≡) ==> R ==> (≡)) monPred_at.
Proof. repeat intro. apply equiv_dist=>?. f_equiv=>//. by apply equiv_dist. Qed.
End Ofe_Cofe.

Arguments monPred _ _ : clear implicits.
Arguments monPred_at {_ _} _%I _.
Local Existing Instance monPred_mono.
Arguments monPredO _ _ : clear implicits.

(** BI canonical structure *)

Section Bi.
Context {I : biIndex} {PROP : bi}.
Implicit Types i : I.
Notation monPred := (monPred I PROP).
Implicit Types P Q : monPred.

Inductive monPred_entails (P1 P2 : monPred) : Prop :=
  { monPred_in_entails i : P1 i ⊢ P2 i }.
Hint Immediate monPred_in_entails : core.

Program Definition monPred_upclosed (Φ : I → PROP) : monPred :=
  MonPred (λ i, (∀ j, ⌜i ⊑ j⌝ → Φ j)%I) _.
Next Obligation. solve_proper. Qed.

Definition monPred_embed_def : Embed PROP monPred := λ (P : PROP), MonPred (λ _, P) _.
Definition monPred_embed_aux : seal (@monPred_embed_def). Proof. by eexists. Qed.
Definition monPred_embed := monPred_embed_aux.(unseal).
Definition monPred_embed_eq : @embed _ _ monPred_embed = _ := monPred_embed_aux.(seal_eq).

Definition monPred_emp_def : monPred := MonPred (λ _, emp)%I _.
Definition monPred_emp_aux : seal (@monPred_emp_def). Proof. by eexists. Qed.
Definition monPred_emp := monPred_emp_aux.(unseal).
Definition monPred_emp_eq : @monPred_emp = _ := monPred_emp_aux.(seal_eq).

Definition monPred_pure_def (φ : Prop) : monPred := MonPred (λ _, ⌜φ⌝)%I _.
Definition monPred_pure_aux : seal (@monPred_pure_def). Proof. by eexists. Qed.
Definition monPred_pure := monPred_pure_aux.(unseal).
Definition monPred_pure_eq : @monPred_pure = _ := monPred_pure_aux.(seal_eq).

Definition monPred_objectively_def P : monPred := MonPred (λ _, ∀ i, P i)%I _.
Definition monPred_objectively_aux : seal (@monPred_objectively_def). Proof. by eexists. Qed.
Definition monPred_objectively := monPred_objectively_aux.(unseal).
Definition monPred_objectively_eq : @monPred_objectively = _ := monPred_objectively_aux.(seal_eq).

Definition monPred_subjectively_def P : monPred := MonPred (λ _, ∃ i, P i)%I _.
Definition monPred_subjectively_aux : seal (@monPred_subjectively_def). Proof. by eexists. Qed.
Definition monPred_subjectively := monPred_subjectively_aux.(unseal).
Definition monPred_subjectively_eq : @monPred_subjectively = _ := monPred_subjectively_aux.(seal_eq).

Program Definition monPred_and_def P Q : monPred :=
  MonPred (λ i, P i ∧ Q i)%I _.
Next Obligation. solve_proper. Qed.
Definition monPred_and_aux : seal (@monPred_and_def). Proof. by eexists. Qed.
Definition monPred_and := monPred_and_aux.(unseal).
Definition monPred_and_eq : @monPred_and = _ := monPred_and_aux.(seal_eq).

Program Definition monPred_or_def P Q : monPred :=
  MonPred (λ i, P i ∨ Q i)%I _.
Next Obligation. solve_proper. Qed.
Definition monPred_or_aux : seal (@monPred_or_def). Proof. by eexists. Qed.
Definition monPred_or := monPred_or_aux.(unseal).
Definition monPred_or_eq : @monPred_or = _ := monPred_or_aux.(seal_eq).

Definition monPred_impl_def P Q : monPred :=
  monPred_upclosed (λ i, P i → Q i)%I.
Definition monPred_impl_aux : seal (@monPred_impl_def). Proof. by eexists. Qed.
Definition monPred_impl := monPred_impl_aux.(unseal).
Definition monPred_impl_eq : @monPred_impl = _ := monPred_impl_aux.(seal_eq).

Program Definition monPred_forall_def A (Φ : A → monPred) : monPred :=
  MonPred (λ i, ∀ x : A, Φ x i)%I _.
Next Obligation. solve_proper. Qed.
Definition monPred_forall_aux : seal (@monPred_forall_def). Proof. by eexists. Qed.
Definition monPred_forall := monPred_forall_aux.(unseal).
Definition monPred_forall_eq : @monPred_forall = _ := monPred_forall_aux.(seal_eq).

Program Definition monPred_exist_def A (Φ : A → monPred) : monPred :=
  MonPred (λ i, ∃ x : A, Φ x i)%I _.
Next Obligation. solve_proper. Qed.
Definition monPred_exist_aux : seal (@monPred_exist_def). Proof. by eexists. Qed.
Definition monPred_exist := monPred_exist_aux.(unseal).
Definition monPred_exist_eq : @monPred_exist = _ := monPred_exist_aux.(seal_eq).

Program Definition monPred_sep_def P Q : monPred :=
  MonPred (λ i, P i ∗ Q i)%I _.
Next Obligation. solve_proper. Qed.
Definition monPred_sep_aux : seal (@monPred_sep_def). Proof. by eexists. Qed.
Definition monPred_sep := monPred_sep_aux.(unseal).
Definition monPred_sep_eq : @monPred_sep = _ := monPred_sep_aux.(seal_eq).

Definition monPred_wand_def P Q : monPred :=
  monPred_upclosed (λ i, P i -∗ Q i)%I.
Definition monPred_wand_aux : seal (@monPred_wand_def). Proof. by eexists. Qed.
Definition monPred_wand := monPred_wand_aux.(unseal).
Definition monPred_wand_eq : @monPred_wand = _ := monPred_wand_aux.(seal_eq).

Program Definition monPred_persistently_def P : monPred :=
  MonPred (λ i, <pers> (P i))%I _.
Next Obligation. solve_proper. Qed.
Definition monPred_persistently_aux : seal (@monPred_persistently_def). Proof. by eexists. Qed.
Definition monPred_persistently := monPred_persistently_aux.(unseal).
Definition monPred_persistently_eq : @monPred_persistently = _ := monPred_persistently_aux.(seal_eq).

Program Definition monPred_in_def (i0 : I) : monPred :=
  MonPred (λ i : I, ⌜i0 ⊑ i⌝%I) _.
Next Obligation. solve_proper. Qed.
Definition monPred_in_aux : seal (@monPred_in_def). Proof. by eexists. Qed.
Definition monPred_in := monPred_in_aux.(unseal).
Definition monPred_in_eq : @monPred_in = _ := monPred_in_aux.(seal_eq).

Program Definition monPred_later_def P : monPred := MonPred (λ i, ▷ (P i))%I _.
Next Obligation. solve_proper. Qed.
Definition monPred_later_aux : seal monPred_later_def. Proof. by eexists. Qed.
Definition monPred_later := monPred_later_aux.(unseal).
Definition monPred_later_eq : monPred_later = _ := monPred_later_aux.(seal_eq).
End Bi.

Arguments monPred_objectively {_ _} _%I.
Arguments monPred_subjectively {_ _} _%I.
Notation "'<obj>' P" := (monPred_objectively P) : bi_scope.
Notation "'<subj>' P" := (monPred_subjectively P) : bi_scope.

Module MonPred.
Definition unseal_eqs :=
  (@monPred_and_eq, @monPred_or_eq, @monPred_impl_eq,
   @monPred_forall_eq, @monPred_exist_eq, @monPred_sep_eq, @monPred_wand_eq,
   @monPred_persistently_eq, @monPred_later_eq, @monPred_in_eq,
   @monPred_embed_eq, @monPred_emp_eq, @monPred_pure_eq,
   @monPred_objectively_eq, @monPred_subjectively_eq).
Ltac unseal :=
  unfold bi_affinely, bi_absorbingly, bi_except_0, bi_pure, bi_emp,
         monPred_upclosed, bi_and, bi_or,
         bi_impl, bi_forall, bi_exist, bi_sep, bi_wand,
         bi_persistently, bi_affinely, bi_later;
  simpl;
  rewrite !unseal_eqs /=.
End MonPred.
Import MonPred.

Section canonical.
Context (I : biIndex) (PROP : bi).

Lemma monPred_bi_mixin : BiMixin (PROP:=monPred I PROP)
  monPred_entails monPred_emp monPred_pure monPred_and monPred_or
  monPred_impl monPred_forall monPred_exist monPred_sep monPred_wand
  monPred_persistently.
Proof.
  split; try unseal; try by (split=> ? /=; repeat f_equiv).
  - split.
    + intros P. by split.
    + intros P Q R [H1] [H2]. split => ?. by rewrite H1 H2.
  - split.
    + intros [HPQ]. split; split => i; move: (HPQ i); by apply bi.equiv_spec.
    + intros [[] []]. split=>i. by apply bi.equiv_spec.
  - intros P φ ?. split=> i. by apply bi.pure_intro.
  - intros φ P HP. split=> i. apply bi.pure_elim'=> ?. by apply HP.
  - intros P Q. split=> i. by apply bi.and_elim_l.
  - intros P Q. split=> i. by apply bi.and_elim_r.
  - intros P Q R [?] [?]. split=> i. by apply bi.and_intro.
  - intros P Q. split=> i. by apply bi.or_intro_l.
  - intros P Q. split=> i. by apply bi.or_intro_r.
  - intros P Q R [?] [?]. split=> i. by apply bi.or_elim.
  - intros P Q R [HR]. split=> i /=. setoid_rewrite bi.pure_impl_forall.
    apply bi.forall_intro=> j. apply bi.forall_intro=> Hij.
    apply bi.impl_intro_r. by rewrite -HR /= !Hij.
  - intros P Q R [HR]. split=> i /=.
     rewrite HR /= bi.forall_elim bi.pure_impl_forall bi.forall_elim //.
    apply bi.impl_elim_l.
  - intros A P Ψ HΨ. split=> i. apply bi.forall_intro => ?. by apply HΨ.
  - intros A Ψ. split=> i. by apply: bi.forall_elim.
  - intros A Ψ a. split=> i. by rewrite /= -bi.exist_intro.
  - intros A Ψ Q HΨ. split=> i. apply bi.exist_elim => a. by apply HΨ.
  - intros P P' Q Q' [?] [?]. split=> i. by apply bi.sep_mono.
  - intros P. split=> i. by apply bi.emp_sep_1.
  - intros P. split=> i. by apply bi.emp_sep_2.
  - intros P Q. split=> i. by apply bi.sep_comm'.
  - intros P Q R. split=> i. by apply bi.sep_assoc'.
  - intros P Q R [HR]. split=> i /=. setoid_rewrite bi.pure_impl_forall.
    apply bi.forall_intro=> j. apply bi.forall_intro=> Hij.
    apply bi.wand_intro_r. by rewrite -HR /= !Hij.
  - intros P Q R [HP]. split=> i. apply bi.wand_elim_l'.
    rewrite HP /= bi.forall_elim bi.pure_impl_forall bi.forall_elim //.
  - intros P Q [?]. split=> i /=. by f_equiv.
  - intros P. split=> i. by apply bi.persistently_idemp_2.
  - split=> i. by apply bi.persistently_emp_intro.
  - intros A Ψ. split=> i. by apply bi.persistently_forall_2.
  - intros A Ψ. split=> i. by apply bi.persistently_exist_1.
  - intros P Q. split=> i. apply bi.sep_elim_l, _.
  - intros P Q. split=> i. by apply bi.persistently_and_sep_elim.
Qed.

Lemma monPred_bi_later_mixin :
  BiLaterMixin (PROP:=monPred I PROP) monPred_entails monPred_pure
               monPred_or monPred_impl monPred_forall monPred_exist
               monPred_sep monPred_persistently monPred_later.
Proof.
  split; unseal.
  - by split=> ? /=; repeat f_equiv.
  - intros P Q [?]. split=> i. by apply bi.later_mono.
  - intros P. split=> i /=. by apply bi.later_intro.
  - intros A Ψ. split=> i. by apply bi.later_forall_2.
  - intros A Ψ. split=> i. by apply bi.later_exist_false.
  - intros P Q. split=> i. by apply bi.later_sep_1.
  - intros P Q. split=> i. by apply bi.later_sep_2.
  - intros P. split=> i. by apply bi.later_persistently_1.
  - intros P. split=> i. by apply bi.later_persistently_2.
  - intros P. split=> i /=. rewrite -bi.forall_intro. apply bi.later_false_em.
    intros j. rewrite bi.pure_impl_forall. apply bi.forall_intro=> Hij. by rewrite Hij.
Qed.

Canonical Structure monPredI : bi :=
  {| bi_ofe_mixin := monPred_ofe_mixin; bi_bi_mixin := monPred_bi_mixin;
     bi_bi_later_mixin := monPred_bi_later_mixin |}.
End canonical.

Class Objective {I : biIndex} {PROP : bi} (P : monPred I PROP) :=
  objective_at i j : P i -∗ P j.
Arguments Objective {_ _} _%I.
Arguments objective_at {_ _} _%I {_}.
Hint Mode Objective + + ! : typeclass_instances.
Instance: Params (@Objective) 2 := {}.

(** Primitive facts that cannot be deduced from the BI structure. *)

Section bi_facts.
Context {I : biIndex} {PROP : bi}.
Local Notation monPred := (monPred I PROP).
Local Notation monPredI := (monPredI I PROP).
Local Notation monPred_at := (@monPred_at I PROP).
Local Notation BiIndexBottom := (@BiIndexBottom I).
Implicit Types i : I.
Implicit Types P Q : monPred.

Lemma monPred_wand_force i P Q : (P -∗ Q) i -∗ (P i -∗ Q i).
Proof. unseal. rewrite bi.forall_elim bi.pure_impl_forall bi.forall_elim //. Qed.
Lemma monPred_impl_force i P Q : (P → Q) i -∗ (P i → Q i).
Proof. unseal. rewrite bi.forall_elim bi.pure_impl_forall bi.forall_elim //. Qed.

(** Plainly *)
Definition monPred_plainly_def {_:BiPlainly PROP} P : monPred :=
  MonPred (λ _, ∀ i, ■ (P i))%I _.
Definition monPred_plainly_aux : seal (@monPred_plainly_def). Proof. by eexists. Qed.
Definition monPred_plainly := monPred_plainly_aux.(unseal).
Arguments monPred_plainly {_}.
Lemma monPred_plainly_eq {_:BiPlainly PROP} : @plainly _ monPred_plainly = monPred_plainly_def.
Proof. rewrite -monPred_plainly_aux.(seal_eq) //. Qed.

Lemma monPred_plainly_mixin {_:BiPlainly PROP} : BiPlainlyMixin monPredI monPred_plainly.
Proof.
  split; rewrite monPred_plainly_eq; try unseal.
  - by (split=> ? /=; repeat f_equiv).
  - intros P Q [?]. split=> i /=. by do 3 f_equiv.
  - intros P. split=> i /=. by rewrite bi.forall_elim plainly_elim_persistently.
  - intros P. split=> i /=. do 3 setoid_rewrite <-plainly_forall.
    rewrite -plainly_idemp_2. f_equiv. by apply bi.forall_intro=>_.
  - intros A Ψ. split=> i /=. apply bi.forall_intro=> j.
    rewrite plainly_forall. apply bi.forall_intro=> a. by rewrite !bi.forall_elim.
  - intros P Q. split=> i /=. setoid_rewrite bi.pure_impl_forall.
    setoid_rewrite <-plainly_forall.
    do 2 setoid_rewrite bi.persistently_forall. do 4 f_equiv.
    apply persistently_impl_plainly.
  - intros P Q. split=> i /=.
    setoid_rewrite bi.pure_impl_forall. rewrite 2!bi.forall_elim //.
    do 2 setoid_rewrite <-plainly_forall.
    setoid_rewrite plainly_impl_plainly. f_equiv.
    do 3 apply bi.forall_intro => ?. f_equiv. rewrite bi.forall_elim //.
  - intros P. split=> i /=. apply bi.forall_intro=>_. by apply plainly_emp_intro.
  - intros P Q. split=> i. apply bi.sep_elim_l, _.
  - intros P. split=> i /=.
    rewrite bi.later_forall. f_equiv=> j. by rewrite -later_plainly_1.
  - intros P. split=> i /=.
    rewrite bi.later_forall. f_equiv=> j. by rewrite -later_plainly_2.
Qed.

EOF
coqc -q bug.v
RalfJung

comment created time in 8 hours

issue commentrust-lang/rust

repr(transparent) on generic type skips "exactly one non-zero-sized field" check

I wouldn't call () "arbitrary". It is basically the canonical "informationless type" in Rust, or "final element" in category theory speak -- similar to how ! is the canonical "uninhabited type" or "initial element".

So, specifying () as a canonical representative of 1-ZST makes a lot of sense IMO.

mahkoh

comment created time in 8 hours

issue commentcoq/coq

More setoid_rewrite failures with name mangling

@coqbot: minimize

opam repo add iris-dev https://gitlab.mpi-sws.org/iris/opam.git
opam install -y coq-iris.dev.2020-10-22.1.cfbdb375
eval $(opam env)
mkdir temp
cd temp
cat >bug.v <<EOF
Global Set Mangle Names.

From stdpp Require Import coPset.
From iris.bi Require Import bi.
From iris Require Import options.

(** Definitions. *)
Structure biIndex :=
  BiIndex
    { bi_index_type :> Type;
      bi_index_inhabited : Inhabited bi_index_type;
      bi_index_rel : SqSubsetEq bi_index_type;
      bi_index_rel_preorder : PreOrder (⊑@{bi_index_type}) }.
Existing Instances bi_index_inhabited bi_index_rel bi_index_rel_preorder.

(* We may want to instantiate monPred with the reflexivity relation in
   the case where there is no relevent order. In that case, there is
   no bottom element, so that we do not want to force any BI index to
   have one. *)
Class BiIndexBottom {I : biIndex} (bot : I) :=
  bi_index_bot i : bot ⊑ i.

Section Ofe_Cofe.
Context {I : biIndex} {PROP : bi}.
Implicit Types i : I.

Record monPred :=
  MonPred { monPred_at :> I → PROP;
            monPred_mono : Proper ((⊑) ==> (⊢)) monPred_at }.
Local Existing Instance monPred_mono.

Declare Scope monPred.
Bind Scope monPred with bi.

Implicit Types P Q : monPred.

(** Ofe + Cofe instances  *)

Section Ofe_Cofe_def.
  Inductive monPred_equiv' P Q : Prop :=
    { monPred_in_equiv i : P i ≡ Q i } .
  Instance monPred_equiv : Equiv monPred := monPred_equiv'.
  Inductive monPred_dist' (n : nat) (P Q : monPred) : Prop :=
    { monPred_in_dist i : P i ≡{n}≡ Q i }.
  Instance monPred_dist : Dist monPred := monPred_dist'.

  Definition monPred_sig P : { f : I -d> PROP | Proper ((⊑) ==> (⊢)) f } :=
    exist _ (monPred_at P) (monPred_mono P).

  Definition sig_monPred (P' : { f : I -d> PROP | Proper ((⊑) ==> (⊢)) f })
    : monPred :=
    MonPred (proj1_sig P') (proj2_sig P').

  (* These two lemma use the wrong Equiv and Dist instance for
    monPred. so we make sure they are not accessible outside of the
    section by using Let. *)
  Let monPred_sig_equiv:
    ∀ P Q, P ≡ Q ↔ monPred_sig P ≡ monPred_sig Q.
  Proof. by split; [intros []|]. Qed.
  Let monPred_sig_dist:
    ∀ n, ∀ P Q : monPred, P ≡{n}≡ Q ↔ monPred_sig P ≡{n}≡ monPred_sig Q.
  Proof. by split; [intros []|]. Qed.

  Definition monPred_ofe_mixin : OfeMixin monPred.
  Proof. by apply (iso_ofe_mixin monPred_sig monPred_sig_equiv monPred_sig_dist). Qed.

  Canonical Structure monPredO := OfeT monPred monPred_ofe_mixin.

  Global Instance monPred_cofe `{Cofe PROP} : Cofe monPredO.
  Proof.
    unshelve refine (iso_cofe_subtype (A:=I-d>PROP) _ MonPred monPred_at _ _ _);
      [apply _|by apply monPred_sig_dist|done|].
    intros c i j Hij. apply @limit_preserving;
      [by apply bi.limit_preserving_entails; intros ??|]=>n. by rewrite Hij.
  Qed.
End Ofe_Cofe_def.

Lemma monPred_sig_monPred (P' : { f : I -d> PROP | Proper ((⊑) ==> (⊢)) f }) :
  monPred_sig (sig_monPred P') ≡ P'.
Proof. by change (P' ≡ P'). Qed.
Lemma sig_monPred_sig P : sig_monPred (monPred_sig P) ≡ P.
Proof. done. Qed.

Global Instance monPred_sig_ne : NonExpansive monPred_sig.
Proof. move=> ??? [?] ? //=. Qed.
Global Instance monPred_sig_proper : Proper ((≡) ==> (≡)) monPred_sig.
Proof. eapply (ne_proper _). Qed.
Global Instance sig_monPred_ne : NonExpansive (@sig_monPred).
Proof. split=>? //=. Qed.
Global Instance sig_monPred_proper : Proper ((≡) ==> (≡)) sig_monPred.
Proof. eapply (ne_proper _). Qed.

(* We generalize over the relation R which is morally the equivalence
   relation over B. That way, the BI index can use equality as an
   equivalence relation (and Coq is able to infer the Proper and
   Reflexive instances properly), or any other equivalence relation,
   provided it is compatible with (⊑). *)
Global Instance monPred_at_ne (R : relation I) :
  Proper (R ==> R ==> iff) (⊑) → Reflexive R →
  ∀ n, Proper (dist n ==> R ==> dist n) monPred_at.
Proof.
  intros ????? [Hd] ?? HR. rewrite Hd.
  apply equiv_dist, bi.equiv_spec; split; f_equiv; rewrite ->HR; done.
Qed.
Global Instance monPred_at_proper (R : relation I) :
  Proper (R ==> R ==> iff) (⊑) → Reflexive R →
  Proper ((≡) ==> R ==> (≡)) monPred_at.
Proof. repeat intro. apply equiv_dist=>?. f_equiv=>//. by apply equiv_dist. Qed.
End Ofe_Cofe.

Arguments monPred _ _ : clear implicits.
Arguments monPred_at {_ _} _%I _.
Local Existing Instance monPred_mono.
Arguments monPredO _ _ : clear implicits.

(** BI canonical structure *)

Section Bi.
Context {I : biIndex} {PROP : bi}.
Implicit Types i : I.
Notation monPred := (monPred I PROP).
Implicit Types P Q : monPred.

Inductive monPred_entails (P1 P2 : monPred) : Prop :=
  { monPred_in_entails i : P1 i ⊢ P2 i }.
Hint Immediate monPred_in_entails : core.

Program Definition monPred_upclosed (Φ : I → PROP) : monPred :=
  MonPred (λ i, (∀ j, ⌜i ⊑ j⌝ → Φ j)%I) _.
Next Obligation. solve_proper. Qed.

Definition monPred_embed_def : Embed PROP monPred := λ (P : PROP), MonPred (λ _, P) _.
Definition monPred_embed_aux : seal (@monPred_embed_def). Proof. by eexists. Qed.
Definition monPred_embed := monPred_embed_aux.(unseal).
Definition monPred_embed_eq : @embed _ _ monPred_embed = _ := monPred_embed_aux.(seal_eq).

Definition monPred_emp_def : monPred := MonPred (λ _, emp)%I _.
Definition monPred_emp_aux : seal (@monPred_emp_def). Proof. by eexists. Qed.
Definition monPred_emp := monPred_emp_aux.(unseal).
Definition monPred_emp_eq : @monPred_emp = _ := monPred_emp_aux.(seal_eq).

Definition monPred_pure_def (φ : Prop) : monPred := MonPred (λ _, ⌜φ⌝)%I _.
Definition monPred_pure_aux : seal (@monPred_pure_def). Proof. by eexists. Qed.
Definition monPred_pure := monPred_pure_aux.(unseal).
Definition monPred_pure_eq : @monPred_pure = _ := monPred_pure_aux.(seal_eq).

Definition monPred_objectively_def P : monPred := MonPred (λ _, ∀ i, P i)%I _.
Definition monPred_objectively_aux : seal (@monPred_objectively_def). Proof. by eexists. Qed.
Definition monPred_objectively := monPred_objectively_aux.(unseal).
Definition monPred_objectively_eq : @monPred_objectively = _ := monPred_objectively_aux.(seal_eq).

Definition monPred_subjectively_def P : monPred := MonPred (λ _, ∃ i, P i)%I _.
Definition monPred_subjectively_aux : seal (@monPred_subjectively_def). Proof. by eexists. Qed.
Definition monPred_subjectively := monPred_subjectively_aux.(unseal).
Definition monPred_subjectively_eq : @monPred_subjectively = _ := monPred_subjectively_aux.(seal_eq).

Program Definition monPred_and_def P Q : monPred :=
  MonPred (λ i, P i ∧ Q i)%I _.
Next Obligation. solve_proper. Qed.
Definition monPred_and_aux : seal (@monPred_and_def). Proof. by eexists. Qed.
Definition monPred_and := monPred_and_aux.(unseal).
Definition monPred_and_eq : @monPred_and = _ := monPred_and_aux.(seal_eq).

Program Definition monPred_or_def P Q : monPred :=
  MonPred (λ i, P i ∨ Q i)%I _.
Next Obligation. solve_proper. Qed.
Definition monPred_or_aux : seal (@monPred_or_def). Proof. by eexists. Qed.
Definition monPred_or := monPred_or_aux.(unseal).
Definition monPred_or_eq : @monPred_or = _ := monPred_or_aux.(seal_eq).

Definition monPred_impl_def P Q : monPred :=
  monPred_upclosed (λ i, P i → Q i)%I.
Definition monPred_impl_aux : seal (@monPred_impl_def). Proof. by eexists. Qed.
Definition monPred_impl := monPred_impl_aux.(unseal).
Definition monPred_impl_eq : @monPred_impl = _ := monPred_impl_aux.(seal_eq).

Program Definition monPred_forall_def A (Φ : A → monPred) : monPred :=
  MonPred (λ i, ∀ x : A, Φ x i)%I _.
Next Obligation. solve_proper. Qed.
Definition monPred_forall_aux : seal (@monPred_forall_def). Proof. by eexists. Qed.
Definition monPred_forall := monPred_forall_aux.(unseal).
Definition monPred_forall_eq : @monPred_forall = _ := monPred_forall_aux.(seal_eq).

Program Definition monPred_exist_def A (Φ : A → monPred) : monPred :=
  MonPred (λ i, ∃ x : A, Φ x i)%I _.
Next Obligation. solve_proper. Qed.
Definition monPred_exist_aux : seal (@monPred_exist_def). Proof. by eexists. Qed.
Definition monPred_exist := monPred_exist_aux.(unseal).
Definition monPred_exist_eq : @monPred_exist = _ := monPred_exist_aux.(seal_eq).

Program Definition monPred_sep_def P Q : monPred :=
  MonPred (λ i, P i ∗ Q i)%I _.
Next Obligation. solve_proper. Qed.
Definition monPred_sep_aux : seal (@monPred_sep_def). Proof. by eexists. Qed.
Definition monPred_sep := monPred_sep_aux.(unseal).
Definition monPred_sep_eq : @monPred_sep = _ := monPred_sep_aux.(seal_eq).

Definition monPred_wand_def P Q : monPred :=
  monPred_upclosed (λ i, P i -∗ Q i)%I.
Definition monPred_wand_aux : seal (@monPred_wand_def). Proof. by eexists. Qed.
Definition monPred_wand := monPred_wand_aux.(unseal).
Definition monPred_wand_eq : @monPred_wand = _ := monPred_wand_aux.(seal_eq).

Program Definition monPred_persistently_def P : monPred :=
  MonPred (λ i, <pers> (P i))%I _.
Next Obligation. solve_proper. Qed.
Definition monPred_persistently_aux : seal (@monPred_persistently_def). Proof. by eexists. Qed.
Definition monPred_persistently := monPred_persistently_aux.(unseal).
Definition monPred_persistently_eq : @monPred_persistently = _ := monPred_persistently_aux.(seal_eq).

Program Definition monPred_in_def (i0 : I) : monPred :=
  MonPred (λ i : I, ⌜i0 ⊑ i⌝%I) _.
Next Obligation. solve_proper. Qed.
Definition monPred_in_aux : seal (@monPred_in_def). Proof. by eexists. Qed.
Definition monPred_in := monPred_in_aux.(unseal).
Definition monPred_in_eq : @monPred_in = _ := monPred_in_aux.(seal_eq).

Program Definition monPred_later_def P : monPred := MonPred (λ i, ▷ (P i))%I _.
Next Obligation. solve_proper. Qed.
Definition monPred_later_aux : seal monPred_later_def. Proof. by eexists. Qed.
Definition monPred_later := monPred_later_aux.(unseal).
Definition monPred_later_eq : monPred_later = _ := monPred_later_aux.(seal_eq).
End Bi.

Arguments monPred_objectively {_ _} _%I.
Arguments monPred_subjectively {_ _} _%I.
Notation "'<obj>' P" := (monPred_objectively P) : bi_scope.
Notation "'<subj>' P" := (monPred_subjectively P) : bi_scope.

Module MonPred.
Definition unseal_eqs :=
  (@monPred_and_eq, @monPred_or_eq, @monPred_impl_eq,
   @monPred_forall_eq, @monPred_exist_eq, @monPred_sep_eq, @monPred_wand_eq,
   @monPred_persistently_eq, @monPred_later_eq, @monPred_in_eq,
   @monPred_embed_eq, @monPred_emp_eq, @monPred_pure_eq,
   @monPred_objectively_eq, @monPred_subjectively_eq).
Ltac unseal :=
  unfold bi_affinely, bi_absorbingly, bi_except_0, bi_pure, bi_emp,
         monPred_upclosed, bi_and, bi_or,
         bi_impl, bi_forall, bi_exist, bi_sep, bi_wand,
         bi_persistently, bi_affinely, bi_later;
  simpl;
  rewrite !unseal_eqs /=.
End MonPred.
Import MonPred.

Section canonical.
Context (I : biIndex) (PROP : bi).

Lemma monPred_bi_mixin : BiMixin (PROP:=monPred I PROP)
  monPred_entails monPred_emp monPred_pure monPred_and monPred_or
  monPred_impl monPred_forall monPred_exist monPred_sep monPred_wand
  monPred_persistently.
Proof.
  split; try unseal; try by (split=> ? /=; repeat f_equiv).
  - split.
    + intros P. by split.
    + intros P Q R [H1] [H2]. split => ?. by rewrite H1 H2.
  - split.
    + intros [HPQ]. split; split => i; move: (HPQ i); by apply bi.equiv_spec.
    + intros [[] []]. split=>i. by apply bi.equiv_spec.
  - intros P φ ?. split=> i. by apply bi.pure_intro.
  - intros φ P HP. split=> i. apply bi.pure_elim'=> ?. by apply HP.
  - intros P Q. split=> i. by apply bi.and_elim_l.
  - intros P Q. split=> i. by apply bi.and_elim_r.
  - intros P Q R [?] [?]. split=> i. by apply bi.and_intro.
  - intros P Q. split=> i. by apply bi.or_intro_l.
  - intros P Q. split=> i. by apply bi.or_intro_r.
  - intros P Q R [?] [?]. split=> i. by apply bi.or_elim.
  - intros P Q R [HR]. split=> i /=. setoid_rewrite bi.pure_impl_forall.
    apply bi.forall_intro=> j. apply bi.forall_intro=> Hij.
    apply bi.impl_intro_r. by rewrite -HR /= !Hij.
  - intros P Q R [HR]. split=> i /=.
     rewrite HR /= bi.forall_elim bi.pure_impl_forall bi.forall_elim //.
    apply bi.impl_elim_l.
  - intros A P Ψ HΨ. split=> i. apply bi.forall_intro => ?. by apply HΨ.
  - intros A Ψ. split=> i. by apply: bi.forall_elim.
  - intros A Ψ a. split=> i. by rewrite /= -bi.exist_intro.
  - intros A Ψ Q HΨ. split=> i. apply bi.exist_elim => a. by apply HΨ.
  - intros P P' Q Q' [?] [?]. split=> i. by apply bi.sep_mono.
  - intros P. split=> i. by apply bi.emp_sep_1.
  - intros P. split=> i. by apply bi.emp_sep_2.
  - intros P Q. split=> i. by apply bi.sep_comm'.
  - intros P Q R. split=> i. by apply bi.sep_assoc'.
  - intros P Q R [HR]. split=> i /=. setoid_rewrite bi.pure_impl_forall.
    apply bi.forall_intro=> j. apply bi.forall_intro=> Hij.
    apply bi.wand_intro_r. by rewrite -HR /= !Hij.
  - intros P Q R [HP]. split=> i. apply bi.wand_elim_l'.
    rewrite HP /= bi.forall_elim bi.pure_impl_forall bi.forall_elim //.
  - intros P Q [?]. split=> i /=. by f_equiv.
  - intros P. split=> i. by apply bi.persistently_idemp_2.
  - split=> i. by apply bi.persistently_emp_intro.
  - intros A Ψ. split=> i. by apply bi.persistently_forall_2.
  - intros A Ψ. split=> i. by apply bi.persistently_exist_1.
  - intros P Q. split=> i. apply bi.sep_elim_l, _.
  - intros P Q. split=> i. by apply bi.persistently_and_sep_elim.
Qed.

Lemma monPred_bi_later_mixin :
  BiLaterMixin (PROP:=monPred I PROP) monPred_entails monPred_pure
               monPred_or monPred_impl monPred_forall monPred_exist
               monPred_sep monPred_persistently monPred_later.
Proof.
  split; unseal.
  - by split=> ? /=; repeat f_equiv.
  - intros P Q [?]. split=> i. by apply bi.later_mono.
  - intros P. split=> i /=. by apply bi.later_intro.
  - intros A Ψ. split=> i. by apply bi.later_forall_2.
  - intros A Ψ. split=> i. by apply bi.later_exist_false.
  - intros P Q. split=> i. by apply bi.later_sep_1.
  - intros P Q. split=> i. by apply bi.later_sep_2.
  - intros P. split=> i. by apply bi.later_persistently_1.
  - intros P. split=> i. by apply bi.later_persistently_2.
  - intros P. split=> i /=. rewrite -bi.forall_intro. apply bi.later_false_em.
    intros j. rewrite bi.pure_impl_forall. apply bi.forall_intro=> Hij. by rewrite Hij.
Qed.

Canonical Structure monPredI : bi :=
  {| bi_ofe_mixin := monPred_ofe_mixin; bi_bi_mixin := monPred_bi_mixin;
     bi_bi_later_mixin := monPred_bi_later_mixin |}.
End canonical.

Class Objective {I : biIndex} {PROP : bi} (P : monPred I PROP) :=
  objective_at i j : P i -∗ P j.
Arguments Objective {_ _} _%I.
Arguments objective_at {_ _} _%I {_}.
Hint Mode Objective + + ! : typeclass_instances.
Instance: Params (@Objective) 2 := {}.

(** Primitive facts that cannot be deduced from the BI structure. *)

Section bi_facts.
Context {I : biIndex} {PROP : bi}.
Local Notation monPred := (monPred I PROP).
Local Notation monPredI := (monPredI I PROP).
Local Notation monPred_at := (@monPred_at I PROP).
Local Notation BiIndexBottom := (@BiIndexBottom I).
Implicit Types i : I.
Implicit Types P Q : monPred.

Lemma monPred_wand_force i P Q : (P -∗ Q) i -∗ (P i -∗ Q i).
Proof. unseal. rewrite bi.forall_elim bi.pure_impl_forall bi.forall_elim //. Qed.
Lemma monPred_impl_force i P Q : (P → Q) i -∗ (P i → Q i).
Proof. unseal. rewrite bi.forall_elim bi.pure_impl_forall bi.forall_elim //. Qed.

(** Plainly *)
Definition monPred_plainly_def `{BiPlainly PROP} P : monPred :=
  MonPred (λ _, ∀ i, ■ (P i))%I _.
Definition monPred_plainly_aux : seal (@monPred_plainly_def). Proof. by eexists. Qed.
Definition monPred_plainly := monPred_plainly_aux.(unseal).
Arguments monPred_plainly {_}.
Lemma monPred_plainly_eq `{BiPlainly PROP} : @plainly _ monPred_plainly = monPred_plainly_def.
Proof. rewrite -monPred_plainly_aux.(seal_eq) //. Qed.

Lemma monPred_plainly_mixin `{BiPlainly PROP} : BiPlainlyMixin monPredI monPred_plainly.
Proof.
  split; rewrite monPred_plainly_eq; try unseal.
  - by (split=> ? /=; repeat f_equiv).
  - intros P Q [?]. split=> i /=. by do 3 f_equiv.
  - intros P. split=> i /=. by rewrite bi.forall_elim plainly_elim_persistently.
  - intros P. split=> i /=. do 3 setoid_rewrite <-plainly_forall.
    rewrite -plainly_idemp_2. f_equiv. by apply bi.forall_intro=>_.
  - intros A Ψ. split=> i /=. apply bi.forall_intro=> j.
    rewrite plainly_forall. apply bi.forall_intro=> a. by rewrite !bi.forall_elim.
  - intros P Q. split=> i /=. setoid_rewrite bi.pure_impl_forall.
    setoid_rewrite <-plainly_forall.
    do 2 setoid_rewrite bi.persistently_forall. do 4 f_equiv.
    apply persistently_impl_plainly.
  - intros P Q. split=> i /=.
    setoid_rewrite bi.pure_impl_forall. rewrite 2!bi.forall_elim //.
    do 2 setoid_rewrite <-plainly_forall.
    setoid_rewrite plainly_impl_plainly. f_equiv.
    do 3 apply bi.forall_intro => ?. f_equiv. rewrite bi.forall_elim //.
  - intros P. split=> i /=. apply bi.forall_intro=>_. by apply plainly_emp_intro.
  - intros P Q. split=> i. apply bi.sep_elim_l, _.
  - intros P. split=> i /=.
    rewrite bi.later_forall. f_equiv=> j. by rewrite -later_plainly_1.
  - intros P. split=> i /=.
    rewrite bi.later_forall. f_equiv=> j. by rewrite -later_plainly_2.
Qed.
EOF
coqc -q bug.v
RalfJung

comment created time in 9 hours

issue commentcoq/coq

More setoid_rewrite failures with name mangling

Let's see if we can get the coqbot to minimize this... @coqbot: minimize

opam repo add iris-dev https://gitlab.mpi-sws.org/iris/opam.git
opam install -y coq-iris.dev.2020-10-22.1.cfbdb375
eval $(opam env)
mkdir temp
cd temp
cat >bug.v <<EOF
Global Set Mangle Names.

From stdpp Require Import coPset.
From iris.bi Require Import bi.
From iris Require Import options.

(** Definitions. *)
Structure biIndex :=
  BiIndex
    { bi_index_type :> Type;
      bi_index_inhabited : Inhabited bi_index_type;
      bi_index_rel : SqSubsetEq bi_index_type;
      bi_index_rel_preorder : PreOrder (⊑@{bi_index_type}) }.
Existing Instances bi_index_inhabited bi_index_rel bi_index_rel_preorder.

(* We may want to instantiate monPred with the reflexivity relation in
   the case where there is no relevent order. In that case, there is
   no bottom element, so that we do not want to force any BI index to
   have one. *)
Class BiIndexBottom {I : biIndex} (bot : I) :=
  bi_index_bot i : bot ⊑ i.

Section Ofe_Cofe.
Context {I : biIndex} {PROP : bi}.
Implicit Types i : I.

Record monPred :=
  MonPred { monPred_at :> I → PROP;
            monPred_mono : Proper ((⊑) ==> (⊢)) monPred_at }.
Local Existing Instance monPred_mono.

Declare Scope monPred.
Bind Scope monPred with bi.

Implicit Types P Q : monPred.

(** Ofe + Cofe instances  *)

Section Ofe_Cofe_def.
  Inductive monPred_equiv' P Q : Prop :=
    { monPred_in_equiv i : P i ≡ Q i } .
  Instance monPred_equiv : Equiv monPred := monPred_equiv'.
  Inductive monPred_dist' (n : nat) (P Q : monPred) : Prop :=
    { monPred_in_dist i : P i ≡{n}≡ Q i }.
  Instance monPred_dist : Dist monPred := monPred_dist'.

  Definition monPred_sig P : { f : I -d> PROP | Proper ((⊑) ==> (⊢)) f } :=
    exist _ (monPred_at P) (monPred_mono P).

  Definition sig_monPred (P' : { f : I -d> PROP | Proper ((⊑) ==> (⊢)) f })
    : monPred :=
    MonPred (proj1_sig P') (proj2_sig P').

  (* These two lemma use the wrong Equiv and Dist instance for
    monPred. so we make sure they are not accessible outside of the
    section by using Let. *)
  Let monPred_sig_equiv:
    ∀ P Q, P ≡ Q ↔ monPred_sig P ≡ monPred_sig Q.
  Proof. by split; [intros []|]. Qed.
  Let monPred_sig_dist:
    ∀ n, ∀ P Q : monPred, P ≡{n}≡ Q ↔ monPred_sig P ≡{n}≡ monPred_sig Q.
  Proof. by split; [intros []|]. Qed.

  Definition monPred_ofe_mixin : OfeMixin monPred.
  Proof. by apply (iso_ofe_mixin monPred_sig monPred_sig_equiv monPred_sig_dist). Qed.

  Canonical Structure monPredO := OfeT monPred monPred_ofe_mixin.

  Global Instance monPred_cofe `{Cofe PROP} : Cofe monPredO.
  Proof.
    unshelve refine (iso_cofe_subtype (A:=I-d>PROP) _ MonPred monPred_at _ _ _);
      [apply _|by apply monPred_sig_dist|done|].
    intros c i j Hij. apply @limit_preserving;
      [by apply bi.limit_preserving_entails; intros ??|]=>n. by rewrite Hij.
  Qed.
End Ofe_Cofe_def.

Lemma monPred_sig_monPred (P' : { f : I -d> PROP | Proper ((⊑) ==> (⊢)) f }) :
  monPred_sig (sig_monPred P') ≡ P'.
Proof. by change (P' ≡ P'). Qed.
Lemma sig_monPred_sig P : sig_monPred (monPred_sig P) ≡ P.
Proof. done. Qed.

Global Instance monPred_sig_ne : NonExpansive monPred_sig.
Proof. move=> ??? [?] ? //=. Qed.
Global Instance monPred_sig_proper : Proper ((≡) ==> (≡)) monPred_sig.
Proof. eapply (ne_proper _). Qed.
Global Instance sig_monPred_ne : NonExpansive (@sig_monPred).
Proof. split=>? //=. Qed.
Global Instance sig_monPred_proper : Proper ((≡) ==> (≡)) sig_monPred.
Proof. eapply (ne_proper _). Qed.

(* We generalize over the relation R which is morally the equivalence
   relation over B. That way, the BI index can use equality as an
   equivalence relation (and Coq is able to infer the Proper and
   Reflexive instances properly), or any other equivalence relation,
   provided it is compatible with (⊑). *)
Global Instance monPred_at_ne (R : relation I) :
  Proper (R ==> R ==> iff) (⊑) → Reflexive R →
  ∀ n, Proper (dist n ==> R ==> dist n) monPred_at.
Proof.
  intros ????? [Hd] ?? HR. rewrite Hd.
  apply equiv_dist, bi.equiv_spec; split; f_equiv; rewrite ->HR; done.
Qed.
Global Instance monPred_at_proper (R : relation I) :
  Proper (R ==> R ==> iff) (⊑) → Reflexive R →
  Proper ((≡) ==> R ==> (≡)) monPred_at.
Proof. repeat intro. apply equiv_dist=>?. f_equiv=>//. by apply equiv_dist. Qed.
End Ofe_Cofe.

Arguments monPred _ _ : clear implicits.
Arguments monPred_at {_ _} _%I _.
Local Existing Instance monPred_mono.
Arguments monPredO _ _ : clear implicits.

(** BI canonical structure *)

Section Bi.
Context {I : biIndex} {PROP : bi}.
Implicit Types i : I.
Notation monPred := (monPred I PROP).
Implicit Types P Q : monPred.

Inductive monPred_entails (P1 P2 : monPred) : Prop :=
  { monPred_in_entails i : P1 i ⊢ P2 i }.
Hint Immediate monPred_in_entails : core.

Program Definition monPred_upclosed (Φ : I → PROP) : monPred :=
  MonPred (λ i, (∀ j, ⌜i ⊑ j⌝ → Φ j)%I) _.
Next Obligation. solve_proper. Qed.

Definition monPred_embed_def : Embed PROP monPred := λ (P : PROP), MonPred (λ _, P) _.
Definition monPred_embed_aux : seal (@monPred_embed_def). Proof. by eexists. Qed.
Definition monPred_embed := monPred_embed_aux.(unseal).
Definition monPred_embed_eq : @embed _ _ monPred_embed = _ := monPred_embed_aux.(seal_eq).

Definition monPred_emp_def : monPred := MonPred (λ _, emp)%I _.
Definition monPred_emp_aux : seal (@monPred_emp_def). Proof. by eexists. Qed.
Definition monPred_emp := monPred_emp_aux.(unseal).
Definition monPred_emp_eq : @monPred_emp = _ := monPred_emp_aux.(seal_eq).

Definition monPred_pure_def (φ : Prop) : monPred := MonPred (λ _, ⌜φ⌝)%I _.
Definition monPred_pure_aux : seal (@monPred_pure_def). Proof. by eexists. Qed.
Definition monPred_pure := monPred_pure_aux.(unseal).
Definition monPred_pure_eq : @monPred_pure = _ := monPred_pure_aux.(seal_eq).

Definition monPred_objectively_def P : monPred := MonPred (λ _, ∀ i, P i)%I _.
Definition monPred_objectively_aux : seal (@monPred_objectively_def). Proof. by eexists. Qed.
Definition monPred_objectively := monPred_objectively_aux.(unseal).
Definition monPred_objectively_eq : @monPred_objectively = _ := monPred_objectively_aux.(seal_eq).

Definition monPred_subjectively_def P : monPred := MonPred (λ _, ∃ i, P i)%I _.
Definition monPred_subjectively_aux : seal (@monPred_subjectively_def). Proof. by eexists. Qed.
Definition monPred_subjectively := monPred_subjectively_aux.(unseal).
Definition monPred_subjectively_eq : @monPred_subjectively = _ := monPred_subjectively_aux.(seal_eq).

Program Definition monPred_and_def P Q : monPred :=
  MonPred (λ i, P i ∧ Q i)%I _.
Next Obligation. solve_proper. Qed.
Definition monPred_and_aux : seal (@monPred_and_def). Proof. by eexists. Qed.
Definition monPred_and := monPred_and_aux.(unseal).
Definition monPred_and_eq : @monPred_and = _ := monPred_and_aux.(seal_eq).

Program Definition monPred_or_def P Q : monPred :=
  MonPred (λ i, P i ∨ Q i)%I _.
Next Obligation. solve_proper. Qed.
Definition monPred_or_aux : seal (@monPred_or_def). Proof. by eexists. Qed.
Definition monPred_or := monPred_or_aux.(unseal).
Definition monPred_or_eq : @monPred_or = _ := monPred_or_aux.(seal_eq).

Definition monPred_impl_def P Q : monPred :=
  monPred_upclosed (λ i, P i → Q i)%I.
Definition monPred_impl_aux : seal (@monPred_impl_def). Proof. by eexists. Qed.
Definition monPred_impl := monPred_impl_aux.(unseal).
Definition monPred_impl_eq : @monPred_impl = _ := monPred_impl_aux.(seal_eq).

Program Definition monPred_forall_def A (Φ : A → monPred) : monPred :=
  MonPred (λ i, ∀ x : A, Φ x i)%I _.
Next Obligation. solve_proper. Qed.
Definition monPred_forall_aux : seal (@monPred_forall_def). Proof. by eexists. Qed.
Definition monPred_forall := monPred_forall_aux.(unseal).
Definition monPred_forall_eq : @monPred_forall = _ := monPred_forall_aux.(seal_eq).

Program Definition monPred_exist_def A (Φ : A → monPred) : monPred :=
  MonPred (λ i, ∃ x : A, Φ x i)%I _.
Next Obligation. solve_proper. Qed.
Definition monPred_exist_aux : seal (@monPred_exist_def). Proof. by eexists. Qed.
Definition monPred_exist := monPred_exist_aux.(unseal).
Definition monPred_exist_eq : @monPred_exist = _ := monPred_exist_aux.(seal_eq).

Program Definition monPred_sep_def P Q : monPred :=
  MonPred (λ i, P i ∗ Q i)%I _.
Next Obligation. solve_proper. Qed.
Definition monPred_sep_aux : seal (@monPred_sep_def). Proof. by eexists. Qed.
Definition monPred_sep := monPred_sep_aux.(unseal).
Definition monPred_sep_eq : @monPred_sep = _ := monPred_sep_aux.(seal_eq).

Definition monPred_wand_def P Q : monPred :=
  monPred_upclosed (λ i, P i -∗ Q i)%I.
Definition monPred_wand_aux : seal (@monPred_wand_def). Proof. by eexists. Qed.
Definition monPred_wand := monPred_wand_aux.(unseal).
Definition monPred_wand_eq : @monPred_wand = _ := monPred_wand_aux.(seal_eq).

Program Definition monPred_persistently_def P : monPred :=
  MonPred (λ i, <pers> (P i))%I _.
Next Obligation. solve_proper. Qed.
Definition monPred_persistently_aux : seal (@monPred_persistently_def). Proof. by eexists. Qed.
Definition monPred_persistently := monPred_persistently_aux.(unseal).
Definition monPred_persistently_eq : @monPred_persistently = _ := monPred_persistently_aux.(seal_eq).

Program Definition monPred_in_def (i0 : I) : monPred :=
  MonPred (λ i : I, ⌜i0 ⊑ i⌝%I) _.
Next Obligation. solve_proper. Qed.
Definition monPred_in_aux : seal (@monPred_in_def). Proof. by eexists. Qed.
Definition monPred_in := monPred_in_aux.(unseal).
Definition monPred_in_eq : @monPred_in = _ := monPred_in_aux.(seal_eq).

Program Definition monPred_later_def P : monPred := MonPred (λ i, ▷ (P i))%I _.
Next Obligation. solve_proper. Qed.
Definition monPred_later_aux : seal monPred_later_def. Proof. by eexists. Qed.
Definition monPred_later := monPred_later_aux.(unseal).
Definition monPred_later_eq : monPred_later = _ := monPred_later_aux.(seal_eq).
End Bi.

Arguments monPred_objectively {_ _} _%I.
Arguments monPred_subjectively {_ _} _%I.
Notation "'<obj>' P" := (monPred_objectively P) : bi_scope.
Notation "'<subj>' P" := (monPred_subjectively P) : bi_scope.

Module MonPred.
Definition unseal_eqs :=
  (@monPred_and_eq, @monPred_or_eq, @monPred_impl_eq,
   @monPred_forall_eq, @monPred_exist_eq, @monPred_sep_eq, @monPred_wand_eq,
   @monPred_persistently_eq, @monPred_later_eq, @monPred_in_eq,
   @monPred_embed_eq, @monPred_emp_eq, @monPred_pure_eq,
   @monPred_objectively_eq, @monPred_subjectively_eq).
Ltac unseal :=
  unfold bi_affinely, bi_absorbingly, bi_except_0, bi_pure, bi_emp,
         monPred_upclosed, bi_and, bi_or,
         bi_impl, bi_forall, bi_exist, bi_sep, bi_wand,
         bi_persistently, bi_affinely, bi_later;
  simpl;
  rewrite !unseal_eqs /=.
End MonPred.
Import MonPred.

Section canonical.
Context (I : biIndex) (PROP : bi).

Lemma monPred_bi_mixin : BiMixin (PROP:=monPred I PROP)
  monPred_entails monPred_emp monPred_pure monPred_and monPred_or
  monPred_impl monPred_forall monPred_exist monPred_sep monPred_wand
  monPred_persistently.
Proof.
  split; try unseal; try by (split=> ? /=; repeat f_equiv).
  - split.
    + intros P. by split.
    + intros P Q R [H1] [H2]. split => ?. by rewrite H1 H2.
  - split.
    + intros [HPQ]. split; split => i; move: (HPQ i); by apply bi.equiv_spec.
    + intros [[] []]. split=>i. by apply bi.equiv_spec.
  - intros P φ ?. split=> i. by apply bi.pure_intro.
  - intros φ P HP. split=> i. apply bi.pure_elim'=> ?. by apply HP.
  - intros P Q. split=> i. by apply bi.and_elim_l.
  - intros P Q. split=> i. by apply bi.and_elim_r.
  - intros P Q R [?] [?]. split=> i. by apply bi.and_intro.
  - intros P Q. split=> i. by apply bi.or_intro_l.
  - intros P Q. split=> i. by apply bi.or_intro_r.
  - intros P Q R [?] [?]. split=> i. by apply bi.or_elim.
  - intros P Q R [HR]. split=> i /=. setoid_rewrite bi.pure_impl_forall.
    apply bi.forall_intro=> j. apply bi.forall_intro=> Hij.
    apply bi.impl_intro_r. by rewrite -HR /= !Hij.
  - intros P Q R [HR]. split=> i /=.
     rewrite HR /= bi.forall_elim bi.pure_impl_forall bi.forall_elim //.
    apply bi.impl_elim_l.
  - intros A P Ψ HΨ. split=> i. apply bi.forall_intro => ?. by apply HΨ.
  - intros A Ψ. split=> i. by apply: bi.forall_elim.
  - intros A Ψ a. split=> i. by rewrite /= -bi.exist_intro.
  - intros A Ψ Q HΨ. split=> i. apply bi.exist_elim => a. by apply HΨ.
  - intros P P' Q Q' [?] [?]. split=> i. by apply bi.sep_mono.
  - intros P. split=> i. by apply bi.emp_sep_1.
  - intros P. split=> i. by apply bi.emp_sep_2.
  - intros P Q. split=> i. by apply bi.sep_comm'.
  - intros P Q R. split=> i. by apply bi.sep_assoc'.
  - intros P Q R [HR]. split=> i /=. setoid_rewrite bi.pure_impl_forall.
    apply bi.forall_intro=> j. apply bi.forall_intro=> Hij.
    apply bi.wand_intro_r. by rewrite -HR /= !Hij.
  - intros P Q R [HP]. split=> i. apply bi.wand_elim_l'.
    rewrite HP /= bi.forall_elim bi.pure_impl_forall bi.forall_elim //.
  - intros P Q [?]. split=> i /=. by f_equiv.
  - intros P. split=> i. by apply bi.persistently_idemp_2.
  - split=> i. by apply bi.persistently_emp_intro.
  - intros A Ψ. split=> i. by apply bi.persistently_forall_2.
  - intros A Ψ. split=> i. by apply bi.persistently_exist_1.
  - intros P Q. split=> i. apply bi.sep_elim_l, _.
  - intros P Q. split=> i. by apply bi.persistently_and_sep_elim.
Qed.

Lemma monPred_bi_later_mixin :
  BiLaterMixin (PROP:=monPred I PROP) monPred_entails monPred_pure
               monPred_or monPred_impl monPred_forall monPred_exist
               monPred_sep monPred_persistently monPred_later.
Proof.
  split; unseal.
  - by split=> ? /=; repeat f_equiv.
  - intros P Q [?]. split=> i. by apply bi.later_mono.
  - intros P. split=> i /=. by apply bi.later_intro.
  - intros A Ψ. split=> i. by apply bi.later_forall_2.
  - intros A Ψ. split=> i. by apply bi.later_exist_false.
  - intros P Q. split=> i. by apply bi.later_sep_1.
  - intros P Q. split=> i. by apply bi.later_sep_2.
  - intros P. split=> i. by apply bi.later_persistently_1.
  - intros P. split=> i. by apply bi.later_persistently_2.
  - intros P. split=> i /=. rewrite -bi.forall_intro. apply bi.later_false_em.
    intros j. rewrite bi.pure_impl_forall. apply bi.forall_intro=> Hij. by rewrite Hij.
Qed.

Canonical Structure monPredI : bi :=
  {| bi_ofe_mixin := monPred_ofe_mixin; bi_bi_mixin := monPred_bi_mixin;
     bi_bi_later_mixin := monPred_bi_later_mixin |}.
End canonical.

Class Objective {I : biIndex} {PROP : bi} (P : monPred I PROP) :=
  objective_at i j : P i -∗ P j.
Arguments Objective {_ _} _%I.
Arguments objective_at {_ _} _%I {_}.
Hint Mode Objective + + ! : typeclass_instances.
Instance: Params (@Objective) 2 := {}.

(** Primitive facts that cannot be deduced from the BI structure. *)

Section bi_facts.
Context {I : biIndex} {PROP : bi}.
Local Notation monPred := (monPred I PROP).
Local Notation monPredI := (monPredI I PROP).
Local Notation monPred_at := (@monPred_at I PROP).
Local Notation BiIndexBottom := (@BiIndexBottom I).
Implicit Types i : I.
Implicit Types P Q : monPred.

Lemma monPred_wand_force i P Q : (P -∗ Q) i -∗ (P i -∗ Q i).
Proof. unseal. rewrite bi.forall_elim bi.pure_impl_forall bi.forall_elim //. Qed.
Lemma monPred_impl_force i P Q : (P → Q) i -∗ (P i → Q i).
Proof. unseal. rewrite bi.forall_elim bi.pure_impl_forall bi.forall_elim //. Qed.

(** Plainly *)
Definition monPred_plainly_def `{BiPlainly PROP} P : monPred :=
  MonPred (λ _, ∀ i, ■ (P i))%I _.
Definition monPred_plainly_aux : seal (@monPred_plainly_def). Proof. by eexists. Qed.
Definition monPred_plainly := monPred_plainly_aux.(unseal).
Arguments monPred_plainly {_}.
Lemma monPred_plainly_eq `{BiPlainly PROP} : @plainly _ monPred_plainly = monPred_plainly_def.
Proof. rewrite -monPred_plainly_aux.(seal_eq) //. Qed.

Lemma monPred_plainly_mixin `{BiPlainly PROP} : BiPlainlyMixin monPredI monPred_plainly.
Proof.
  split; rewrite monPred_plainly_eq; try unseal.
  - by (split=> ? /=; repeat f_equiv).
  - intros P Q [?]. split=> i /=. by do 3 f_equiv.
  - intros P. split=> i /=. by rewrite bi.forall_elim plainly_elim_persistently.
  - intros P. split=> i /=. do 3 setoid_rewrite <-plainly_forall.
    rewrite -plainly_idemp_2. f_equiv. by apply bi.forall_intro=>_.
  - intros A Ψ. split=> i /=. apply bi.forall_intro=> j.
    rewrite plainly_forall. apply bi.forall_intro=> a. by rewrite !bi.forall_elim.
  - intros P Q. split=> i /=. setoid_rewrite bi.pure_impl_forall.
    setoid_rewrite <-plainly_forall.
    do 2 setoid_rewrite bi.persistently_forall. do 4 f_equiv.
    apply persistently_impl_plainly.
  - intros P Q. split=> i /=.
    setoid_rewrite bi.pure_impl_forall. rewrite 2!bi.forall_elim //.
    do 2 setoid_rewrite <-plainly_forall.
    setoid_rewrite plainly_impl_plainly. f_equiv.
    do 3 apply bi.forall_intro => ?. f_equiv. rewrite bi.forall_elim //.
  - intros P. split=> i /=. apply bi.forall_intro=>_. by apply plainly_emp_intro.
  - intros P Q. split=> i. apply bi.sep_elim_l, _.
  - intros P. split=> i /=.
    rewrite bi.later_forall. f_equiv=> j. by rewrite -later_plainly_1.
  - intros P. split=> i /=.
    rewrite bi.later_forall. f_equiv=> j. by rewrite -later_plainly_2.
Qed.
EOF
coqc -q bug.v
RalfJung

comment created time in 9 hours

pull request commentrust-lang/rust

update Miri

@bors p=1

RalfJung

comment created time in 9 hours

pull request commentcoq/coq

Re-importing notations give them again a higher priority

Actually, after having fallen on this problem, I made #12986 which orders notation by precision. I'll try to experiment it on Iris to see what it gives.

That sounds great!

Actually, after having fallen on this problem, I made #12986 which orders notation by precision. I'll try to experiment it on Iris to see what it gives. One the problem is that to experiment, it is not only about compiling but also about interactively using the feature. So would you eventually be ok to work with a version of Coq providing #12986 and give feedback on whether this is a good strategy or not?

I can offer to look through some of our files with that patch -- but I think our printing test suite will already catch many problems, like it caught this one. That is exactly why we added it -- not to defend against changes on the Coq side, but because printing is so fragile that we wanted to defend against breaking this accidentally by reordering some imports somewhere.

Thinking aloud, maybe do we need another command such as Ensure library which reexport only if not already imported once.

That brings back some bad memories from my C/C++ days, of things like #ifndef HEADER_NAME...

I think part of the problem here is hat Export does two things that we cannot disentangle:

  • it provides "global effects" such as notation and canonical structures
  • it embeds the names of that library into the current namespace

For canonical structures at least, import order does not matter, so Export of just those is never a problem. The same might be true with notation once we have something like #12986 (and maybe a way to give notation a "printing priority" to break ties?). But for names the "last import wins". I think I'd be fine having to directly Import every library tat provides a name that I use in the current .v file (i.e., work as if there was no Export anywhere), but doing that for notation and canonical structures would be really painful.

herbelin

comment created time in 9 hours

pull request commentrust-lang/rust

update Miri

@bors r+

RalfJung

comment created time in 11 hours

PR opened rust-lang/rust

update Miri

Fixes https://github.com/rust-lang/rust/issues/78339 Cc @rust-lang/miri r? @ghost

+1 -1

0 comment

1 changed file

pr created time in 11 hours

create barnchRalfJung/rust

branch : miri

created branch time in 11 hours

delete branch RalfJung/rust

delete branch : uninhabited-statics

delete time in 11 hours

delete branch RalfJung/rust

delete branch : transmute_copy

delete time in 11 hours

delete branch RalfJung/rust

delete branch : miri-comments

delete time in 11 hours

delete branch RalfJung/rust

delete branch : dont-promote-unions

delete time in 11 hours

pull request commentcoq/coq

Re-importing notations give them again a higher priority

To take a step back: currently, notation printing feels very fragile. Some Iris notation sometimes fails to print, and I have spent some hours and then given up figuring out where that comes from and instead just randomly reordered imports until it works. (I also entirely failed to minimize this problem of even reproduce it properly without a crazy dependency chain, which is why I never got around to make a bugreport.) The current conclusion is that we give very specific import order advice to our users, and that seems to mostly work very well -- but this PR breaks that advice.

I think to fix this and to have behavior more in line with user expectations (at least for Iris), printing precedence needs to be less dependent on import order. For cases like the code in the PR description, using import order seems fine, and I agree that "last import wins" is more consistent (that's also how name resolution works -- this does lead to problems but at least it is somewhat predictable).

But for cases where one notation clearly "specializes" another, I think import order should not matter:

Module A. Notation "# P" := (True /\ P) (at level 20, P at level 40). End A.
Module B. Notation "##" := (True /\ True). End B.
Import A. Import B. Import A.
Check (True /\ True).
(* Should print `##`. *)

Am I right that with this PR, that will print # True instead? That seems to be what happens on the Iris side.

herbelin

comment created time in 11 hours

pull request commentcoq/coq

Re-importing notations give them again a higher priority

Importation of notations is made more inline with the expected behavior of Import

FWIW, given the consequences for Iris, I disagree that this is expected behavior. This change makes specializing notation essentially impossible: for example, for a project using Utf8 notation, there is no good way to have any notation with a top-level forall:

  • As that Iris change shows, for that notation to work, the specialized notation needs to be imported last. This means every client, transitively throughout the entire stack of libraries, needs to be aware of this and also explicitly import this last. Modularity is entirely lost, this change will have to be done in every Coq file that imports Iris.
  • And if that was not bad enough, this breaks down the moment there are two such "specializing" notations: only one of them can be imported last, so the other one will always be broken.

The only alternative is to never Export Utf8, and instead have an Import Utf8 in every single file. And of course Utf8 is not special here, any module defining notation where other modules might want to introduce more specialized notation for some cases potentially has this problem. As far as I can see, this means there is no good way to use Export in a library, ever.

On CI it looks like Iris is the only project that is affected, but that might be because Iris is the only project to test notation printing. I expect this PR will break notation printing all over the place; I do not feel like what we are doing in Iris (defining a notation for a term that already has a notation) is particularly uncommon.

herbelin

comment created time in 11 hours

delete branch RalfJung/const-eval

delete branch : promotion

delete time in 11 hours

create barnchRalfJung/const-eval

branch : promotion

created branch time in 12 hours

pull request commentcoq/coq

adjust Search deprecation warning

Squashed.

RalfJung

comment created time in 12 hours

push eventRalfJung/coq

Ralf Jung

commit sha a2ce4da4c2b0dc81d4c61f3e672d6c9d65dba46b

adjust Search deprecation warning

view details

push time in 12 hours

push eventRalfJung/ansible

Ralf Jung

commit sha c1f305f1d26a92eaa7130394d3e04f27b4149107

journalwatch: ignore some openvpn messages

view details

push time in 12 hours

pull request commentrust-lang/rust

Move "mutable thing in const" check from interning to validity

@bors r=oli-obk

RalfJung

comment created time in 14 hours

Pull request review commentrust-lang/rust

Update RELEASES.md for 1.48.0

+Version 1.48.0 (2020-11-19)+==========================++Language+--------++- [The `unsafe` keyword is now syntactically permitted on modules.][75857] This+  is still rejected *semantically*, but can now be parsed by procedural macros.++Compiler+--------+- [Stabilised the `-C link-self-contained=<yes|no>`][76158] Which tells `rustc` whether to link+  its own C runtime and libraries or to rely on a external linker to find them. (supported only on+  `windows-gnu`, `linux-musl`, and `wasi` platforms.)+- [You can now use `-C target-feature=+crt-static` on `linux-gnu` targets.][77386]+- [Added tier 2\* support for `aarch64-unknown-linux-musl`.][76420]++\* Refer to Rust's [platform support page][forge-platform-support] for more+information on Rust's tiered platform support.++Libraries+---------+- [`io::Write` is now implemented for `&ChildStdin` `&Sink`, `&Stdout`,+  and `&Stderr`.][76275]+- [All arrays now implement `TryFrom<Vec<T>>`.][76310]+- [The `matches!` macro now supports having a trailing comma.][74880]+- [`Vec<A>` now implements `PartialEq<[B]>` where `A: PartialEq<B>`.][74194]+- [Nearly all of `Cell`'s panicking functions now use the `#[track_caller]`+  attribute.][77055]++Stabilized APIs+---------------+- [`slice::as_ptr_range`]+- [`slice::as_mut_ptr_range`]+- [`VecDeque::make_contiguous`]+- [`future::pending`]+- [`future::ready`]++The following previously stable methods are now `const fn`'s:++- [`Option::is_some`]+- [`Option::is_none`]+- [`Option::as_ref`]+- [`Result::is_ok`]+- [`Result::is_err`]+- [`Result::as_ref`]+- [`Ordering::reverse`]+- [`Ordering::then`]++Cargo+-----++Misc+----+- [You can now link to different items in `rustdoc` using the intra-doc link+  syntax.][74430] E.g. ``/// Uses [`std::future`]`` will automatically generate+  a link to `std::future`'s documentation. See ["Linking to items by+  name"][intradoc-links] for more information.+- [You can now specify `#[doc(alias = "<alias>")]` on items to add search aliases+  when searching through `rustdoc`'s UI.][75740]+- [You can now use `rustup install <major>.<minor>` to specify installing the+  latest available patch of that minor version of the toolchain.][76107] E.g.+  `rustup install 1.45` would install `1.45.2`, and `1.46` would install `1.46.0`.++Compatibility Notes+-------------------+- [`const fn`s are now implicitly promoted to `const`.][75502] Meaning that it+  will only warn if your code fails `const` evaluation, and not produce an error.

Yeah that description does not seem to have much to do with what the PR does.

A short summary could be something like: promotion of references to 'static lifetime inside const fn now follows the same rules as inside fn; in particular, &foo() will not be promoted to 'static lifetime any more inside const fn.

This is a bugfix, we should never have done this to begin with. It is part of an ongoing effort to fix promotion, and then to restrict it a bit further to make it less painful throughout the compiler (see https://github.com/rust-lang/const-eval/issues/53).

XAMPPRocky

comment created time in 14 hours

PullRequestReviewEvent

push eventRalfJung/rust

rail

commit sha dc89bb1135afc31fc9ee2272e627192c04354d22

Use if_chain in Increment/InitializeVisitor

view details

rail

commit sha 116f30dc33d9e3744f257f2f7f5467acfbff178b

Use else blocks instead of return statements in Increment/InitializeVisitor

view details

rail

commit sha b2d5b89a1de15df9052fdf44d01b174add82837f

Check if it's after the loop earlier

view details

rail

commit sha 31cb1109648bf4242cab47571343578244e7fb9d

add concinient methods to Increment/InitializeVisitor

view details

rail

commit sha c599e2fcfaaedb12b560f4136bab3d0b450acf8f

Split VarState

view details

rail

commit sha 13c207d3756754c54a6b20d852087616d5abfbf4

Generalise `InitializeVisitor`

view details

rail

commit sha 9573a0d378033a81e55ca834a5d305d3cf2be24d

Rename variables

view details

rail

commit sha 1026b42f0694eb9239b5cebe80be743d5ded0da5

Rename a struct and variables

view details

rail

commit sha b4b4da162f19e9a4c63854a2b5a6167b83f9d8b9

Introduce Start and StartKind

view details

rail

commit sha 720f19f2ec4282f636889b35beabf31272e3b1b2

Implement detecting `manual_memcpy` with loop counters

view details

rail

commit sha de56279cd9047832216e1d1c06dc45375bf01b31

Implement building the `manual_memcpy` sugggestion with loop counters

view details

rail

commit sha 8da6cfd17b7707d678d01a6688572169015ea83e

fmt

view details

rail

commit sha d9a88be0b05c2cfec0679caf428d129c9d46256d

Rename `get_offset` and its private items

view details

rail

commit sha 774e82a566c6c3349700a8bece44d6a8c6755039

Add the tests for `manual_memcpy` with loop counters

view details

rail

commit sha 9aad38bf614c3fb6d306f5dec4a0af606bb3c9c8

Update `manual_memcpy.stderr` to reflect additional parentheses

view details

rail

commit sha 4ea4a972500a8ddecfc737d51eec960324dcb02f

Add tests for bitwise operations

view details

rail

commit sha eb3ffe6ed2999e9d3385be0ff981e30082ea0d2c

make use of macros in operator overloading

view details

rail

commit sha 10d7a18f72155f03dbd27b872a52b5dd45def8db

fmt

view details

rail

commit sha 174065fc98ef9335ea45a234aa18286cdf6c3934

fix the multiple counters test

view details

rail

commit sha 44187383f4724bd7e4b2b220235e93438043947a

Use operator overloading instead of direct calls of `make_binop`

view details

push time in 15 hours

pull request commentrust-lang/homu

Add a "create a similar rollup" link in rollup PR body

It's been a while since I did rollups but this looks great. :-)

oliviacrain

comment created time in 15 hours

Pull request review commentrust-lang/rust

[WIP] Add const qualifier in FnSig (for const fn pointers)

+#![feature(const_fn)]+#![feature(const_fn_pointer)]+#[allow(dead_code)]++const fn const_fn() { }+fn not_const_fn() { }+unsafe fn unsafe_fn() { }+const unsafe fn const_unsafe_fn() { }++const _: fn() = const_fn;+const _: unsafe fn() = const_fn;+const _: const unsafe fn() = const_fn;++const _: const fn() = not_const_fn;+//~^ ERROR mismatched types++const _: const fn() = unsafe_fn;+//~^ ERROR mismatched types++const _: const unsafe fn() = unsafe_fn;+//~^ ERROR mismatched types++const _: unsafe fn() = const_unsafe_fn;

The file is called "const_fn_ptr_cast" but it only seems to check coercions, not casts (via as). Is that the same code in the compiler or should as-casts be tested explicitly as well?

filtsin

comment created time in 15 hours

PullRequestReviewEvent

Pull request review commentrust-lang/rust

[WIP] Add const qualifier in FnSig (for const fn pointers)

 impl Visitor<'tcx> for Validator<'mir, 'tcx> {                 let (mut callee, substs) = match *fn_ty.kind() {                     ty::FnDef(def_id, substs) => (def_id, substs), -                    ty::FnPtr(_) => {+                    ty::FnPtr(fn_sig) => {+                        // At this point, we are calling a function by raw pointer because+                        // we know that it is const+                        if self.ccx.tcx.features().const_fn_pointer

What do you mean with "by raw pointer"? A raw pointer would be *const T/*mut T, and I do not think there is such a pointer here.

filtsin

comment created time in 15 hours

PullRequestReviewEvent

Pull request review commentrust-lang/rust

[WIP] Add const qualifier in FnSig (for const fn pointers)

 impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {                 }             } +            Pointer(PointerCast::NotConstFnPointer) => {+                let src = self.read_immediate(src)?;+                match cast_ty.kind() {+                    ty::FnPtr(_) => {+                        // No change to value+                        self.write_immediate(*src, dest)?;+                    }

Please merge these two new match arms into the existing one for UnsafeFnPointer... seems unnecessary to duplicate that code.

filtsin

comment created time in 15 hours

PullRequestReviewEvent

pull request commentrust-lang/rust

Crater expeximent: can we remove this weird special case from promotion?

@craterbot check

RalfJung

comment created time in a day

pull request commentrust-lang/rust

Crater expeximent: can we remove this weird special case from promotion?

eh... @bors try

RalfJung

comment created time in a day

pull request commentrust-lang/rust

Crater expeximent: can we remove this weird special case from promotion?

@bors retry

RalfJung

comment created time in a day

Pull request review commentrust-lang/const-eval

RFC for const-UB

+- Feature Name: `const_ub`+- Start Date: 2020-10-10+- RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/0000)+- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000)++# Summary+[summary]: #summary++Define UB during const evaluation to lead to an unspecified result for the affected CTFE query, but not otherwise infect the compilation process.++# Motivation+[motivation]: #motivation++So far, nothing is specified about what happens when `unsafe` code leads to UB during CTFE.+This is a major blocker for stabilizing `unsafe` operations in const-contexts.++# Guide-level explanation+[guide-level-explanation]: #guide-level-explanation++There are some values that Rust needs to compute at compile-time.+This includes the initial value of a `const`/`static`, and array lengths (and more general, const generics).+Computing these initial values is called compile-time function evaluation (CTFE).+CTFE in Rust is very powerful and permits running almost arbitrary Rust code.+This begs the question, what happens when there is `unsafe` code and it causes Undefined Behavior (UB)?++The answer is that in this case, the final value that is currently being executed is arbitrary.+For example, when UB arises while computing an array length, then the final array length can be any `usize`, or it can be (partially) uninitialized memory.+No guarantees are made about this final value, and it can be different depending on host and target architecture, compiler flags, and more.+However, UB will not otherwise adversely affect the currently running compiler; type-checking and lints and everything else will work correctly given whatever the result of the CTFE computation is.++Note, however, that this means compile-time UB can later cause runtime UB when the program is actually executed:+for example, if there is UB while computing the initial value of a `Vec<i32>`, the result might be a completely invalid vector that causes UB at runtime when used in the program.++Sometimes, the compiler might be able to detect such problems and show an error or warning about CTFE computation having gone wrong (for example, the compiler might detect when the array length ends up being uninitialized).+But other times, this might not be the case -- UB is not reliably detected during CTFE.+This can change from compiler version to compiler version: CTFE code that causes UB could build fine with one compiler and fail to build with another.+(This is in accordance with the general policy that unsound code is not subject to strict stability guarantees.)++# Reference-level explanation+[reference-level-explanation]: #reference-level-explanation++When UB arises as part of CTFE, the result of this evaluation is an unspecified constant.+The compiler might be able to detect that UB occurred and raise an error or a warning, but this is not mandated, and absence of lints does not imply absence of UB.

Read for submission as a proper RFC I hope?

RalfJung

comment created time in a day

PullRequestReviewEvent

Pull request review commentrust-lang/const-eval

RFC for const-UB

+- Feature Name: `const_ub`+- Start Date: 2020-10-10+- RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/0000)+- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000)++# Summary+[summary]: #summary++Define UB during const evaluation to lead to an unspecified result for the affected CTFE query, but not otherwise infect the compilation process.++# Motivation+[motivation]: #motivation++So far, nothing is specified about what happens when `unsafe` code leads to UB during CTFE.+This is a major blocker for stabilizing `unsafe` operations in const-contexts.++# Guide-level explanation+[guide-level-explanation]: #guide-level-explanation++There are some values that Rust needs to compute at compile-time.+This includes the initial value of a `const`/`static`, and array lengths (and more general, const generics).+Computing these initial values is called compile-time function evaluation (CTFE).+CTFE in Rust is very powerful and permits running almost arbitrary Rust code.+This begs the question, what happens when there is `unsafe` code and it causes Undefined Behavior (UB)?++The answer is that in this case, the final value that is currently being executed is arbitrary.+For example, when UB arises while computing an array length, then the final array length can be any `usize`, or it can be (partially) uninitialized memory.+No guarantees are made about this final value, and it can be different depending on host and target architecture, compiler flags, and more.+However, UB will not otherwise adversely affect the currently running compiler; type-checking and lints and everything else will work correctly given whatever the result of the CTFE computation is.++Note, however, that this means compile-time UB can later cause runtime UB when the program is actually executed:+for example, if there is UB while computing the initial value of a `Vec<i32>`, the result might be a completely invalid vector that causes UB at runtime when used in the program.++Sometimes, the compiler might be able to detect such problems and show an error or warning about CTFE computation having gone wrong (for example, the compiler might detect when the array length ends up being uninitialized).+But other times, this might not be the case -- UB is not reliably detected during CTFE.+This can change from compiler version to compiler version: CTFE code that causes UB could build fine with one compiler and fail to build with another.+(This is in accordance with the general policy that unsound code is not subject to strict stability guarantees.)++# Reference-level explanation+[reference-level-explanation]: #reference-level-explanation++When UB arises as part of CTFE, the result of this evaluation is an unspecified constant.+The compiler might be able to detect that UB occurred and raise an error or a warning, but this is not mandated, and absence of lints does not imply absence of UB.

I am not sure about mandating that we detect "Uninit memory in final values"... this also needs very careful wording (uninit memory in a union or padding is okay!).

RalfJung

comment created time in a day

PullRequestReviewEvent

Pull request review commentrust-lang/const-eval

RFC for const-UB

+- Feature Name: `const_ub`+- Start Date: 2020-10-10+- RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/0000)+- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000)++# Summary+[summary]: #summary++Define UB during const evaluation to lead to an unspecified result for the affected CTFE query, but not otherwise infect the compilation process.++# Motivation+[motivation]: #motivation++So far, nothing is specified about what happens when `unsafe` code leads to UB during CTFE.+This is a major blocker for stabilizing `unsafe` operations in const-contexts.++# Guide-level explanation+[guide-level-explanation]: #guide-level-explanation++There are some values that Rust needs to compute at compile-time.+This includes the initial value of a `const`/`static`, and array lengths (and more general, const generics).+Computing these initial values is called compile-time function evaluation (CTFE).+CTFE in Rust is very powerful and permits running almost arbitrary Rust code.+This begs the question, what happens when there is `unsafe` code and it causes Undefined Behavior (UB)?++The answer is that in this case, the final value that is currently being executed is arbitrary.+For example, when UB arises while computing an array length, then the final array length can be any `usize`, or it can be (partially) uninitialized memory.+No guarantees are made about this final value, and it can be different depending on host and target architecture, compiler flags, and more.+However, UB will not otherwise adversely affect the currently running compiler; type-checking and lints and everything else will work correctly given whatever the result of the CTFE computation is.++Note, however, that this means compile-time UB can later cause runtime UB when the program is actually executed:+for example, if there is UB while computing the initial value of a `Vec<i32>`, the result might be a completely invalid vector that causes UB at runtime when used in the program.++Sometimes, the compiler might be able to detect such problems and show an error or warning about CTFE computation having gone wrong (for example, the compiler might detect when the array length ends up being uninitialized).+But other times, this might not be the case -- UB is not reliably detected during CTFE.+This can change from compiler version to compiler version: CTFE code that causes UB could build fine with one compiler and fail to build with another.+(This is in accordance with the general policy that unsound code is not subject to strict stability guarantees.)++# Reference-level explanation+[reference-level-explanation]: #reference-level-explanation++When UB arises as part of CTFE, the result of this evaluation is an unspecified constant.+The compiler might be able to detect that UB occurred and raise an error or a warning, but this is not mandated, and absence of lints does not imply absence of UB.

Ah right we could also mention "uninit memory occurring as an input to an arithmetic, logical or control-flow operation".

While I get that pointer comparisons aren't really UB, they just aren't possible, at least doing math or so with uninitialized memory/undefined values should be UB. Or is there a difference between intrinsics and basic ops?

I'd like not to touch on unconst operations in this RFC; that is a more tricky subject that I planned to leave for the future.

RalfJung

comment created time in a day

PullRequestReviewEvent

pull request commentrust-lang/rust

Crater expeximent: can we remove this weird special case from promotion?

Is this maybe a leftover of the fact that promotion checking and const checking used to be one huge spaghetti monster? Or is it "just because" our promotion rules in const contexts kind of follow explicit promotion rules?

I think it is a "because we can" that was added when promotion was ported to MIR (probably it was natural to add given that it was the same code as const checking, where such precision is probably useful and less of a problem).

RalfJung

comment created time in a day

push eventRalfJung/rust

Ralf Jung

commit sha dfd3ec06104aaaa23cecde2f24fedac2d5fb156b

cleanup code a bit Co-authored-by: Oli Scherer <github35764891676564198441@oli-obk.de>

view details

push time in a day

Pull request review commentrust-lang/rust

Crater expeximent: can we remove this weird special case from promotion?

 impl<'tcx> Validator<'_, 'tcx> {                         if place.projection.contains(&ProjectionElem::Deref) {                             return Err(Unpromotable);                         }--                        let mut has_mut_interior =-                            self.qualif_local::<qualifs::HasMutInterior>(place.local);-                        // HACK(eddyb) this should compute the same thing as-                        // `<HasMutInterior as Qualif>::in_projection` from-                        // `check_consts::qualifs` but without recursion.-                        if has_mut_interior {-                            // This allows borrowing fields which don't have-                            // `HasMutInterior`, from a type that does, e.g.:-                            // `let _: &'static _ = &(Cell::new(1), 2).1;`-                            let mut place_projection = &place.projection[..];-                            // FIXME(eddyb) use a forward loop instead of a reverse one.-                            while let &[ref proj_base @ .., elem] = place_projection {-                                // FIXME(eddyb) this is probably excessive, with-                                // the exception of `union` member accesses.-                                let ty =-                                    Place::ty_from(place.local, proj_base, self.body, self.tcx)-                                        .projection_ty(self.tcx, elem)-                                        .ty;-                                if ty.is_freeze(self.tcx.at(DUMMY_SP), self.param_env) {-                                    has_mut_interior = false;-                                    break;-                                }--                                place_projection = proj_base;-                            }+                        if self.qualif_local::<qualifs::NeedsDrop>(place.local) {+                            return Err(Unpromotable);                         }                          // FIXME(eddyb) this duplicates part of `validate_rvalue`.+                        let has_mut_interior =+                            self.qualif_local::<qualifs::HasMutInterior>(place.local);                         if has_mut_interior {                             return Err(Unpromotable);                         }-                        if self.qualif_local::<qualifs::NeedsDrop>(place.local) {

To make the block of code that is the same as validate_rvalue one contiguous block, starting at the "FIXME this is duplicated".

RalfJung

comment created time in a day

PullRequestReviewEvent

Pull request review commentrust-lang/rust

Crater expeximent: can we remove this weird special case from promotion?

 impl<'tcx> Validator<'_, 'tcx> {                  self.validate_place(place)?; -                // HACK(eddyb) this should compute the same thing as-                // `<HasMutInterior as Qualif>::in_projection` from-                // `check_consts::qualifs` but without recursion.-                let mut has_mut_interior =-                    self.qualif_local::<qualifs::HasMutInterior>(place.local);-                if has_mut_interior {-                    let mut place_projection = place.projection;-                    // FIXME(eddyb) use a forward loop instead of a reverse one.-                    while let &[ref proj_base @ .., elem] = place_projection {-                        // FIXME(eddyb) this is probably excessive, with-                        // the exception of `union` member accesses.-                        let ty = Place::ty_from(place.local, proj_base, self.body, self.tcx)-                            .projection_ty(self.tcx, elem)-                            .ty;-                        if ty.is_freeze(self.tcx.at(DUMMY_SP), self.param_env) {-                            has_mut_interior = false;-                            break;-                        }--                        place_projection = proj_base;-                    }-                }+                let has_mut_interior = self.qualif_local::<qualifs::HasMutInterior>(place.local);                 if has_mut_interior {

Yeah this is not meant to be clean code, just the easiest patch that works and passes CI and rustfmt.^^

RalfJung

comment created time in a day

PullRequestReviewEvent

pull request commentrust-lang/rust

Crater expeximent: can we remove this weird special case from promotion?

Ah, here is another case that is affected:

const FIVE: Cell<i32> = Cell::new(5);

#[inline(never)]
fn tuple_field() -> &'static u32 {
    // This test is MIR-borrowck-only because the old borrowck
    // doesn't agree that borrows of "frozen" (i.e., without any
    // interior mutability) fields of non-frozen temporaries,
    // should be promoted, while MIR promotion does promote them.
    &(FIVE, 42).1
}

(I wish we would have sticked to what the old borrowck allows.^^)

RalfJung

comment created time in a day

Pull request review commentrust-lang/const-eval

RFC for const-UB

+- Feature Name: `const_ub`+- Start Date: 2020-10-10+- RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/0000)+- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000)++# Summary+[summary]: #summary++Define UB during const evaluation to lead to an unspecified result for the affected CTFE query, but not otherwise infect the compilation process.++# Motivation+[motivation]: #motivation++So far, nothing is specified about what happens when `unsafe` code leads to UB during CTFE.+This is a major blocker for stabilizing `unsafe` operations in const-contexts.++# Guide-level explanation+[guide-level-explanation]: #guide-level-explanation++There are some values that Rust needs to compute at compile-time.+This includes the initial value of a `const`/`static`, and array lengths (and more general, const generics).+Computing these initial values is called compile-time function evaluation (CTFE).+CTFE in Rust is very powerful and permits running almost arbitrary Rust code.+This begs the question, what happens when there is `unsafe` code and it causes Undefined Behavior (UB)?++The answer is that in this case, the final value that is currently being executed is arbitrary.+For example, when UB arises while computing an array length, then the final array length can be any `usize`, or it can be (partially) uninitialized memory.+No guarantees are made about this final value, and it can be different depending on host and target architecture, compiler flags, and more.+However, UB will not otherwise adversely affect the currently running compiler; type-checking and lints and everything else will work correctly given whatever the result of the CTFE computation is.++Note, however, that this means compile-time UB can later cause runtime UB when the program is actually executed:+for example, if there is UB while computing the initial value of a `Vec<i32>`, the result might be a completely invalid vector that causes UB at runtime when used in the program.++Sometimes, the compiler might be able to detect such problems and show an error or warning about CTFE computation having gone wrong (for example, the compiler might detect when the array length ends up being uninitialized).+But other times, this might not be the case -- UB is not reliably detected during CTFE.+This can change from compiler version to compiler version: CTFE code that causes UB could build fine with one compiler and fail to build with another.+(This is in accordance with the general policy that unsound code is not subject to strict stability guarantees.)++# Reference-level explanation+[reference-level-explanation]: #reference-level-explanation++When UB arises as part of CTFE, the result of this evaluation is an unspecified constant.+The compiler might be able to detect that UB occurred and raise an error or a warning, but this is not mandated, and absence of lints does not imply absence of UB.

I think in this section we should explain the various mechanisms for detecting UB and their respective "detection rate" of UB.

I have to say this list seems to be awfully geared around what happens to be the current implementation... in particular if we consider RFCs as applying to all Rust compilers, this seems unnecessarily specific.

I'd say something much shorter, mire like:

  • UB caused by inrinsics is detected.
  • Dereferencing dangling pointers is detected. (But misalignment is not!)
  • All the other UB listed here is not detected.
RalfJung

comment created time in a day

PullRequestReviewEvent

push eventRalfJung/rust

Ralf Jung

commit sha 6abc85758b62298b4a3f745292e46f9933ac0127

WIP: remove a hack that seems to only benefit a few very special cases

view details

push time in a day

Pull request review commentrust-lang/rust

Crater expeximent: can we remove this weird special case from promotion?

 const TEST_UNION: () = {     let _x: &'static i32 = &unsafe { U { x: 0 }.x }; //~ ERROR temporary value dropped while borrowed }; -fn main() {}+// In a `const`, we do not promote things with interior mutability. Not even if we "project it away".+const TEST_INTERIOR_MUT: () = {+    // The "0." case is already ruled out by not permitting any interior mutability in `const`.+    let _val: &'static _ = &(Cell::new(1), 2).1; //~ ERROR temporary value dropped while borrowed+};++fn main() {+    // We must not promote things with interior mutability. Not even if we "project it away".+    let _val: &'static _ = &(Cell::new(1), 2).0; //~ ERROR temporary value dropped while borrowed+    let _val: &'static _ = &(Cell::new(1), 2).1; //~ ERROR temporary value dropped while borrowed

These two already failed before.

RalfJung

comment created time in a day

PullRequestReviewEvent

PR opened rust-lang/rust

Crater expeximent: can we remove this weird special case from promotion?

Promotion has a special case to ignore interior mutability under some specific circumstances. The purpose of this PR is to figure out what changes if we remove that. Since Cell::new and friends only get promoted inside const/static initializers these days, it actually is not easy to exploit this case: you need something like

const TEST_INTERIOR_MUT: () = {
    // The "0." case is already ruled out by not permitting any interior mutability in `const`.
    let _val: &'static _ = &(Cell::new(1), 2).1;
};

I assume something like &Some(&(Cell::new(1), 2).1) would hit the nested case inside validate_rvalue... though I am not sure why that would not just trigger nested promotion, first promoting the inner reference and then the outer one?

r? @oli-obk (but for now this is not meant to be merged!) Cc @rust-lang/wg-const-eval

+56 -58

0 comment

3 changed files

pr created time in a day

push eventRalfJung/rust

Ralf Jung

commit sha 8969650a3b738f7b560971084e55264e3e11c59b

make sure we do not promote things with interior mutability

view details

Ralf Jung

commit sha 79e6f609e4e6925c8548096eb578027cbf0f15b5

WIP: remove a hack that seems to only benefit a few very special cases

view details

push time in a day

issue commentrust-lang/rust

Promotion creates invalid constants that are never used in invalid ways

let x: &'static i32 = &[(Cell::new(42), 1), Cell::new(42), 2)][runtime_index].1;

FWIW, this code is currently not even accepted inside a function, I think? It only works inside another const/static, because there we still permit promotion of arbitrary const fn.

oli-obk

comment created time in a day

push eventRalfJung/rust

Ralf Jung

commit sha 686deea3822ec8a94e697087104e96e2545aff5a

remove more interior mut special cases

view details

push time in a day

create barnchRalfJung/rust

branch : promotion

created branch time in a day

Pull request review commentrust-lang/rust

ensure that statics are inhabited

+#![feature(never_type)]+#![deny(uninhabited_static)]++enum Void {}+extern {+    static VOID: Void; //~ ERROR static of uninhabited type+    //~| WARN: previously accepted+    static NEVER: !; //~ ERROR static of uninhabited type

Yes, looks like it does (see the test change I just pushed)... would you prefer it to only apply to foreign items?

RalfJung

comment created time in a day

PullRequestReviewEvent

push eventRalfJung/rust

Ralf Jung

commit sha 3bd5cc900c55722c38cf5aa51793cc133c8d741a

also test non-extern uninhabited statics

view details

push time in a day

pull request commentrust-lang/rust

Move "mutable thing in const" check from interning to validity

I think we totally can make them silently immutable. "Everything in a constant is immutable period" seems like a rule we could impose on such code.

But anyway, that's a discussion for the future. ;)

RalfJung

comment created time in a day

issue commentrust-lang/rust

Promoted values are not validated

We no longer promote union field accesses... but we still promote arbitrary const fn calls in const/static initializers so the issue can be reproduced that way.

Also I feel like my argument above only really works for implicit promoteds; explicit promoteds likely should be validated -- but I am not sure if there is an easy way we can make that distinction? It might just not be worth it.

oli-obk

comment created time in a day

pull request commentrust-lang/rust

Move "mutable thing in const" check from interning to validity

But this made me realize that if we used the "leftover interner" for consts and promoteds, the type-based traversal would be used only for statics, which would be a possible future simplification (if we are willing to give up that "untyped pointers are not allowed in constant" error)... just a possibility to keep in mind. ;)

RalfJung

comment created time in a day

pull request commentrust-lang/rust

Move "mutable thing in const" check from interning to validity

I was complicit in creating the mess, having been the reviewer and prompting you to add more and more sanity checks. ;)

I added a comment at the top of the file explaining why interning is a bit more complicated than it might seem -- I think now wanting to make statics immutable where possible is truly all the complication that is left in this file, which is a nice separation of concerns. (Except for the "untyped pointers are not allowed in constant" error, which sticks out a bit.) Could you chck if this comment makes sense as well?

@bors r-

RalfJung

comment created time in a day

push eventRalfJung/rust

Ralf Jung

commit sha db01d97ea7f73fef92a2199e66fa5dd46c5ca472

explain why interning is not as trivial as it might seem

view details

push time in a day

push eventRalfJung/ansible

Ralf Jung

commit sha 0fbca447d7dca874c24a6151caa662d7a661c419

install and configure coturn

view details

Ralf Jung

commit sha 4e2fef517c6d8ed6c88142e7486fe42a945adda2

confgure external services for prosody

view details

Ralf Jung

commit sha b0c6a3da0e5e5b144befbcc0c5faa93dd5101c03

restrict coturn port range

view details

push time in a day

pull request commentrust-lang/rust

Qualify `panic!` with `$crate::` in `core` macros

I'm all for just breaking assert!(.., 123) (and panic!(123)). But most discussions about this came to the conclusion that this should probably be gated on the next edition.

For panic! I agree the change is too invasive, but for assert! I am less sure.

I'll turn my notes about this into an RFC today (and also add something about assert!()), so we can make a final decision about how to go forward with panic!() (and assert!() (and debug_assert!())).

Okay, great. :) (But some of this will likely require further data, in particular for assert! I think it would be really good to know how wide-spread such non-string uses are.)

camelid

comment created time in a day

pull request commentrust-lang/rust

Qualify `panic!` with `$crate::` in `core` macros

assert!(1 + 1 == 3, 123); // ok with std, error with core

I doubt this was ever intended to work, and even for people using panic! with a custom payload, this seems like a stretch. It would be worth a crater run to see how often this actually occurs in practice.

camelid

comment created time in a day

push eventRalfJung/rust

Ralf Jung

commit sha 7c7b90d61614716ab73e6f437924afad12249809

interning cleanup: we no longer need to distinguish Const and ConstInner; we no longer need the ignore_interior_mut_in_const hack

view details

push time in 2 days

PR opened rust-lang/rust

Move "mutable thing in const" check from interning to validity

This moves the check for mutable things (such as UnsafeCell or &mut) in aconst from interning to validity. That means we can give more targeted error messages (pointing out where the problem lies), and we can simplify interning a bit.

Also fix the interning mode used for promoteds in statics.

r? @oli-obk

+144 -164

0 comment

10 changed files

pr created time in 2 days

push eventRalfJung/rust

Ralf Jung

commit sha a74e5acc36740d4138f4a4cde7824fd4eb70c4db

interning cleanup: we no longer need to distinguish Const and ConstInner; we no longer need the ignore_interior_mut_in_const hack

view details

push time in 2 days

issue openedrust-lang/rustfmt

Suboptimal formatting of `let`-bound chains of `||` with `==` inside them.

Input

                    let assign_to_field =
                        context == PlaceContext::MutatingUse(MutatingUseContext::Store)
                        || context == PlaceContext::MutatingUse(MutatingUseContext::Drop)
                        || context == PlaceContext::MutatingUse(MutatingUseContext::AsmOutput);

Output

                    let assign_to_field = context
                        == PlaceContext::MutatingUse(MutatingUseContext::Store)
                        || context == PlaceContext::MutatingUse(MutatingUseContext::Drop)
                        || context == PlaceContext::MutatingUse(MutatingUseContext::AsmOutput);

Expected output

                    let assign_to_field =
                        context == PlaceContext::MutatingUse(MutatingUseContext::Store)
                        || context == PlaceContext::MutatingUse(MutatingUseContext::Drop)
                        || context == PlaceContext::MutatingUse(MutatingUseContext::AsmOutput);

The reformatting actually makes the code look worse (linebreak in the middle of one of the comparisons) without a need (such as a line being too long).

Meta

  • This is via ./x.py fmt in current rustc

created time in 2 days

create barnchRalfJung/rust

branch : validity-unsafe-cell

created branch time in 2 days

delete branch RalfJung/miri

delete branch : rustup

delete time in 2 days

pull request commentrust-lang/rust

Qualify `panic!` with `$crate::` in `core` macros

Seems fine to me, and actually with @m-ou-se's recent changes the two macros are now more similar than before.

camelid

comment created time in 2 days

Pull request review commentemilk/drop-merge-sort

Get rid of mem::uninitialized()

 impl<'a, T> Drop for DmSorter<'a, T> { #[inline(always)] unsafe fn unsafe_push<T>(vec: &mut Vec<T>, value: &T) { 	let old_len = vec.len();-	vec.push(mem::uninitialized::<T>());+	vec.reserve(1); 	ptr::copy_nonoverlapping(value, vec.get_unchecked_mut(old_len), 1);+	vec.set_len(old_len + 1);

Yes that is much better than mucking about with uninitialized memory. :)

ilaril

comment created time in 2 days

PullRequestReviewEvent

pull request commentrust-lang/miri

rustup; make panic output less dependent on stdlib internals

@bors r+

RalfJung

comment created time in 2 days

create barnchRalfJung/miri

branch : rustup

created branch time in 2 days

PR opened rust-lang/miri

rustup; make panic output less dependent on stdlib internals
+27 -27

0 comment

6 changed files

pr created time in 2 days

issue commentrust-lang/unsafe-code-guidelines

What about: invalid not-used-again values? Is "validity on typed copy" enough?

and we might also validate that there exist bytes completing [0, -, -, 42] such that the result is a valid u32, although that sounds like a bit of headache to define.

That is indeed the case I am most worried about... in particular if you think of cases like [0, -, -, -] and whether this is a valid NonZeroU32.

RalfJung

comment created time in 2 days

issue commentrust-lang/miri

Improve handling of failed operations in isolation mode

@camelid that's great. :-)

Aaron1011

comment created time in 2 days

pull request commentrust-lang/miri

Make `miri_default_args()` a constant

Sure, why not. :) No idea why this is a function... thanks! @bors r+

camelid

comment created time in 2 days

Pull request review commentrust-lang/rust

consider assignments of union field of ManuallyDrop type safe

 impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {                     UnsafetyViolationKind::GeneralAndConstFn,                     UnsafetyViolationDetails::DerefOfRawPointer,                 ),-                ty::Adt(adt, _) => {-                    if adt.is_union() {-                        if context == PlaceContext::MutatingUse(MutatingUseContext::Store)-                            || context == PlaceContext::MutatingUse(MutatingUseContext::Drop)-                            || context == PlaceContext::MutatingUse(MutatingUseContext::AsmOutput)-                        {-                            let elem_ty = match elem {-                                ProjectionElem::Field(_, ty) => ty,-                                _ => span_bug!(-                                    self.source_info.span,-                                    "non-field projection {:?} from union?",-                                    place-                                ),-                            };-                            if !elem_ty.is_copy_modulo_regions(+                ty::Adt(adt, _) if adt.is_union() => {+                    let assign_to_field = context+                        == PlaceContext::MutatingUse(MutatingUseContext::Store)

This strikes me as rather suboptimal formatting, bur rustfmt insists on it...

RalfJung

comment created time in 2 days

more