Skip to content

Using map_err on a SelectorErrorKind error results in a panic #212

@fgimian

Description

@fgimian

Hey there, absolutely love your work on this library!

Unfortunately, the way that the SelectorErrorKind error behaves is a bit unusual.

use anyhow::anyhow;
use scraper::Selector;

fn main() {
    let selector_result = Selector::parse("div138293@!#@!!@#").map_err(|e| anyhow!("oh no: {e}"));
    println!("====> {:?}", selector_result);
}

The following code panics instead of gracefully printing the result via println!.

thread 'main' panicked at C:\Users\Fots\.cargo\registry\src\index.crates.io-6f17d22bba15001f\scraper-0.20.0\src\error\utils.rs:56:18:
Token Delim('@') is not supposed to match as a single-character token!
stack backtrace:
   0: std::panicking::begin_panic_handler
             at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14\library/std\src\panicking.rs:662
   1: core::panicking::panic_fmt
             at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14\library/core\src\panicking.rs:74
   2: scraper::error::utils::render_single_char_token
             at C:\Users\Fots\.cargo\registry\src\index.crates.io-6f17d22bba15001f\scraper-0.20.0\src\error\utils.rs:56
   3: scraper::error::utils::render_token
             at C:\Users\Fots\.cargo\registry\src\index.crates.io-6f17d22bba15001f\scraper-0.20.0\src\error\utils.rs:34
   4: scraper::error::impl$3::fmt
             at C:\Users\Fots\.cargo\registry\src\index.crates.io-6f17d22bba15001f\scraper-0.20.0\src\error.rs:83
   5: core::fmt::rt::Argument::fmt
             at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14\library/core\src\fmt\rt.rs:177
   6: core::fmt::write
             at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14\library/core\src\fmt\mod.rs:1178
   7: core::fmt::Write::write_fmt::impl$1::spec_write_fmt
             at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14\library/core\src\fmt\mod.rs:226
   8: core::fmt::Write::write_fmt
             at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14\library/core\src\fmt\mod.rs:231
   9: alloc::fmt::format::format_inner
             at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14\library/alloc\src\fmt.rs:637
  10: alloc::fmt::format::closure$0
             at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14\library\alloc\src\fmt.rs:642
  11: enum2$<core::option::Option<ref$<str$> > >::map_or_else<ref$<str$>,alloc::string::String,alloc::fmt::format::closure_env$0,alloc::string::String (*)(ref$<str$>)>
             at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14\library\core\src\option.rs:1211
  12: alloc::fmt::format
             at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14\library\alloc\src\fmt.rs:642
  13: anyhow::__private::format_err
             at C:\Users\Fots\.cargo\registry\src\index.crates.io-6f17d22bba15001f\anyhow-1.0.89\src\lib.rs:693
  14: ableton_downloads::main::closure$0
             at .\src\main.rs:5
  15: enum2$<core::result::Result<scraper::selector::Selector,enum2$<scraper::error::SelectorErrorKind> > >::map_err<scraper::selector::Selector,enum2$<scraper::error::SelectorErrorKind>,anyhow::Error,ableton_downloads::main::closure_env$0>
             at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14\library\core\src\result.rs:854
  16: ableton_downloads::main
             at .\src\main.rs:5
  17: core::ops::function::FnOnce::call_once<void (*)(),tuple$<> >
             at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14\library\core\src\ops\function.rs:250
  18: core::hint::black_box
             at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14\library\core\src\hint.rs:388
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

The panic is found at https://github.com/rust-scraper/scraper/blob/master/scraper/src/error/utils.rs#L56.

Just as a bonus, it also is impossible to use the .context or .with_context anyhow methods to add context to this error enum due to the following trait bounds not being met.

e.g.

let selector_result = Selector::parse("div138293@!#@!!@#").context("unable to parse selector");

Results in the following:

error[E0599]: the method `context` exists for enum `Result<Selector, SelectorErrorKind<'_>>`, but its trait bounds were not satisfied
   --> src/main.rs:5:64
    |
5   |     let selector_result = Selector::parse("div138293@!#@!!@#").context("unable to parse selector");
    |                                                                ^^^^^^^ method cannot be called on `Result<Selector, SelectorErrorKind<'_>>` due to unsatisfied trait bounds
    |
   ::: C:\Users\Fots\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib/rustlib/src/rust\library\core\src\result.rs:527:1
    |
527 | pub enum Result<T, E> {
    | --------------------- doesn't satisfy `_: Context<Selector, SelectorErrorKind<'_>>`
    |
   ::: C:\Users\Fots\.cargo\registry\src\index.crates.io-6f17d22bba15001f\scraper-0.20.0\src\error.rs:13:1
    |
13  | pub enum SelectorErrorKind<'a> {
    | ------------------------------ doesn't satisfy `SelectorErrorKind<'_>: Send`, `SelectorErrorKind<'_>: Sync` or `_: StdError`
    |
    = note: the following trait bounds were not satisfied:
            `SelectorErrorKind<'_>: anyhow::context::ext::StdError`
            which is required by `Result<Selector, SelectorErrorKind<'_>>: anyhow::Context<Selector, SelectorErrorKind<'_>>`
            `SelectorErrorKind<'_>: Send`
            which is required by `Result<Selector, SelectorErrorKind<'_>>: anyhow::Context<Selector, SelectorErrorKind<'_>>`
            `SelectorErrorKind<'_>: Sync`
            which is required by `Result<Selector, SelectorErrorKind<'_>>: anyhow::Context<Selector, SelectorErrorKind<'_>>`

As per the output, I'm testing on Windows using the MSVC Rust toolchain.

Thanks heaps in advance! 😄
Fotis

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions