Skip to content

Commit 9a8400c

Browse files
committed
implement Ord for OutlivesPredicate and other types
1 parent 1977849 commit 9a8400c

File tree

11 files changed

+100
-34
lines changed

11 files changed

+100
-34
lines changed

src/librustc/hir/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -930,7 +930,7 @@ pub enum PatKind {
930930
Slice(HirVec<P<Pat>>, Option<P<Pat>>, HirVec<P<Pat>>),
931931
}
932932

933-
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
933+
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
934934
pub enum Mutability {
935935
MutMutable,
936936
MutImmutable,
@@ -1523,7 +1523,7 @@ pub struct Destination {
15231523
pub target_id: Result<NodeId, LoopIdError>,
15241524
}
15251525

1526-
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
1526+
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
15271527
pub enum GeneratorMovability {
15281528
Static,
15291529
Movable,
@@ -1775,7 +1775,7 @@ pub enum IsAuto {
17751775
No
17761776
}
17771777

1778-
#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
1778+
#[derive(Copy, Clone, PartialEq, Eq,PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash, Debug)]
17791779
pub enum Unsafety {
17801780
Unsafe,
17811781
Normal,

src/librustc/middle/const_val.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use rustc_data_structures::sync::Lrc;
2222

2323
pub type EvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ConstEvalErr<'tcx>>;
2424

25-
#[derive(Copy, Clone, Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq)]
25+
#[derive(Copy, Clone, Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq, Ord, PartialOrd)]
2626
pub enum ConstVal<'tcx> {
2727
Unevaluated(DefId, &'tcx Substs<'tcx>),
2828
Value(ConstValue<'tcx>),

src/librustc/mir/interpret/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ pub trait PointerArithmetic: layout::HasDataLayout {
109109
impl<T: layout::HasDataLayout> PointerArithmetic for T {}
110110

111111

112-
#[derive(Copy, Clone, Debug, Eq, PartialEq, RustcEncodable, RustcDecodable, Hash)]
112+
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)]
113113
pub struct MemoryPointer {
114114
pub alloc_id: AllocId,
115115
pub offset: Size,
@@ -335,7 +335,7 @@ impl<'tcx, M: fmt::Debug + Eq + Hash + Clone> AllocMap<'tcx, M> {
335335
}
336336
}
337337

338-
#[derive(Clone, Debug, Eq, PartialEq, Hash, RustcEncodable, RustcDecodable)]
338+
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
339339
pub struct Allocation {
340340
/// The actual bytes of the allocation.
341341
/// Note that the bytes of a pointer represent the offset of the pointer
@@ -384,7 +384,7 @@ impl Allocation {
384384

385385
impl<'tcx> ::serialize::UseSpecializedDecodable for &'tcx Allocation {}
386386

387-
#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
387+
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
388388
pub struct Relocations(SortedMap<Size, AllocId>);
389389

390390
impl Relocations {
@@ -455,7 +455,7 @@ pub fn read_target_uint(endianness: layout::Endian, mut source: &[u8]) -> Result
455455
type Block = u64;
456456
const BLOCK_SIZE: u64 = 64;
457457

458-
#[derive(Clone, Debug, Eq, PartialEq, Hash, RustcEncodable, RustcDecodable)]
458+
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
459459
pub struct UndefMask {
460460
blocks: Vec<Block>,
461461
len: Size,

src/librustc/mir/interpret/value.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use super::{EvalResult, MemoryPointer, PointerArithmetic, Allocation};
77

88
/// Represents a constant value in Rust. ByVal and ByValPair are optimizations which
99
/// matches Value's optimizations for easy conversions between these two types
10-
#[derive(Clone, Copy, Debug, Eq, PartialEq, RustcEncodable, RustcDecodable, Hash)]
10+
#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash)]
1111
pub enum ConstValue<'tcx> {
1212
/// Used only for types with layout::abi::Scalar ABI and ZSTs which use PrimVal::Undef
1313
ByVal(PrimVal),
@@ -76,7 +76,7 @@ impl<'tcx> ConstValue<'tcx> {
7676
/// For optimization of a few very common cases, there is also a representation for a pair of
7777
/// primitive values (`ByValPair`). It allows Miri to avoid making allocations for checked binary
7878
/// operations and fat pointers. This idea was taken from rustc's codegen.
79-
#[derive(Clone, Copy, Debug, Eq, PartialEq, RustcEncodable, RustcDecodable, Hash)]
79+
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)]
8080
pub enum Value {
8181
ByRef(Pointer, Align),
8282
ByVal(PrimVal),
@@ -99,7 +99,7 @@ impl<'tcx> ty::TypeFoldable<'tcx> for Value {
9999
/// I (@oli-obk) believe it is less easy to mix up generic primvals and primvals that are just
100100
/// the representation of pointers. Also all the sites that convert between primvals and pointers
101101
/// are explicit now (and rare!)
102-
#[derive(Clone, Copy, Debug, Eq, PartialEq, RustcEncodable, RustcDecodable, Hash)]
102+
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)]
103103
pub struct Pointer {
104104
pub primval: PrimVal,
105105
}
@@ -194,7 +194,7 @@ impl ::std::convert::From<MemoryPointer> for Pointer {
194194
/// `memory::Allocation`. It is in many ways like a small chunk of a `Allocation`, up to 8 bytes in
195195
/// size. Like a range of bytes in an `Allocation`, a `PrimVal` can either represent the raw bytes
196196
/// of a simple value, a pointer into another `Allocation`, or be undefined.
197-
#[derive(Clone, Copy, Debug, Eq, PartialEq, RustcEncodable, RustcDecodable, Hash)]
197+
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)]
198198
pub enum PrimVal {
199199
/// The raw bytes of a simple value.
200200
Bytes(u128),

src/librustc/ty/mod.rs

+44-2
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ use util::nodemap::{NodeSet, DefIdMap, FxHashMap};
3939

4040
use serialize::{self, Encodable, Encoder};
4141
use std::cell::RefCell;
42-
use std::cmp;
42+
use std::cmp::{self, Ordering};
4343
use std::fmt;
4444
use std::hash::{Hash, Hasher};
4545
use std::ops::Deref;
@@ -491,6 +491,18 @@ pub struct TyS<'tcx> {
491491
region_depth: u32,
492492
}
493493

494+
impl<'tcx> Ord for TyS<'tcx> {
495+
fn cmp(&self, other: &TyS<'tcx>) -> Ordering {
496+
self.sty.cmp(&other.sty)
497+
}
498+
}
499+
500+
impl<'tcx> PartialOrd for TyS<'tcx> {
501+
fn partial_cmp(&self, other: &TyS<'tcx>) -> Option<Ordering> {
502+
Some(self.sty.cmp(&other.sty))
503+
}
504+
}
505+
494506
impl<'tcx> PartialEq for TyS<'tcx> {
495507
#[inline]
496508
fn eq(&self, other: &TyS<'tcx>) -> bool {
@@ -578,6 +590,22 @@ impl <'gcx: 'tcx, 'tcx> Canonicalize<'gcx, 'tcx> for Ty<'tcx> {
578590
#[derive(Debug, RustcEncodable)]
579591
pub struct Slice<T>([T]);
580592

593+
impl<T> Ord for Slice<T> where T: Ord {
594+
fn cmp(&self, other: &Slice<T>) -> Ordering {
595+
if self == other { Ordering::Equal } else {
596+
<[T] as Ord>::cmp(&self.0, &other.0)
597+
}
598+
}
599+
}
600+
601+
impl<T> PartialOrd for Slice<T> where T: PartialOrd {
602+
fn partial_cmp(&self, other: &Slice<T>) -> Option<Ordering> {
603+
if self == other { Some(Ordering::Equal) } else {
604+
<[T] as PartialOrd>::partial_cmp(&self.0, &other.0)
605+
}
606+
}
607+
}
608+
581609
impl<T> PartialEq for Slice<T> {
582610
#[inline]
583611
fn eq(&self, other: &Slice<T>) -> bool {
@@ -1104,7 +1132,7 @@ impl<'tcx> PolyTraitPredicate<'tcx> {
11041132
}
11051133
}
11061134

1107-
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
1135+
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
11081136
pub struct OutlivesPredicate<A,B>(pub A, pub B); // `A : B`
11091137
pub type PolyOutlivesPredicate<A,B> = ty::Binder<OutlivesPredicate<A,B>>;
11101138
pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate<ty::Region<'tcx>,
@@ -1606,6 +1634,20 @@ pub struct AdtDef {
16061634
pub repr: ReprOptions,
16071635
}
16081636

1637+
impl PartialOrd for AdtDef {
1638+
fn partial_cmp(&self, other: &AdtDef) -> Option<Ordering> {
1639+
Some(self.cmp(&other))
1640+
}
1641+
}
1642+
1643+
/// There should be only one AdtDef for each `did`, therefore
1644+
/// it is fine to implement `Ord` only based on `did`.
1645+
impl Ord for AdtDef {
1646+
fn cmp(&self, other: &AdtDef) -> Ordering {
1647+
self.did.cmp(&other.did)
1648+
}
1649+
}
1650+
16091651
impl PartialEq for AdtDef {
16101652
// AdtDef are always interned and this is part of TyS equality
16111653
#[inline]

src/librustc/ty/sty.rs

+16-16
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use hir;
3434
use self::InferTy::*;
3535
use self::TypeVariants::*;
3636

37-
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
37+
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
3838
pub struct TypeAndMut<'tcx> {
3939
pub ty: Ty<'tcx>,
4040
pub mutbl: hir::Mutability,
@@ -80,7 +80,7 @@ impl BoundRegion {
8080

8181
/// NB: If you change this, you'll probably want to change the corresponding
8282
/// AST structure in libsyntax/ast.rs as well.
83-
#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
83+
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
8484
pub enum TypeVariants<'tcx> {
8585
/// The primitive boolean type. Written as `bool`.
8686
TyBool,
@@ -268,7 +268,7 @@ pub enum TypeVariants<'tcx> {
268268
///
269269
/// It'd be nice to split this struct into ClosureSubsts and
270270
/// GeneratorSubsts, I believe. -nmatsakis
271-
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
271+
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
272272
pub struct ClosureSubsts<'tcx> {
273273
/// Lifetime and type parameters from the enclosing function,
274274
/// concatenated with the types of the upvars.
@@ -351,7 +351,7 @@ impl<'tcx> ClosureSubsts<'tcx> {
351351
}
352352
}
353353

354-
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
354+
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
355355
pub struct GeneratorSubsts<'tcx> {
356356
pub substs: &'tcx Substs<'tcx>,
357357
}
@@ -484,7 +484,7 @@ impl<'tcx> UpvarSubsts<'tcx> {
484484
}
485485
}
486486

487-
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
487+
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash, RustcEncodable, RustcDecodable)]
488488
pub enum ExistentialPredicate<'tcx> {
489489
/// e.g. Iterator
490490
Trait(ExistentialTraitRef<'tcx>),
@@ -660,7 +660,7 @@ impl<'tcx> PolyTraitRef<'tcx> {
660660
///
661661
/// The substitutions don't include the erased `Self`, only trait
662662
/// type and lifetime parameters (`[X, Y]` and `['a, 'b]` above).
663-
#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
663+
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
664664
pub struct ExistentialTraitRef<'tcx> {
665665
pub def_id: DefId,
666666
pub substs: &'tcx Substs<'tcx>,
@@ -728,7 +728,7 @@ impl<'tcx> PolyExistentialTraitRef<'tcx> {
728728
/// erase, or otherwise "discharge" these bound regions, we change the
729729
/// type from `Binder<T>` to just `T` (see
730730
/// e.g. `liberate_late_bound_regions`).
731-
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
731+
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
732732
pub struct Binder<T>(T);
733733

734734
impl<T> Binder<T> {
@@ -834,7 +834,7 @@ impl<T> Binder<T> {
834834

835835
/// Represents the projection of an associated type. In explicit UFCS
836836
/// form this would be written `<T as Trait<..>>::N`.
837-
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
837+
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
838838
pub struct ProjectionTy<'tcx> {
839839
/// The parameters of the associated item.
840840
pub substs: &'tcx Substs<'tcx>,
@@ -902,7 +902,7 @@ impl<'tcx> PolyGenSig<'tcx> {
902902
/// - `inputs` is the list of arguments and their modes.
903903
/// - `output` is the return type.
904904
/// - `variadic` indicates whether this is a variadic function. (only true for foreign fns)
905-
#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
905+
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
906906
pub struct FnSig<'tcx> {
907907
pub inputs_and_output: &'tcx Slice<Ty<'tcx>>,
908908
pub variadic: bool,
@@ -946,7 +946,7 @@ impl<'tcx> PolyFnSig<'tcx> {
946946
}
947947
}
948948

949-
#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
949+
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
950950
pub struct ParamTy {
951951
pub idx: u32,
952952
pub name: InternedString,
@@ -1148,17 +1148,17 @@ pub struct EarlyBoundRegion {
11481148
pub name: InternedString,
11491149
}
11501150

1151-
#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
1151+
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
11521152
pub struct TyVid {
11531153
pub index: u32,
11541154
}
11551155

1156-
#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
1156+
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
11571157
pub struct IntVid {
11581158
pub index: u32,
11591159
}
11601160

1161-
#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
1161+
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
11621162
pub struct FloatVid {
11631163
pub index: u32,
11641164
}
@@ -1169,7 +1169,7 @@ newtype_index!(RegionVid
11691169
DEBUG_FORMAT = custom,
11701170
});
11711171

1172-
#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
1172+
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
11731173
pub enum InferTy {
11741174
TyVar(TyVid),
11751175
IntVar(IntVid),
@@ -1189,7 +1189,7 @@ pub enum InferTy {
11891189
newtype_index!(CanonicalVar);
11901190

11911191
/// A `ProjectionPredicate` for an `ExistentialTraitRef`.
1192-
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
1192+
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
11931193
pub struct ExistentialProjection<'tcx> {
11941194
pub item_def_id: DefId,
11951195
pub substs: &'tcx Substs<'tcx>,
@@ -1758,7 +1758,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
17581758
}
17591759

17601760
/// Typed constant value.
1761-
#[derive(Copy, Clone, Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq)]
1761+
#[derive(Copy, Clone, Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq, Ord, PartialOrd)]
17621762
pub struct Const<'tcx> {
17631763
pub ty: Ty<'tcx>,
17641764

src/librustc/ty/subst.rs

+23
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use rustc_data_structures::accumulate_vec::AccumulateVec;
2020
use rustc_data_structures::array_vec::ArrayVec;
2121

2222
use core::intrinsics;
23+
use std::cmp::Ordering;
2324
use std::fmt;
2425
use std::marker::PhantomData;
2526
use std::mem;
@@ -70,6 +71,28 @@ impl<'tcx> UnpackedKind<'tcx> {
7071
}
7172
}
7273

74+
impl<'tcx> Ord for Kind<'tcx> {
75+
fn cmp(&self, other: &Kind) -> Ordering {
76+
match (self.unpack(), other.unpack()) {
77+
(UnpackedKind::Type(_), UnpackedKind::Lifetime(_)) => Ordering::Greater,
78+
79+
(UnpackedKind::Type(ty1), UnpackedKind::Type(ty2)) => {
80+
ty1.sty.cmp(&ty2.sty)
81+
}
82+
83+
(UnpackedKind::Lifetime(reg1), UnpackedKind::Lifetime(reg2)) => reg1.cmp(reg2),
84+
85+
(UnpackedKind::Lifetime(_), UnpackedKind::Type(_)) => Ordering::Less,
86+
}
87+
}
88+
}
89+
90+
impl<'tcx> PartialOrd for Kind<'tcx> {
91+
fn partial_cmp(&self, other: &Kind) -> Option<Ordering> {
92+
Some(self.cmp(&other))
93+
}
94+
}
95+
7396
impl<'tcx> From<ty::Region<'tcx>> for Kind<'tcx> {
7497
fn from(r: ty::Region<'tcx>) -> Kind<'tcx> {
7598
UnpackedKind::Lifetime(r).pack()

src/librustc_data_structures/sorted_map.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ use std::ops::{RangeBounds, Bound, Index, IndexMut};
2222
/// stores data in a more compact way. It also supports accessing contiguous
2323
/// ranges of elements as a slice, and slices of already sorted elements can be
2424
/// inserted efficiently.
25-
#[derive(Clone, PartialEq, Eq, Hash, Default, Debug, RustcEncodable, RustcDecodable)]
25+
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug, RustcEncodable,
26+
RustcDecodable)]
2627
pub struct SortedMap<K: Ord, V> {
2728
data: Vec<(K,V)>
2829
}

src/librustc_target/abi/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ impl AddAssign for Size {
332332
/// Each field is a power of two, giving the alignment a maximum value
333333
/// of 2<sup>(2<sup>8</sup> - 1)</sup>, which is limited by LLVM to a
334334
/// maximum capacity of 2<sup>29</sup> or 536870912.
335-
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
335+
#[derive(Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash, Debug, RustcEncodable, RustcDecodable)]
336336
pub struct Align {
337337
abi_pow2: u8,
338338
pref_pow2: u8,

src/librustc_target/spec/abi.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use std::fmt;
1212

13-
#[derive(PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Clone, Copy, Debug)]
13+
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Clone, Copy, Debug)]
1414
pub enum Abi {
1515
// NB: This ordering MUST match the AbiDatas array below.
1616
// (This is ensured by the test indices_are_correct().)

0 commit comments

Comments
 (0)