japaric/xargo 790
The sysroot manager that lets you build and customize `std`
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:
Safe pointer-to-member functionality for rust
ansible playbooks for my servers
Client and broker for our custom L2TPv3 NAT-traversing tunnel setup protocol based on L2TPv3 support in the Linux kernel.
ESP32 firmware for the SHA2017 badge
MicroPython ported to the SHA2017 badge
pull request commentrust-lang/const-eval
Now I am confused, I was going to update the RFC to incorporate what we discussed.^^
comment created time in 3 hours
Pull request review commentrust-lang/const-eval
+- 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.
comment created time in 4 hours
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.
comment created time in 4 hours
push eventRalfJung/rust
commit sha 8ab831973fb81eed53fb98ddd0efcc4227e954ac
improve formatting
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.
comment created 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)
I reported this against rustfmt: https://github.com/rust-lang/rustfmt/issues/4492
comment created time in 4 hours
Pull request review commentrust-lang/const-eval
+- 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.
comment created time in 4 hours
push eventmit-pdos/perennial
commit sha 83218f55ebbd4a73a06b0d419dbadb36d630ac43
strengthen common_proof lemmas to be Iris-level entailments
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.
comment created time in 5 hours
push eventmit-pdos/perennial
commit sha b2e3c8b9b674b451aff430e4d5c88a6a7e682afc
avoid some \later
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
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.
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
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
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.
comment created time in 9 hours
PR opened rust-lang/rust
Fixes https://github.com/rust-lang/rust/issues/78339 Cc @rust-lang/miri r? @ghost
pr created 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.
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.
comment created time in 11 hours
pull request commentcoq/coq
adjust Search deprecation warning
Squashed.
comment created time in 12 hours
push eventRalfJung/coq
commit sha a2ce4da4c2b0dc81d4c61f3e672d6c9d65dba46b
adjust Search deprecation warning
push time in 12 hours
push eventRalfJung/ansible
commit sha c1f305f1d26a92eaa7130394d3e04f27b4149107
journalwatch: ignore some openvpn messages
push time in 12 hours
pull request commentrust-lang/rust
Move "mutable thing in const" check from interning to validity
@bors r=oli-obk
comment created time in 14 hours
Pull request review commentrust-lang/rust
+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).
comment created time in 14 hours
push eventRalfJung/rust
commit sha dc89bb1135afc31fc9ee2272e627192c04354d22
Use if_chain in Increment/InitializeVisitor
commit sha 116f30dc33d9e3744f257f2f7f5467acfbff178b
Use else blocks instead of return statements in Increment/InitializeVisitor
commit sha b2d5b89a1de15df9052fdf44d01b174add82837f
Check if it's after the loop earlier
commit sha 31cb1109648bf4242cab47571343578244e7fb9d
add concinient methods to Increment/InitializeVisitor
commit sha c599e2fcfaaedb12b560f4136bab3d0b450acf8f
Split VarState
commit sha 13c207d3756754c54a6b20d852087616d5abfbf4
Generalise `InitializeVisitor`
commit sha 9573a0d378033a81e55ca834a5d305d3cf2be24d
Rename variables
commit sha 1026b42f0694eb9239b5cebe80be743d5ded0da5
Rename a struct and variables
commit sha b4b4da162f19e9a4c63854a2b5a6167b83f9d8b9
Introduce Start and StartKind
commit sha 720f19f2ec4282f636889b35beabf31272e3b1b2
Implement detecting `manual_memcpy` with loop counters
commit sha de56279cd9047832216e1d1c06dc45375bf01b31
Implement building the `manual_memcpy` sugggestion with loop counters
commit sha 8da6cfd17b7707d678d01a6688572169015ea83e
fmt
commit sha d9a88be0b05c2cfec0679caf428d129c9d46256d
Rename `get_offset` and its private items
commit sha 774e82a566c6c3349700a8bece44d6a8c6755039
Add the tests for `manual_memcpy` with loop counters
commit sha 9aad38bf614c3fb6d306f5dec4a0af606bb3c9c8
Update `manual_memcpy.stderr` to reflect additional parentheses
commit sha 4ea4a972500a8ddecfc737d51eec960324dcb02f
Add tests for bitwise operations
commit sha eb3ffe6ed2999e9d3385be0ff981e30082ea0d2c
make use of macros in operator overloading
commit sha 10d7a18f72155f03dbd27b872a52b5dd45def8db
fmt
commit sha 174065fc98ef9335ea45a234aa18286cdf6c3934
fix the multiple counters test
commit sha 44187383f4724bd7e4b2b220235e93438043947a
Use operator overloading instead of direct calls of `make_binop`
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. :-)
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?
comment created time in 15 hours
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.
comment created time in 15 hours
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.
comment created time in 15 hours
pull request commentrust-lang/rust
Crater expeximent: can we remove this weird special case from promotion?
@craterbot check
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
comment created time in a day
pull request commentrust-lang/rust
Crater expeximent: can we remove this weird special case from promotion?
@bors retry
comment created time in a day
Pull request review commentrust-lang/const-eval
+- 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?
comment created time in a day
Pull request review commentrust-lang/const-eval
+- 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!).
comment created time in a day
Pull request review commentrust-lang/const-eval
+- 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.
comment created time in a day
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).
comment created time in a day
push eventRalfJung/rust
commit sha dfd3ec06104aaaa23cecde2f24fedac2d5fb156b
cleanup code a bit Co-authored-by: Oli Scherer <[email protected]>
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".
comment created 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> { 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.^^
comment created time in a day
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.^^)
comment created time in a day
Pull request review commentrust-lang/const-eval
+- 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.
comment created time in a day
push eventRalfJung/rust
commit sha 6abc85758b62298b4a3f745292e46f9933ac0127
WIP: remove a hack that seems to only benefit a few very special cases
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.
comment created time in a day
PR opened rust-lang/rust
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
pr created time in a day
push eventRalfJung/rust
commit sha 8969650a3b738f7b560971084e55264e3e11c59b
make sure we do not promote things with interior mutability
commit sha 79e6f609e4e6925c8548096eb578027cbf0f15b5
WIP: remove a hack that seems to only benefit a few very special cases
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.
comment created time in a day
push eventRalfJung/rust
commit sha 686deea3822ec8a94e697087104e96e2545aff5a
remove more interior mut special cases
push 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?
comment created time in a day
push eventRalfJung/rust
commit sha 3bd5cc900c55722c38cf5aa51793cc133c8d741a
also test non-extern uninhabited statics
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. ;)
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.
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. ;)
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-
comment created time in a day
push eventRalfJung/rust
commit sha db01d97ea7f73fef92a2199e66fa5dd46c5ca472
explain why interning is not as trivial as it might seem
push time in a day
push eventRalfJung/ansible
commit sha 0fbca447d7dca874c24a6151caa662d7a661c419
install and configure coturn
commit sha 4e2fef517c6d8ed6c88142e7486fe42a945adda2
confgure external services for prosody
commit sha b0c6a3da0e5e5b144befbcc0c5faa93dd5101c03
restrict coturn port range
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.)
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.
comment created time in a day
push eventRalfJung/rust
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
push time in 2 days
PR opened rust-lang/rust
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
pr created time in 2 days
push eventRalfJung/rust
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
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 fmtin current rustc
created 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.
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. :)
comment created time in 2 days
pull request commentrust-lang/miri
rustup; make panic output less dependent on stdlib internals
@bors r+
comment created time in 2 days
PR opened rust-lang/miri
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.
comment created time in 2 days
issue commentrust-lang/miri
Improve handling of failed operations in isolation mode
@camelid that's great. :-)
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+
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...
comment created time in 2 days