Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

Use a more typesafe approach for managing indexed data#5503

Closed
tifecool wants to merge 33 commits intoparitytech:masterfrom
tifecool:fix2403
Closed

Use a more typesafe approach for managing indexed data#5503
tifecool wants to merge 33 commits intoparitytech:masterfrom
tifecool:fix2403

Conversation

@tifecool
Copy link
Copy Markdown
Contributor

My attempt to resolve issue: paritytech/polkadot-sdk#978

Currently incomplete, having an error at polkadot-erasure-coding preventing me from testing, was hoping to get some advice and confirmation that I'm going about this the right way!

@tifecool
Copy link
Copy Markdown
Contributor Author

@eskimor

Copy link
Copy Markdown
Member

@eskimor eskimor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good at first pass.

impl From<usize> for ValidatorIndex {
fn from(n: usize) -> Self {
// can't panic, so need to truncate
let n = n.try_into().unwrap_or(u32::MAX);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

debug_assert would be good.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How would I implement this?

@tifecool
Copy link
Copy Markdown
Contributor Author

Thanks so much for the review! @eskimor
Will keep at it and implement the suggested changes ❤️

@ordian
Copy link
Copy Markdown

ordian commented May 18, 2022

I'd vote for creating our own type-wrapper for Vec instead of using a dependency. We don't seem to need most of its methods other than type-safe indexing, which can be implemented easily as pointed out in paritytech/polkadot-sdk#978.

As a side note, please revert unrelated changes.

@tifecool
Copy link
Copy Markdown
Contributor Author

tifecool commented May 19, 2022

I'd vote for creating our own type-wrapper for Vec instead of using a dependency. We don't seem to need most of its methods other than type-safe indexing, which can be implemented easily as pointed out in #2403 (comment).

Might need a bit of assistance/step through with this, but I think I have an idea of how to implement the change. Also, could I get help with why the checks are failing? Working on it

As a side note, please revert unrelated changes.

Which changes?

@paritytech-ci paritytech-ci requested review from a team May 19, 2022 22:54
@tifecool
Copy link
Copy Markdown
Contributor Author

tifecool commented May 19, 2022

Not the best at git. Apologies for the numerous pushes

}
}

impl From<usize> for ValidatorIndex {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need an impl for From<usize> if it's not guaranteed to be ok? Wouldn't a From<u32> not make more sense and leave it to the user to decide what to do on errors instead of generating a garbage ValidatorIndex? TryFrom<usize> and From<u32> seem more reasonable to me.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While working on this, the error:

the trait bound `K: From<usize>` is not satisfied
    --> primitives/src/v2/mod.rs:1616:17
     |
1616 | #[derive(Clone, RuntimeDebug)]
     |                 ^^^^^^^^^^^^ the trait `From<usize>` is not implemented for `K`

came up. This is why I likely implemented the From<usize> trait.

@paritytech-ci paritytech-ci requested a review from a team May 20, 2022 11:15
Sr25519Keyring::Charlie,
]),
validator_groups: vec![
validator_groups: TypeVec::from(vec![
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should consider adding a custom macro that resembles the ergonomy of vec![..]

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't write macros.

@paritytech-ci paritytech-ci requested a review from a team May 20, 2022 11:22
}
}

impl<K: From<usize>, V: Clone> From<Vec<V>> for TypeVec<K, V> {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
impl<K: From<usize>, V: Clone> From<Vec<V>> for TypeVec<K, V> {
impl<K: From<usize>, V: Clone, I: IntoIterator<Item=V>> From<I> for TypeVec<K, V> {

type Identity = ();

fn type_info() -> Type {
todo!()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Must be fixed before merge

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not quite sure how to implement this trait.

Copy link
Copy Markdown
Contributor

@drahnr drahnr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your contribution and the time invested! The direction of the impl is definitely something we want rather sooner than later 👍

Though, I am not sure the chosen crate is the best choice. Having a fallback of u32::MAX is not necessarily a good thing when values are out of bounds when the only reason to have those bounds is the chosen crate to require From<usize> to be implemented. I am aware that practically speaking this should never happen, I am just very reluctanct to introduce a future footgun.

fn from(vec: Vec<V>) -> Self {
let mut type_vec: TypeVec<K, V> = TypeVec::new();
for value in vec.into_iter() {
type_vec.0.push(value)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a very inefficient impl considering that TiVec impls From<Vec<T>>

#[cfg(feature = "std")]
impl<K: From<usize>, V: Clone> MallocSizeOf for TypeVec<K, V> {
fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
0
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

incorrect, should delegate to Vec impl

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Attempting this is causing issues.

Copy link
Copy Markdown
Contributor Author

@tifecool tifecool May 20, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#[cfg(feature = "std")]
has to be implemented in numerous places to trait bound generic type V

Copy link
Copy Markdown
Contributor Author

@tifecool tifecool May 20, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Attempted implementation:

#[cfg(feature = "std")]
impl<K: From<usize>, V: Clone> MallocSizeOf for TypeVec<K, V> {
	fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
		self.to_vec().size_of(ops)
	}
}

0
}
fn constant_size() -> Option<usize> {
Some(0)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

incorrect, shouldn't be implemented

frame_election_provider_support::ElectionDataProvider
<Self as pallet_election_provider_multi_phase::Config>::DataProvider
as
frame_election_provider_support::ElectionDataProvider
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unrelated change (and probably doesn't pass rustfmt)

/// A bitfield indicating all validators for the candidate.
pub validators_for: BitVec<u8, bitvec::order::Lsb0>, // one bit per validator.
pub validators_for: BitVec<u8, bitvec::order::Lsb0>,
// one bit per validator.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please revert unrelated formatting changes, we're using a specific nightly version for fmt

{
let mut trie = TrieDBMut::new(&mut trie_storage, &mut root);
for (i, chunk) in chunks.as_ref().iter().enumerate() {
for (i, chunk) in chunks.iter().enumerate() {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unrelated change

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was getting this error:

error[E0282]: type annotations needed
   --> erasure-coding/src/lib.rs:261:28
    |
261 |         for (i, chunk) in chunks.as_ref().iter().enumerate() {
    |                           -------^^^^^^--
    |                           |      |
    |                           |      cannot infer type for type parameter `T` declared on the trait `AsRef`
    |                           this method call resolves to `&T`
    |
    = note: type must be known at this point

And on debugging saw the as_ref() made no difference to the object.

@paritytech-ci paritytech-ci requested a review from a team May 20, 2022 13:50
tifecool and others added 2 commits May 20, 2022 19:03
Co-authored-by: Bernhard Schuster <bernhard@ahoi.io>
@tifecool
Copy link
Copy Markdown
Contributor Author

Going to reattempt this from scratch

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants