I was gonna say no, but I came up with a way that might work for many cases (nightly-only):
#![feature(negative_impls)]
#![feature(auto_traits)]
fn test(x: &mut [i32; 10]) {
foo(|| {
let a = x[3];
})
}
fn foo(_: impl Foo) {}
auto trait Foo {}
impl<T: ?Sized> !Foo for &T {}
impl<T: ?Sized> !Foo for &mut T {}
error[E0277]: the trait bound `&[i32; 10]: Foo` is not satisfied in `[closure@src/lib.rs:5:9: 5:11]`
--> src/lib.rs:5:9
|
5 | foo(|| {
| --- ^-
| | |
| _____|___within this `[closure@src/lib.rs:5:9: 5:11]`
| | |
| | required by a bound introduced by this call
6 | | let a = x[3];
7 | | })
| |_____^ within `[closure@src/lib.rs:5:9: 5:11]`, the trait `Foo` is not implemented for `&[i32; 10]`
|
note: required because it's used within this closure
--> src/lib.rs:5:9
|
5 | foo(|| {
| ^^
note: required by a bound in `foo`
--> src/lib.rs:10:16
|
10 | fn foo(_: impl Foo) {}
| ^^^ required by this bound in `foo`
Note the lines
within `[closure@src/lib.rs:5:9: 5:11]`, the trait `Foo` is not implemented for `&[i32; 10]`
note: required because it's used within this closure
which basically tells you that the closure captures &[i32; 10]
. Different sets of negative impls (for the concrete types you think might be captured) can give you information about different non-reference types, too, and the error tends to keep being kinda clear about what the closure captures. E.g. using impl !Foo for [i32; 10] {}
instead of the two negative impls above would result in
error[E0277]: the trait bound `[i32; 10]: Foo` is not satisfied in `[closure@src/lib.rs:5:9: 5:11]`
--> src/lib.rs:5:9
|
5 | foo(|| {
| --- ^-
| | |
| _____|___within this `[closure@src/lib.rs:5:9: 5:11]`
| | |
| | required by a bound introduced by this call
6 | | let a = x[3];
7 | | })
| |_____^ within `[closure@src/lib.rs:5:9: 5:11]`, the trait `Foo` is not implemented for `[i32; 10]`
|
= note: required because it appears within the type `&[i32; 10]`
note: required because it's used within this closure
--> src/lib.rs:5:9
|
5 | foo(|| {
| ^^
note: required by a bound in `foo`
--> src/lib.rs:10:16
|
10 | fn foo(_: impl Foo) {}
| ^^^ required by this bound in `foo`
where the lines
within `[closure@src/lib.rs:5:9: 5:11]`, the trait `Foo` is not implemented for `[i32; 10]`
= note: required because it appears within the type `&[i32; 10]`
note: required because it's used within this closure
pretty much tell you that &[i32; 10]
is captured. It also talks about [i32; 10]
, too though, so there is some care needed in correctly reading these error messages, I guess.
Maybe someone else even knows a more straightforward approach.
If there isn’t any more straightforward way, maybe we should add one? The compiler certainly has the necessary information, so a “feature” to deliberately create a compilation error that reports accurately the types captured by a particular closure seems potentially quite useful, especially for learning purposes.