Skip to content

rkyv in Rust 1.56: type annotations needed #90195

Closed

Description

@xobs

Prior to Rust 1.56, I could use const usize values when defining rkyv structs. However, in Rust 1.56, this is no longer allowed.

Code

I tried this code:

const ARRAY_SIZE: usize = 32;

#[derive(rkyv::Archive, rkyv::Deserialize)]
struct SomeStruct1 {
    buffer_one: Option<[u8; ARRAY_SIZE]>,
    buffer_two: Option<[u8; ARRAY_SIZE]>,
}

fn main() {
    println!("Pass");
}

I expected to see this happen: Prior to Rust 1.56, this compiled.

Instead, this happened: The following error appears:

error[E0284]: type annotations needed: cannot satisfy `<Option<[u8; 32]> as Archive>::Archived == _`
 --> src\main.rs:3:25
  |
3 | #[derive(rkyv::Archive, rkyv::Deserialize)]
  |                         ^^^^^^^^^^^^^^^^^ cannot satisfy `<Option<[u8; 32]> as Archive>::Archived == _`
  |
  = note: this error originates in the derive macro `rkyv::Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info)

For more information about this error, try `rustc --explain E0284`.
error: could not compile `rkyv-test` due to previous error

Version it worked on

It most recently worked on: Rust 1.55

Version with regression

rustc --version --verbose:

rustc 1.56.0 (09c42c458 2021-10-18)
binary: rustc
commit-hash: 09c42c45858d5f3aedfa670698275303a3d19afa
commit-date: 2021-10-18
host: x86_64-pc-windows-msvc
release: 1.56.0
LLVM version: 13.0.0

Activity

  1. added
    C-bugCategory: This is a bug.
    regression-untriagedUntriaged performance or correctness regression.
    on Oct 23, 2021
  2. added
    I-prioritizeIssue needs a team member to assess the impact. Will be replaced by P-{low,medium,high,critical}
    and removed
    I-prioritizeIssue needs a team member to assess the impact. Will be replaced by P-{low,medium,high,critical}
    regression-untriagedUntriaged performance or correctness regression.
    on Oct 23, 2021
  3. xobs commented on Oct 23, 2021

    @xobs
    ContributorAuthor

    Further information: This is using the rkyv crate. We use an older 0.4.0, however this still occurs with the latest 0.7 version.

  4. hkratz commented on Oct 23, 2021

    @hkratz
    Contributor

    Bisected to #87280.

    @rustbot label +E-needs-mcve

  5. added
    E-needs-mcveCall for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example
    on Oct 23, 2021
  6. hkratz commented on Oct 23, 2021

    @hkratz
    Contributor

    Reproducer without macros, but still dependent on rkyv:

    #![allow(dead_code)]
    #![allow(unused_variables)]
    
    use rkyv::{Archive, Archived, Deserialize, Fallible};
    
    const ARRAY_SIZE: usize = 32;
    struct SomeStruct1 {
        buffer_one: Option<[u8; ARRAY_SIZE]>,
        buffer_two: Option<[u8; ARRAY_SIZE]>,
    }
    
    struct ArchivedSomeStruct1
    where
        Option<[u8; ARRAY_SIZE]>: ::rkyv::Archive,
        Option<[u8; ARRAY_SIZE]>: ::rkyv::Archive,
    {
        buffer_one: ::rkyv::Archived<Option<[u8; ARRAY_SIZE]>>,
        buffer_two: ::rkyv::Archived<Option<[u8; ARRAY_SIZE]>>,
    }
    
    struct SomeStruct1Resolver
    where
        Option<[u8; ARRAY_SIZE]>: ::rkyv::Archive,
        Option<[u8; ARRAY_SIZE]>: ::rkyv::Archive,
    {
        buffer_one: ::rkyv::Resolver<Option<[u8; ARRAY_SIZE]>>,
        buffer_two: ::rkyv::Resolver<Option<[u8; ARRAY_SIZE]>>,
    }
    
    impl Archive for SomeStruct1
    where
        Option<[u8; ARRAY_SIZE]>: ::rkyv::Archive,
        Option<[u8; ARRAY_SIZE]>: ::rkyv::Archive,
    {
        type Archived = ArchivedSomeStruct1;
        type Resolver = SomeStruct1Resolver;
        #[allow(clippy::unit_arg)]
        #[inline]
        unsafe fn resolve(&self, pos: usize, resolver: Self::Resolver, out: *mut Self::Archived) {
            unreachable!();
        }
    }
    
    impl<__D: Fallible + ?Sized> Deserialize<SomeStruct1, __D> for Archived<SomeStruct1>
    where
        Option<[u8; ARRAY_SIZE]>: Archive,
        Archived<Option<[u8; ARRAY_SIZE]>>: Deserialize<Option<[u8; ARRAY_SIZE]>, __D>,
        Option<[u8; ARRAY_SIZE]>: Archive,
        Archived<Option<[u8; ARRAY_SIZE]>>: Deserialize<Option<[u8; ARRAY_SIZE]>, __D>,
    {
        fn deserialize(
            &self,
            deserializer: &mut __D,
        ) -> ::core::result::Result<SomeStruct1, __D::Error> {
            unreachable!();
        }
    }
    
    fn main() {}
  7. SNCPlay42 commented on Oct 23, 2021

    @SNCPlay42
    Contributor

    Reduced:

    pub trait Archive {
        type Archived;
    }
    
    impl<T> Archive for Option<T> {
        type Archived = ();
    }
    pub type Archived<T> = <T as Archive>::Archived;
    
    pub trait Deserialize<D> {}
    
    const ARRAY_SIZE: usize = 32;
    impl<__D> Deserialize<__D> for ()
    where
        Option<[u8; ARRAY_SIZE]>: Archive,
        Option<[u8; ARRAY_SIZE]>: Archive,
        Archived<Option<[u8; ARRAY_SIZE]>>: Deserialize<__D>,
    {
    }

    Also, if you remove one of the Option<[u8; ARRAY_SIZE]>: Archive, lines, the code still compiles on 1.55 but the error on 1.56 changes to:

    error[E0275]: overflow evaluating the requirement `(): Deserialize<__D>`
      --> <source>:13:11
       |
    13 | impl<__D> Deserialize<__D> for ()
       |           ^^^^^^^^^^^^^^^^
       |
    note: required by a bound in `Deserialize`
      --> <source>:10:1
       |
    10 | pub trait Deserialize<D> {}
       | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Deserialize`
    
    error: aborting due to previous error
    
    For more information about this error, try `rustc --explain E0275`.
    

    @rustbot label regression-from-stable-to-stable

    (not sure what happened with rustbot and the labels above)

  8. added
    regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.
    I-prioritizeIssue needs a team member to assess the impact. Will be replaced by P-{low,medium,high,critical}
    on Oct 23, 2021
  9. SNCPlay42 commented on Oct 23, 2021

    @SNCPlay42
    Contributor

    @rustbot label -E-needs-mcve

  10. removed
    E-needs-mcveCall for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example
    on Oct 23, 2021
  11. yanok commented on Oct 28, 2021

    @yanok
    Contributor

    @rustbot claim

  12. apiraino commented on Oct 28, 2021

    @apiraino
    Contributor

    Assigning priority as discussed in the Zulip thread of the Prioritization Working Group.

    @rustbot label -I-prioritize +P-high +T-compiler

  13. added
    P-highHigh priority
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    and removed
    I-prioritizeIssue needs a team member to assess the impact. Will be replaced by P-{low,medium,high,critical}
    on Oct 28, 2021
  14. yanok commented on Oct 28, 2021

    @yanok
    Contributor

    Ok, I know what is the problem and have a fix.

    Apparently when looking for Archive implementation for Option<[u8; ARRAY_SIZE]> compiler considers candidates: one for top-level impl and two ParamCandidates.

    Before #87280 candidate_should_be_dropped_in_favor_of was using TypeFoldable::is_global() that was enough to discard the two ParamCandidates. But #87280 changed it to use TypeFoldable::is_know_global() instead, which is pessimistic, so now the compiler drops the global impl instead (because is_known_global is not sure) and then can't decide between the two ParamCandidates.

  15. yanok commented on Oct 28, 2021

    @yanok
    Contributor

    Funny thing is it seems like it's fixed already in the master branch... Trying to bisect what fixed it to better understand if my change is needed after all.

  16. yanok commented on Oct 28, 2021

    @yanok
    Contributor

    c6b6901 also fixes it.

  17. added a commit that references this issue on Oct 30, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

C-bugCategory: This is a bug.P-highHigh priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions