paritytech / paritytech/parity-scale-codec

Derivation adds unnecessary bounds that can't be satisfied for certain recursive types

Open
#603 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
287
Forks
103
Avg merge
6d 13h
Merged PRs (30d)
1

Description

Error encountered
error[E0277]: the trait bound `BrakesOthers<u32>: Decode` is not satisfied
   --> tests/mod.rs:898:14
    |
898 |     pub broken: runtime::BrakesOthers<u32>,
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Decode` is not implemented for `BrakesOthers<u32>`
    |
    = help: the trait `Decode` is implemented for `BrakesOthers<_1>`

error[E0277]: the trait bound `BrakesOthers<u32>: Encode` is not satisfied
   --> tests/mod.rs:896:24
    |
896 | #[derive(DeriveDecode, DeriveEncode, Debug)]
    |                        ^^^^^^^^^^^^ the trait `Encode` is not implemented for `BrakesOthers<u32>`, which is required by `&BrakesOthers<u32>: Encode`
    |
    = help: the trait `Encode` is implemented for `BrakesOthers<_1>`
    = note: required for `&BrakesOthers<u32>` to implement `Encode`
    = note: this error originates in the derive macro `DeriveEncode` (in Nightly builds, run with -Z macro-backtrace for more info)

For more information about this error, try `rustc --explain E0277`.

Minimal Repro:

#[derive(DeriveDecode, DeriveEncode, Debug)]
pub struct Foo2 {
	pub broken: runtime::BrakesOthers<u32>,
}

pub mod runtime {
	use std::marker::PhantomData;

	use parity_scale_codec_derive::{Decode as DeriveDecode, Encode as DeriveEncode};

	#[derive(DeriveEncode, DeriveDecode, Debug)]
	pub struct BrakesOthers<_1> {
		twtwt: Box<super::runtime::BrakesOthers<_1>>,
		marker: PhantomData<_1>,
	}
}

Produces trait with extra bounds(expansion below, note extra Containter<Self> bounds introduced):

Click me(`Encode` as the example, although same happens for `Decode` too)
// Recursive expansion of DeriveEncode macro
// ==========================================

#[allow(deprecated)]
const _: () = {
	#[automatically_derived]
	impl<_1> ::parity_scale_codec::Encode for BrakesOthers<_1>
	where
		Box<super::runtime::BrakesOthers<_1>>: ::parity_scale_codec::Encode,
		Box<super::runtime::BrakesOthers<_1>>: ::parity_scale_codec::Encode,
		PhantomData<_1>: ::parity_scale_codec::Encode,
		PhantomData<_1>: ::parity_scale_codec::Encode,
	{
		fn size_hint(&self) -> usize {
			0_usize
				.saturating_add(::parity_scale_codec::Encode::size_hint(&self.twtwt))
				.saturating_add(::parity_scale_codec::Encode::size_hint(&self.marker))
		}
		fn encode_to<__CodecOutputEdqy: ::parity_scale_codec::Output + ?::core::marker::Sized>(
			&self,
			__codec_dest_edqy: &mut __CodecOutputEdqy,
		) {
			::parity_scale_codec::Encode::encode_to(&self.twtwt, __codec_dest_edqy);
			::parity_scale_codec::Encode::encode_to(&self.marker, __codec_dest_edqy);
		}
	}
	#[automatically_derived]
	impl<_1> ::parity_scale_codec::EncodeLike for BrakesOthers<_1>
	where
		Box<super::runtime::BrakesOthers<_1>>: ::parity_scale_codec::Encode,
		Box<super::runtime::BrakesOthers<_1>>: ::parity_scale_codec::Encode,
		PhantomData<_1>: ::parity_scale_codec::Encode,
		PhantomData<_1>: ::parity_scale_codec::Encode,
	{
	}
};

changing this line to

  for segment in i.path.segments.iter() {

seems to solve the issue of correctly detecting the recursive ty_ident.

Tests pass after the change, however it might break things not tested in the ecosystem(?)
also see: paritytech/subxt#1603

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Inspect derive/src/trait_bounds.rs around line 55 and the recursive type-identifier detection logic, using the provided BrakesOthers reproduction as the starting case. Run the existing test suite and verify that the generated Encode and Decode implementations no longer contain unsatisfiable recursive bounds. Check that other trait-bound cases remain unaffected, including the related paritytech/subxt#1603 scenario.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
tooling
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.