Skip to content

Commit ede90f3

Browse files
committed
remove equality impls for introspect::Type, in favor of new loose_equals() method
1 parent 755ca84 commit ede90f3

File tree

10 files changed

+33
-78
lines changed

10 files changed

+33
-78
lines changed

capnp/src/data_list.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -218,10 +218,9 @@ impl<'a> From<Reader<'a>> for crate::dynamic_value::Reader<'a> {
218218
impl<'a> crate::dynamic_value::DowncastReader<'a> for Reader<'a> {
219219
fn downcast_reader(v: crate::dynamic_value::Reader<'a>) -> Self {
220220
let dl: crate::dynamic_list::Reader = v.downcast();
221-
assert_eq!(
222-
dl.element_type(),
223-
crate::introspect::TypeVariant::Data.into()
224-
);
221+
assert!(dl
222+
.element_type()
223+
.loose_equals(crate::introspect::TypeVariant::Data.into()));
225224
Reader { reader: dl.reader }
226225
}
227226
}
@@ -238,10 +237,9 @@ impl<'a> From<Builder<'a>> for crate::dynamic_value::Builder<'a> {
238237
impl<'a> crate::dynamic_value::DowncastBuilder<'a> for Builder<'a> {
239238
fn downcast_builder(v: crate::dynamic_value::Builder<'a>) -> Self {
240239
let dl: crate::dynamic_list::Builder = v.downcast();
241-
assert_eq!(
242-
dl.element_type(),
243-
crate::introspect::TypeVariant::Data.into()
244-
);
240+
assert!(dl
241+
.element_type()
242+
.loose_equals(crate::introspect::TypeVariant::Data.into()));
245243
Builder {
246244
builder: dl.builder,
247245
}

capnp/src/dynamic_struct.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ impl<'a> Reader<'a> {
246246
Into::<crate::introspect::Type>::into(crate::introspect::TypeVariant::Struct(
247247
self.schema.raw
248248
))
249-
.may_downcast_to(T::introspect())
249+
.loose_equals(T::introspect())
250250
);
251251
self.reader.into()
252252
}
@@ -814,7 +814,7 @@ impl<'a> Builder<'a> {
814814
Into::<crate::introspect::Type>::into(crate::introspect::TypeVariant::Struct(
815815
self.schema.raw
816816
))
817-
.may_downcast_to(T::introspect())
817+
.loose_equals(T::introspect())
818818
);
819819
self.builder.into()
820820
}

capnp/src/enum_list.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ impl<'a, T: TryFrom<u16, Error = NotInSchema> + crate::introspect::Introspect>
260260
{
261261
fn downcast_reader(v: crate::dynamic_value::Reader<'a>) -> Self {
262262
let dl: crate::dynamic_list::Reader = v.downcast();
263-
assert!(dl.element_type().may_downcast_to(T::introspect()));
263+
assert!(dl.element_type().loose_equals(T::introspect()));
264264
Reader {
265265
reader: dl.reader,
266266
marker: PhantomData,
@@ -284,7 +284,7 @@ impl<'a, T: TryFrom<u16, Error = NotInSchema> + crate::introspect::Introspect>
284284
{
285285
fn downcast_builder(v: crate::dynamic_value::Builder<'a>) -> Self {
286286
let dl: crate::dynamic_list::Builder = v.downcast();
287-
assert!(dl.element_type().may_downcast_to(T::introspect()));
287+
assert!(dl.element_type().loose_equals(T::introspect()));
288288
Builder {
289289
builder: dl.builder,
290290
marker: PhantomData,

capnp/src/introspect.rs

Lines changed: 7 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ pub trait Introspect {
1313
/// optimized to avoid heap allocation.
1414
///
1515
/// To examine a `Type`, you should call the `which()` method.
16-
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
16+
#[derive(Copy, Clone, Debug)]
1717
pub struct Type {
1818
/// The type, minus any outer `List( )`.
1919
base: BaseType,
@@ -105,9 +105,9 @@ impl Type {
105105
}
106106
}
107107

108-
/// Returns true is a dynamic value of type `self` is
109-
/// allowed to be downcast to type `other`.
110-
pub(crate) fn may_downcast_to(&self, other: Self) -> bool {
108+
/// Returns true if `self` is equal to `other` modulo
109+
/// type parameters and interface types.
110+
pub fn loose_equals(&self, other: Self) -> bool {
111111
match (self.which(), other.which()) {
112112
(TypeVariant::Void, TypeVariant::Void) => true,
113113
(TypeVariant::UInt8, TypeVariant::UInt8) => true,
@@ -133,7 +133,7 @@ impl Type {
133133
core::ptr::eq(rbs1.generic, rbs2.generic)
134134
}
135135
(TypeVariant::List(element1), TypeVariant::List(element2)) => {
136-
element1.may_downcast_to(element2)
136+
element1.loose_equals(element2)
137137
}
138138
(TypeVariant::AnyPointer, TypeVariant::AnyPointer) => true,
139139
(TypeVariant::Capability, TypeVariant::Capability) => true,
@@ -142,7 +142,7 @@ impl Type {
142142
}
143143
}
144144

145-
#[derive(Copy, Clone, PartialEq, Eq)]
145+
#[derive(Copy, Clone)]
146146
/// A `Type` unfolded one level. Suitable for pattern matching. Can be trivially
147147
/// converted to `Type` via the `From`/`Into` traits.
148148
pub enum TypeVariant {
@@ -194,7 +194,7 @@ impl From<TypeVariant> for Type {
194194
}
195195

196196
/// A Cap'n Proto type, excluding `List`.
197-
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
197+
#[derive(Copy, Clone, Debug)]
198198
enum BaseType {
199199
Void,
200200
Bool,
@@ -270,34 +270,6 @@ pub struct RawBrandedStructSchema {
270270
pub annotation_types: fn(Option<u16>, u32) -> Type,
271271
}
272272

273-
/// WARNING!
274-
///
275-
/// In capnproto-c++, this method is implemented as a single pointer
276-
/// comparison. That works because C++ guarantees unique addresses
277-
/// for static template instantiations. In contrast, the below Rust
278-
/// implementation uses function pointer comparison, which might
279-
/// give unexpected results (particularly in the presence of type
280-
/// parameter instantiation).
281-
///
282-
/// For this reason, usage of equality on types in capnproto-rust
283-
/// is discouraged.
284-
///
285-
/// You might think that we could still implement the method
286-
/// in a slower way by recursively comparing types of fields.
287-
/// However, that (or at least the naive version of it) can hit
288-
/// infinite loops because e.g. a struct Foo might have a field of
289-
/// type Foo.
290-
///
291-
/// TODO(api_bump): remove this `impl PartialEq`.
292-
impl core::cmp::PartialEq for RawBrandedStructSchema {
293-
#[allow(unpredictable_function_pointer_comparisons)]
294-
fn eq(&self, other: &Self) -> bool {
295-
core::ptr::eq(self.generic, other.generic) && self.field_types == other.field_types
296-
}
297-
}
298-
299-
impl core::cmp::Eq for RawBrandedStructSchema {}
300-
301273
impl core::fmt::Debug for RawBrandedStructSchema {
302274
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::result::Result<(), core::fmt::Error> {
303275
write!(

capnp/src/list_list.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ impl<'a, T: crate::traits::Owned> From<Reader<'a, T>> for crate::dynamic_value::
287287
impl<'a, T: crate::traits::Owned> crate::dynamic_value::DowncastReader<'a> for Reader<'a, T> {
288288
fn downcast_reader(v: crate::dynamic_value::Reader<'a>) -> Self {
289289
let dl: crate::dynamic_list::Reader = v.downcast();
290-
assert!(dl.element_type().may_downcast_to(T::introspect()));
290+
assert!(dl.element_type().loose_equals(T::introspect()));
291291
Reader {
292292
reader: dl.reader,
293293
marker: core::marker::PhantomData,
@@ -307,7 +307,7 @@ impl<'a, T: crate::traits::Owned> From<Builder<'a, T>> for crate::dynamic_value:
307307
impl<'a, T: crate::traits::Owned> crate::dynamic_value::DowncastBuilder<'a> for Builder<'a, T> {
308308
fn downcast_builder(v: crate::dynamic_value::Builder<'a>) -> Self {
309309
let dl: crate::dynamic_list::Builder = v.downcast();
310-
assert!(dl.element_type().may_downcast_to(T::introspect()));
310+
assert!(dl.element_type().loose_equals(T::introspect()));
311311
Builder {
312312
builder: dl.builder,
313313
marker: core::marker::PhantomData,

capnp/src/primitive_list.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ impl<'a, T: PrimitiveElement + crate::introspect::Introspect>
349349
{
350350
fn downcast_reader(v: crate::dynamic_value::Reader<'a>) -> Self {
351351
let dl: crate::dynamic_list::Reader = v.downcast();
352-
assert!(dl.element_type().may_downcast_to(T::introspect()));
352+
assert!(dl.element_type().loose_equals(T::introspect()));
353353
Reader {
354354
reader: dl.reader,
355355
marker: marker::PhantomData,
@@ -373,7 +373,7 @@ impl<'a, T: PrimitiveElement + crate::introspect::Introspect>
373373
{
374374
fn downcast_builder(v: crate::dynamic_value::Builder<'a>) -> Self {
375375
let dl: crate::dynamic_list::Builder = v.downcast();
376-
assert!(dl.element_type().may_downcast_to(T::introspect()));
376+
assert!(dl.element_type().loose_equals(T::introspect()));
377377
Builder {
378378
builder: dl.builder,
379379
marker: marker::PhantomData,

capnp/src/struct_list.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ impl<'a, T: crate::traits::OwnedStruct> From<Reader<'a, T>> for crate::dynamic_v
294294
impl<'a, T: crate::traits::OwnedStruct> crate::dynamic_value::DowncastReader<'a> for Reader<'a, T> {
295295
fn downcast_reader(v: crate::dynamic_value::Reader<'a>) -> Self {
296296
let dl: crate::dynamic_list::Reader = v.downcast();
297-
assert!(dl.element_type().may_downcast_to(T::introspect()));
297+
assert!(dl.element_type().loose_equals(T::introspect()));
298298
Reader {
299299
reader: dl.reader,
300300
marker: PhantomData,
@@ -316,7 +316,7 @@ impl<'a, T: crate::traits::OwnedStruct> crate::dynamic_value::DowncastBuilder<'a
316316
{
317317
fn downcast_builder(v: crate::dynamic_value::Builder<'a>) -> Self {
318318
let dl: crate::dynamic_list::Builder = v.downcast();
319-
assert!(dl.element_type().may_downcast_to(T::introspect()));
319+
assert!(dl.element_type().loose_equals(T::introspect()));
320320
Builder {
321321
builder: dl.builder,
322322
marker: PhantomData,

capnp/src/text_list.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -253,10 +253,9 @@ impl<'a> From<Reader<'a>> for crate::dynamic_value::Reader<'a> {
253253
impl<'a> crate::dynamic_value::DowncastReader<'a> for Reader<'a> {
254254
fn downcast_reader(v: crate::dynamic_value::Reader<'a>) -> Self {
255255
let dl: crate::dynamic_list::Reader = v.downcast();
256-
assert_eq!(
257-
dl.element_type(),
258-
crate::introspect::TypeVariant::Text.into()
259-
);
256+
assert!(dl
257+
.element_type()
258+
.loose_equals(crate::introspect::TypeVariant::Text.into()));
260259
Reader { reader: dl.reader }
261260
}
262261
}
@@ -273,10 +272,9 @@ impl<'a> From<Builder<'a>> for crate::dynamic_value::Builder<'a> {
273272
impl<'a> crate::dynamic_value::DowncastBuilder<'a> for Builder<'a> {
274273
fn downcast_builder(v: crate::dynamic_value::Builder<'a>) -> Self {
275274
let dl: crate::dynamic_list::Builder = v.downcast();
276-
assert_eq!(
277-
dl.element_type(),
278-
crate::introspect::TypeVariant::Text.into()
279-
);
275+
assert!(dl
276+
.element_type()
277+
.loose_equals(crate::introspect::TypeVariant::Text.into()));
280278
Builder {
281279
builder: dl.builder,
282280
}

capnpc/test/dynamic.rs

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -507,24 +507,11 @@ fn test_downcasts() {
507507
}
508508
}
509509

510-
// Function pointer equality is used in
511-
// `impl PartialEq for RawBrandedStructSchema`. On MIRI that implies
512-
// that all struct types are inequal.
513-
//
514-
// The plan is to remove that impl in the future, to avoid
515-
// unpleasant surprises.
516-
#[cfg_attr(miri, ignore)]
517510
#[test]
518-
fn introspect_equality() {
511+
fn introspect_loose_equals() {
519512
use capnp::introspect::Introspect;
520513

521-
assert_eq!(
522-
test_all_types::Owned::introspect(),
523-
test_all_types::Owned::introspect()
524-
);
514+
assert!(test_all_types::Owned::introspect().loose_equals(test_all_types::Owned::introspect()));
525515

526-
assert_ne!(
527-
test_all_types::Owned::introspect(),
528-
test_defaults::Owned::introspect()
529-
)
516+
assert!(!test_all_types::Owned::introspect().loose_equals(test_defaults::Owned::introspect()))
530517
}

example/fill_random_values/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ impl<R: Rng> Filler<R> {
7676
for annotation in annotations {
7777
if annotation.get_id() == fill_capnp::select_from::choices::ID {
7878
if let TypeVariant::List(element_type) = annotation.get_type().which() {
79-
if element_type != field.get_type() {
79+
if !element_type.loose_equals(field.get_type()) {
8080
return Err(::capnp::Error::failed(
8181
"choices annotation element type mismatch".into(),
8282
));

0 commit comments

Comments
 (0)