Skip to content

Make it possible for combine::primitives::ParseError to be std::error::Error for more range types #86

@ncalexan

Description

@ncalexan

Over in https://github.com/mozilla/mentat, we're using combine to parse &'a [edn::Value] slices. Here, edn::Value is a generic value type conceptually similar to JSON. What is happening here is not specific to edn::Value, so I'll use T: we're using combine to parse &'a [T] streams.

The error type of such a Parser is combine::primitives::ParseError<&'a [T]>. Now, around

impl<S> StdError for ParseError<S>
, you'll see that such an error will be a std::error::Error only when the underlying Stream::Range is std::fmt::Display. However, no slice &'a [T] can ever satisfy this trait bound due to rust-lang/rust#39328.

I can think of the following ways to work around this issue:

  • wait for the Rust specialization feature to land in stable, so that we can specialize the implementation of std::error::Error for &'a [edn::Value].
    Even with specialization, this may not allow to solve the problem, depending on the restrictions on third-party types.
  • wrap our &'a [T] streams in a newtype implementing Stream, and wrap the Stream::Range type as well.
    I have done this locally; it's not hard, but I expect it to have a non-trivial runtime cost, since all ranges need to be wrapped and unwrapped. I'd be surprised if the compiler could make this zero-cost, but I'd love to be amazed.
  • add a new function to the Range trait specifically for wrapping or otherwise helping format Range instances.
    I doubt this would be difficult, but it would be a breaking API change: existing consumers with non-default Range implementations would have to add the new method, even if they didn't care about this issue (which they can't have been using without significant effort).
  • add a new RangeDisplay trait in combine, define it for the Range types in combine, and expect that in the std::error::Error implementation.
    This is the least intrusive solution, but ties all Range implementations to a single display format. I think this is okay, though -- it's already the case that &str ranges have a single display format.

@Marwes, have you thought about this problem? Is there an alternate approach you can suggest? Would you accept a patch for one of the final two proposed solutions?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions