Skip to contentSkip to conversation

From<bool> and Bounded's invariant for signed N = 1

DISCUSSION Younes Akhouayri 3 participants 5 messages Aug 13 – Aug 14 Rust

lore
Share & tools
lore
#0 lore raw

Hi,

There seems to be an invariant violation in the generic From<bool> implementation for Bounded.

As I understand it, Bounded<i8, 1> can represent only -1 and 0, while i8::from(true) produces 1. However, this safe code is accepted:

let value: Bounded<i8, 1> = true.into();
let _raw: i8 = *value;

Bounded::<i8, 1>::try_new(1) rejects the same value, but From<bool> passes it directly to the unsafe __new() constructor. The resulting Bounded value violates the invariant relied upon by Deref, whose failure branch calls unreachable_unchecked().

Am I missing an intended constraint on this conversion? If not, it seems the signed N = 1 case needs to be excluded or handled differently.

Any thoughts?

Thanks,
Younes

#1 lore raw
Quoted 2 lines · Younes Akhouayri

Any thoughts?

Thanks for the report!

That is correct, good eyes -- indeed, the Deref bites us again like in 223aa25aee82.

Do you want to write a patch?

Cheers,
Miguel

#2 lore raw
In reply to Younes Akhouayri
Quoted 16 lines · Younes Akhouayri

Hi,

There seems to be an invariant violation in the generic From<bool> implementation for Bounded.

As I understand it, Bounded<i8, 1> can represent only -1 and 0, while i8::from(true) produces 1. However, this safe code is accepted:

let value: Bounded<i8, 1> = true.into();
let _raw: i8 = *value;

Bounded::<i8, 1>::try_new(1) rejects the same value, but From<bool> passes it directly to the unsafe __new() constructor. The resulting Bounded value violates the invariant relied upon by Deref, whose failure branch calls unreachable_unchecked().

Quoted 5 lines

Am I missing an intended constraint on this conversion? If not, it seems the signed N = 1 case needs to be excluded or handled differently.

Any thoughts?

I think you are correct. There is a Signedness associated type on the Integer trait, so it should be trivial to exclude signed integers - do you want to send a patch for that?

#3 lore raw

Thank you both for the feedback. Yes, I can send a patch.

Just to confirm the intended scope: excluding signed integers entirely would also remove valid conversions such as Bounded::<i8, 2>::from(true), since signed Bounded values with N >= 2 can represent both 0 and 1.

Would you prefer the simpler unsigned-only restriction, or should the patch preserve signed conversions for N >= 2?

--

Best regards,
Younes

Aug 13, 2026, 15:04 by [email protected]:

Quoted 29 lines · Younes Akhouayri
Quoted 17 lines

Hi,

There seems to be an invariant violation in the generic From<bool> implementation for Bounded.

As I understand it, Bounded<i8, 1> can represent only -1 and 0, while i8::from(true) produces 1. However, this safe code is accepted:

let value: Bounded<i8, 1> = true.into();
let _raw: i8 = *value;

Bounded::<i8, 1>::try_new(1) rejects the same value, but From<bool> passes it directly to the unsafe __new() constructor. The resulting Bounded value violates the invariant relied upon by Deref, whose failure branch calls unreachable_unchecked().

Quoted 6 lines

Am I missing an intended constraint on this conversion? If not, it seems the signed N = 1 case needs to be excluded or handled differently.

Any thoughts?

I think you are correct. There is a Signedness associated type on the Integer trait, so it should be trivial to exclude signed integers - do you want to send a patch for that?

#4 lore raw
Quoted 5 lines · Younes Akhouayri

Thank you both for the feedback. Yes, I can send a patch.

Just to confirm the intended scope: excluding signed integers entirely would also remove valid conversions such as Bounded::<i8, 2>::from(true), since signed Bounded values with N >= 2 can represent both 0 and 1.

Would you prefer the simpler unsigned-only restriction, or should the patch preserve signed conversions for N >= 2?

If you can preserve the latter without complicating the code too much, then I'd say that should be preferred yes.