owned this note
owned this note
Published
Linked with GitHub
# regressions for https://github.com/rust-lang/rust/pull/71896
Crater report: https://crater-reports.s3.amazonaws.com/pr-71896/index.html
## summary
| package | sound-ish? | trait |
| --- | --- | --- |
| ezksd | :x: | `dyn Parser<Input = X>`, but interacts with outlives
| rocket-rooms | :heavy_check_mark: | response::ResultFuture<'r>
| gribbet.rust_api_example | :heavy_check_mark: | ResultFuture<'static>
| mich101mich.game_rs | :heavy_check_mark: | Iterator
| spacemeowx2.slp-server-rust | :heavy_check_mark: | dyn Stream
| sstanfield.slsh | :heavy_check_mark: | dyn Iterator
| attr-1.0 | :shrug: | unclear
| dcmdump-0.1.0 | :shrug: | unclear
| dicom-object-0.1.0 | :shrug: | unclear, same as previous?
| happy-0.1.0 | :x: | `dyn Parser<Input = X>`, maybe interacts with outlives
| symbolic-debuginfo-7.3.0 | :heavy_check_mark: | `dyn Iterator` |
Key:
* :heavy_check_mark: -- "straightforwardly sound"
* :x: -- not sound
* :shrug: didn't quite figure it out yet
## ezksd.combinator.a2989e2e8fc92c9c8b1b4c949d9d8cc0b4de1986
This one is tricky. The actual interaction of subtyping is unsound. The code is
relying on `Box<dyn Parser<Input = &'static str>>` being a subtype of `Box<dyn
Parser<Input = &'a str>>`, which is incorrect, as `Self::Input` appears in a
*contravariant position*. In other words, effectively, given a fn that requires
`'static` inputs, we are "upcasting" it to a fn that takes any input.
However, the tricky bit is in the *reason* that a `Box<dyn Parser<Input = &'static str>>`
type is required in the first place. This comes about because there is a type like
so used in the `flat_map` combinator:
```
Box<dyn Parser<Input = &'a str, ...>>
```
The problem here is that there is an implicit bound of `Box<dyn Parser<..> +
'static>` going on. The underlying type in this case is something like
`Empty<&'? str>`, where the `'?` is an inference variable. Because of our
outlives rules, that `'?` gets inferred to `'static`. The clincher is that the
`Empty` types does't actually *contain* any data, it's just holding types. We
don't really have a good way to express this today given Rust's outlives rules.
Moreover, if we used the invariant rule that this PR puts in place, *but* we had better
outlives rules, then the code would be accepted.
## githubaccount624.rocket-rooms.181ae13300244f79e7295eff84b3d07f7b28bdd5
The actual error occurs in `rocket`, which is a dependency of `rocket-rooms`:
https://github.com/SergioBenitez/Rocket/blob/e7afd0d1f464b85392051be3a2f382185960ccb8/core/lib/src/response/responder.rs#L218
The relevant code is:
```rust
pub trait Responder<'r> {
fn respond_to(self, request: &'r Request<'_>) -> response::ResultFuture<'r>;
}
impl Responder<'_> for String {
fn respond_to(self, _: &Request<'_>) -> response::ResultFuture<'static> {
Box::pin(async move {
Response::build()
.header(ContentType::Plain)
.sized_body(Cursor::new(self))
.ok()
})
}
}
```
The subtyping is occuring in a covariant position (the return type), so accepting `response::ResultFuture<'static> <: response::ResultFuture<'r>` would be sound if we inferred the variance instead of using `Invariant`.
# gribbet.rust_api_example.6c2086f619b7e3f591cae6a7aa1deed91a504824
The errors are `ResultFuture<'static>` -- the associated type in future is an output that appears in covariant position.
# mich101mich.game_rs.f5e2796d3f8437e9630777e745ed7b8b2a513d30
`Box<dyn Iterator<Item = T>>`, as above
# spacemeowx2.slp-server-rust.2aaf02c7f0a352c6c826c45b6f12f5978604b089
Not a root regression, but related to `dyn futures::Stream<Item = GraphQLResponse<'a, S>`
Not a root regression, but it looks like *maybe* this comes from `Future`? Related to `juniper_subscriptions`
https://github.com/spacemeowx2/juniper/blob/95686b7ce530538d14bd42aafd47e07989dc9c2a/juniper_subscriptions/src/lib.rs#L149
[log](https://crater-reports.s3.amazonaws.com/pr-71896/try%2396b3c169cd2d8959926fa240f10342f1659f8ae3/gh/spacemeowx2.slp-server-rust/log.txt)
# sstanfield.slsh.b3068a910f91a5bd35b2e2b61a18b5ea18071785
` Box<dyn Iterator<Item = &Expression>>`
# attr-0.1.0
Not totally sure what's going on here but I *think* it's related to `Box<dyn Iterator<...>>` and the implicit `'static` bound. The error occurs in a test:
```
[INFO] [stderr] error[E0597]: `path` does not live long enough
[INFO] [stderr] --> tests/mapping.rs:197:18
[INFO] [stderr] |
[INFO] [stderr] 197 | let result = path.traverse(&top).unwrap().map(std::result::Result::unwrap).collect::<Vec<_>>();
[INFO] [stderr] | ^^^^---------------
[INFO] [stderr] | |
[INFO] [stderr] | borrowed value does not live long enough
[INFO] [stderr] | argument requires that `path` is borrowed for `'static`
[INFO] [stderr] 198 | assert_eq!(result, vec!["foo", "bla"]);
[INFO] [stderr] 199 | }
[INFO] [stderr] | - `path` dropped here while still borrowed
```
# dcmdump-0.1.0
Not very clear
```
[INFO] [stderr] error[E0310]: the parameter type `S` may not live long enough
[INFO] [stderr] --> /opt/rustwide/cargo-home/registry/src/github.com-1ecc6299db9ec823/dicom-object-0.1.0/src/mem.rs:183:18
[INFO] [stderr] |
[INFO] [stderr] 166 | pub fn from_reader_with_dict<S>(src: S, dict: D) -> Result<Self>
[INFO] [stderr] | - help: consider adding an explicit lifetime bound...: `S: 'static`
[INFO] [stderr] ...
[INFO] [stderr] 183 | obj: InMemDicomObject::build_object(&mut dataset, dict, false, Length::UNDEFINED)?,
[INFO] [stderr] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[INFO] [stderr] |
[INFO] [stderr] note: ...so that the type `std::io::BufReader<S>` will meet its required lifetime bounds
[INFO] [stderr] --> /opt/rustwide/cargo-home/registry/src/github.com-1ecc6299db9ec823/dicom-object-0.1.0/src/mem.rs:183:18
[INFO] [stderr] |
[INFO] [stderr] 183 | obj: InMemDicomObject::build_object(&mut dataset, dict, false, Length::UNDEFINED)?,
[INFO] [stderr] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[INFO] [stderr]
[INFO] [stderr] error: aborting due to previous error
```
# happy
really derives from a use of [combine](https://crates.io/crates/combine) v2.4.0:
```
[INFO] [stderr] error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
[INFO] [stderr] --> src/parse_route.rs:86:26
[INFO] [stderr] |
[INFO] [stderr] 86 | optional(token('/')).and(many1(segment())).map(|(_, v)| v).boxed()
[INFO] [stderr] | ^^^
[INFO] [stderr] |
[INFO] [stderr] note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 85:8...
[INFO] [stderr] --> src/parse_route.rs:85:8
[INFO] [stderr] |
[INFO] [stderr] 85 | fn url<'a>() -> Box<StrParser<'a, Vec<Segment>>> {
[INFO] [stderr] | ^^
```
```
type StrParser<'a, R> = combine::Parser<Output=R, Input=&'a str>;
```
looks unsound given [Parser trait](https://docs.rs/combine/2.4.0/combine/trait.Parser.html), possibly a similar pattern to the first
# symbolic-debuginfo-7.3.0
```
DynIterator<'_, Symbol<'_>>
```