]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #106360 - estebank:remove-borrow-suggestion, r=compiler-errors
authorMichael Goulet <michael@errs.io>
Thu, 12 Jan 2023 06:25:49 +0000 (22:25 -0800)
committerGitHub <noreply@github.com>
Thu, 12 Jan 2023 06:25:49 +0000 (22:25 -0800)
Tweak E0277 `&`-removal suggestions

Fix #64068, fix #84837.

17 files changed:
compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr
tests/ui/impl-trait/in-trait/issue-102140.stderr
tests/ui/kindck/kindck-copy.stderr
tests/ui/not-panic/not-panic-safe-4.stderr
tests/ui/not-panic/not-panic-safe.rs
tests/ui/not-panic/not-panic-safe.stderr
tests/ui/suggestions/suggest-remove-refs-1.stderr
tests/ui/suggestions/suggest-remove-refs-2.stderr
tests/ui/suggestions/suggest-remove-refs-3.stderr
tests/ui/suggestions/suggest-remove-refs-4.fixed [new file with mode: 0644]
tests/ui/suggestions/suggest-remove-refs-4.rs [new file with mode: 0644]
tests/ui/suggestions/suggest-remove-refs-4.stderr [new file with mode: 0644]
tests/ui/suggestions/suggest-remove-refs-5.fixed [new file with mode: 0644]
tests/ui/suggestions/suggest-remove-refs-5.rs [new file with mode: 0644]
tests/ui/suggestions/suggest-remove-refs-5.stderr [new file with mode: 0644]
tests/ui/typeck/issue-57404.stderr

index 48694bac3bca27b93981042263360784e78a2eab..c1a5c63c6e2be4588770cd984e0c6192200edb0f 100644 (file)
@@ -1361,57 +1361,117 @@ fn suggest_remove_reference(
         err: &mut Diagnostic,
         trait_pred: ty::PolyTraitPredicate<'tcx>,
     ) -> bool {
-        let span = obligation.cause.span;
+        let mut span = obligation.cause.span;
+        let mut trait_pred = trait_pred;
+        let mut code = obligation.cause.code();
+        while let Some((c, Some(parent_trait_pred))) = code.parent() {
+            // We want the root obligation, in order to detect properly handle
+            // `for _ in &mut &mut vec![] {}`.
+            code = c;
+            trait_pred = parent_trait_pred;
+        }
+        while span.desugaring_kind().is_some() {
+            // Remove all the hir desugaring contexts while maintaining the macro contexts.
+            span.remove_mark();
+        }
+        let mut expr_finder = super::FindExprBySpan::new(span);
+        let Some(hir::Node::Expr(body)) = self.tcx.hir().find(obligation.cause.body_id) else {
+            return false;
+        };
+        expr_finder.visit_expr(&body);
+        let mut maybe_suggest = |suggested_ty, count, suggestions| {
+            // Remapping bound vars here
+            let trait_pred_and_suggested_ty =
+                trait_pred.map_bound(|trait_pred| (trait_pred, suggested_ty));
+
+            let new_obligation = self.mk_trait_obligation_with_new_self_ty(
+                obligation.param_env,
+                trait_pred_and_suggested_ty,
+            );
 
-        let mut suggested = false;
-        if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
-            let refs_number =
-                snippet.chars().filter(|c| !c.is_whitespace()).take_while(|c| *c == '&').count();
-            if let Some('\'') = snippet.chars().filter(|c| !c.is_whitespace()).nth(refs_number) {
-                // Do not suggest removal of borrow from type arguments.
-                return false;
+            if self.predicate_may_hold(&new_obligation) {
+                let msg = if count == 1 {
+                    "consider removing the leading `&`-reference".to_string()
+                } else {
+                    format!("consider removing {count} leading `&`-references")
+                };
+
+                err.multipart_suggestion_verbose(
+                    &msg,
+                    suggestions,
+                    Applicability::MachineApplicable,
+                );
+                true
+            } else {
+                false
             }
+        };
 
-            // Skipping binder here, remapping below
-            let mut suggested_ty = trait_pred.self_ty().skip_binder();
+        // Maybe suggest removal of borrows from types in type parameters, like in
+        // `src/test/ui/not-panic/not-panic-safe.rs`.
+        let mut count = 0;
+        let mut suggestions = vec![];
+        // Skipping binder here, remapping below
+        let mut suggested_ty = trait_pred.self_ty().skip_binder();
+        if let Some(mut hir_ty) = expr_finder.ty_result {
+            while let hir::TyKind::Ref(_, mut_ty) = &hir_ty.kind {
+                count += 1;
+                let span = hir_ty.span.until(mut_ty.ty.span);
+                suggestions.push((span, String::new()));
 
-            for refs_remaining in 0..refs_number {
                 let ty::Ref(_, inner_ty, _) = suggested_ty.kind() else {
                     break;
                 };
                 suggested_ty = *inner_ty;
 
-                // Remapping bound vars here
-                let trait_pred_and_suggested_ty =
-                    trait_pred.map_bound(|trait_pred| (trait_pred, suggested_ty));
+                hir_ty = mut_ty.ty;
 
-                let new_obligation = self.mk_trait_obligation_with_new_self_ty(
-                    obligation.param_env,
-                    trait_pred_and_suggested_ty,
-                );
+                if maybe_suggest(suggested_ty, count, suggestions.clone()) {
+                    return true;
+                }
+            }
+        }
 
-                if self.predicate_may_hold(&new_obligation) {
-                    let sp = self
-                        .tcx
-                        .sess
-                        .source_map()
-                        .span_take_while(span, |c| c.is_whitespace() || *c == '&');
+        // Maybe suggest removal of borrows from expressions, like in `for i in &&&foo {}`.
+        let Some(mut expr) = expr_finder.result else { return false; };
+        let mut count = 0;
+        let mut suggestions = vec![];
+        // Skipping binder here, remapping below
+        let mut suggested_ty = trait_pred.self_ty().skip_binder();
+        'outer: loop {
+            while let hir::ExprKind::AddrOf(_, _, borrowed) = expr.kind {
+                count += 1;
+                let span = if expr.span.eq_ctxt(borrowed.span) {
+                    expr.span.until(borrowed.span)
+                } else {
+                    expr.span.with_hi(expr.span.lo() + BytePos(1))
+                };
+                suggestions.push((span, String::new()));
 
-                    let remove_refs = refs_remaining + 1;
+                let ty::Ref(_, inner_ty, _) = suggested_ty.kind() else {
+                    break 'outer;
+                };
+                suggested_ty = *inner_ty;
 
-                    let msg = if remove_refs == 1 {
-                        "consider removing the leading `&`-reference".to_string()
-                    } else {
-                        format!("consider removing {} leading `&`-references", remove_refs)
-                    };
+                expr = borrowed;
 
-                    err.span_suggestion_short(sp, &msg, "", Applicability::MachineApplicable);
-                    suggested = true;
-                    break;
+                if maybe_suggest(suggested_ty, count, suggestions.clone()) {
+                    return true;
                 }
             }
+            if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
+                && let hir::def::Res::Local(hir_id) = path.res
+                && let Some(hir::Node::Pat(binding)) = self.tcx.hir().find(hir_id)
+                && let Some(hir::Node::Local(local)) = self.tcx.hir().find_parent(binding.hir_id)
+                && let None = local.ty
+                && let Some(binding_expr) = local.init
+            {
+                expr = binding_expr;
+            } else {
+                break 'outer;
+            }
         }
-        suggested
+        false
     }
 
     fn suggest_remove_await(&self, obligation: &PredicateObligation<'tcx>, err: &mut Diagnostic) {
index 9aae9013d1b040e20391a4158d19229eb724d262..bd7aaf6fb6dfcdbca247abc193101635b698f8e0 100644 (file)
@@ -4,7 +4,6 @@ error[E0277]: the trait bound `u32: Signed` is not satisfied
 LL |     is_defaulted::<&'static u32>();
    |                    ^^^^^^^^^^^^ the trait `Signed` is not implemented for `u32`
    |
-   = help: the trait `Signed` is implemented for `i32`
 note: required for `&'static u32` to implement `Defaulted`
   --> $DIR/typeck-default-trait-impl-precedence.rs:10:19
    |
@@ -17,6 +16,11 @@ note: required by a bound in `is_defaulted`
    |
 LL | fn is_defaulted<T:Defaulted>() { }
    |                   ^^^^^^^^^ required by this bound in `is_defaulted`
+help: consider removing the leading `&`-reference
+   |
+LL -     is_defaulted::<&'static u32>();
+LL +     is_defaulted::<u32>();
+   |
 
 error: aborting due to previous error
 
index 08602185f50cacb887f5d7d326e9103d47a0358f..18bb63745d7a5f12354106e58fba0b624dc47569 100644 (file)
@@ -2,11 +2,15 @@ error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied
   --> $DIR/issue-102140.rs:23:22
    |
 LL |         MyTrait::foo(&self)
-   |         ------------ -^^^^
-   |         |            |
-   |         |            the trait `MyTrait` is not implemented for `&dyn MyTrait`
-   |         |            help: consider removing the leading `&`-reference
+   |         ------------ ^^^^^ the trait `MyTrait` is not implemented for `&dyn MyTrait`
+   |         |
    |         required by a bound introduced by this call
+   |
+help: consider removing the leading `&`-reference
+   |
+LL -         MyTrait::foo(&self)
+LL +         MyTrait::foo(self)
+   |
 
 error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied
   --> $DIR/issue-102140.rs:23:9
index 9af89159a8cfcec0f98cf91bcbbff4f358b7e34d..aee2aa98a60c20a5e75257313d5e2e35e67089e1 100644 (file)
@@ -4,12 +4,16 @@ error[E0277]: the trait bound `&'static mut isize: Copy` is not satisfied
 LL |     assert_copy::<&'static mut isize>();
    |                   ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `&'static mut isize`
    |
-   = help: the trait `Copy` is implemented for `isize`
 note: required by a bound in `assert_copy`
   --> $DIR/kindck-copy.rs:5:18
    |
 LL | fn assert_copy<T:Copy>() { }
    |                  ^^^^ required by this bound in `assert_copy`
+help: consider removing the leading `&`-reference
+   |
+LL -     assert_copy::<&'static mut isize>();
+LL +     assert_copy::<isize>();
+   |
 
 error[E0277]: the trait bound `&'a mut isize: Copy` is not satisfied
   --> $DIR/kindck-copy.rs:28:19
@@ -17,12 +21,16 @@ error[E0277]: the trait bound `&'a mut isize: Copy` is not satisfied
 LL |     assert_copy::<&'a mut isize>();
    |                   ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `&'a mut isize`
    |
-   = help: the trait `Copy` is implemented for `isize`
 note: required by a bound in `assert_copy`
   --> $DIR/kindck-copy.rs:5:18
    |
 LL | fn assert_copy<T:Copy>() { }
    |                  ^^^^ required by this bound in `assert_copy`
+help: consider removing the leading `&`-reference
+   |
+LL -     assert_copy::<&'a mut isize>();
+LL +     assert_copy::<isize>();
+   |
 
 error[E0277]: the trait bound `Box<isize>: Copy` is not satisfied
   --> $DIR/kindck-copy.rs:31:19
index fc1c594d0d422041ec99e62e30ca70c5c28600ee..9428c125651ec2f718e315ee34965df117a27707 100644 (file)
@@ -12,6 +12,11 @@ note: required by a bound in `assert`
    |
 LL | fn assert<T: UnwindSafe + ?Sized>() {}
    |              ^^^^^^^^^^ required by this bound in `assert`
+help: consider removing the leading `&`-reference
+   |
+LL -     assert::<&RefCell<i32>>();
+LL +     assert::<RefCell<i32>>();
+   |
 
 error[E0277]: the type `UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
   --> $DIR/not-panic-safe-4.rs:9:14
@@ -28,6 +33,11 @@ note: required by a bound in `assert`
    |
 LL | fn assert<T: UnwindSafe + ?Sized>() {}
    |              ^^^^^^^^^^ required by this bound in `assert`
+help: consider removing the leading `&`-reference
+   |
+LL -     assert::<&RefCell<i32>>();
+LL +     assert::<RefCell<i32>>();
+   |
 
 error: aborting due to 2 previous errors
 
index 4165c5dc13aaae07bdc05a6ed1c4cd75d78d56df..1b3c6482ce94fab0607258c3e24d96aa8caf48dc 100644 (file)
@@ -5,6 +5,6 @@
 fn assert<T: UnwindSafe + ?Sized>() {}
 
 fn main() {
-    assert::<&mut i32>();
-    //~^ ERROR the type `&mut i32` may not be safely transferred across an unwind boundary
+    assert::<&mut &mut &i32>();
+    //~^ ERROR the type `&mut &mut &i32` may not be safely transferred across an unwind boundary
 }
index 2cd51a439988db0102d10499e56f5e6aad70064b..37a6aee390669c70536d0791887bf53921bc4f55 100644 (file)
@@ -1,19 +1,21 @@
-error[E0277]: the type `&mut i32` may not be safely transferred across an unwind boundary
+error[E0277]: the type `&mut &mut &i32` may not be safely transferred across an unwind boundary
   --> $DIR/not-panic-safe.rs:8:14
    |
-LL |     assert::<&mut i32>();
-   |              -^^^^^^^
-   |              |
-   |              `&mut i32` may not be safely transferred across an unwind boundary
-   |              help: consider removing the leading `&`-reference
+LL |     assert::<&mut &mut &i32>();
+   |              ^^^^^^^^^^^^^^ `&mut &mut &i32` may not be safely transferred across an unwind boundary
    |
-   = help: the trait `UnwindSafe` is not implemented for `&mut i32`
-   = note: `UnwindSafe` is implemented for `&i32`, but not for `&mut i32`
+   = help: the trait `UnwindSafe` is not implemented for `&mut &mut &i32`
+   = note: `UnwindSafe` is implemented for `&&mut &i32`, but not for `&mut &mut &i32`
 note: required by a bound in `assert`
   --> $DIR/not-panic-safe.rs:5:14
    |
 LL | fn assert<T: UnwindSafe + ?Sized>() {}
    |              ^^^^^^^^^^ required by this bound in `assert`
+help: consider removing 2 leading `&`-references
+   |
+LL -     assert::<&mut &mut &i32>();
+LL +     assert::<&i32>();
+   |
 
 error: aborting due to previous error
 
index 1a843f3f5097bf387b8bb88f507843c4db96f926..387770535f689b8a7f3c7481cf6779f046fcac96 100644 (file)
@@ -2,13 +2,15 @@ error[E0277]: `&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
   --> $DIR/suggest-remove-refs-1.rs:6:19
    |
 LL |     for (i, _) in &v.iter().enumerate() {
-   |                   -^^^^^^^^^^^^^^^^^^^^
-   |                   |
-   |                   `&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
-   |                   help: consider removing the leading `&`-reference
+   |                   ^^^^^^^^^^^^^^^^^^^^^ `&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `&Enumerate<std::slice::Iter<'_, {integer}>>`
    = note: required for `&Enumerate<std::slice::Iter<'_, {integer}>>` to implement `IntoIterator`
+help: consider removing the leading `&`-reference
+   |
+LL -     for (i, _) in &v.iter().enumerate() {
+LL +     for (i, _) in v.iter().enumerate() {
+   |
 
 error: aborting due to previous error
 
index f39361d529fbf97d53c5a3a90a69a2015e238e3b..1632b2abb2f87fb76f8f2c5fa6e63e63304401b4 100644 (file)
@@ -2,13 +2,15 @@ error[E0277]: `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterat
   --> $DIR/suggest-remove-refs-2.rs:6:19
    |
 LL |     for (i, _) in & & & & &v.iter().enumerate() {
-   |                   ---------^^^^^^^^^^^^^^^^^^^^
-   |                   |
-   |                   `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
-   |                   help: consider removing 5 leading `&`-references
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>`
    = note: required for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` to implement `IntoIterator`
+help: consider removing 5 leading `&`-references
+   |
+LL -     for (i, _) in & & & & &v.iter().enumerate() {
+LL +     for (i, _) in v.iter().enumerate() {
+   |
 
 error: aborting due to previous error
 
index 31cca323d0e4226e578b79216ce8637a7bc36fa1..7bf421a7729dfb88253c61ffa0271ad04599a987 100644 (file)
@@ -1,18 +1,20 @@
 error[E0277]: `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
   --> $DIR/suggest-remove-refs-3.rs:6:19
    |
-LL |        for (i, _) in & & &
-   |  ____________________^
-   | | ___________________|
-   | ||
-LL | ||         & &v
-   | ||___________- help: consider removing 5 leading `&`-references
-LL | |          .iter()
-LL | |          .enumerate() {
-   | |_____________________^ `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
+LL |       for (i, _) in & & &
+   |  ___________________^
+LL | |         & &v
+LL | |         .iter()
+LL | |         .enumerate() {
+   | |____________________^ `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>`
    = note: required for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` to implement `IntoIterator`
+help: consider removing 5 leading `&`-references
+   |
+LL -     for (i, _) in & & &
+LL +     for (i, _) in v
+   |
 
 error: aborting due to previous error
 
diff --git a/tests/ui/suggestions/suggest-remove-refs-4.fixed b/tests/ui/suggestions/suggest-remove-refs-4.fixed
new file mode 100644 (file)
index 0000000..dd63d21
--- /dev/null
@@ -0,0 +1,5 @@
+// run-rustfix
+fn main() {
+    let foo = [1,2,3].iter();
+    for _i in foo {} //~ ERROR E0277
+}
diff --git a/tests/ui/suggestions/suggest-remove-refs-4.rs b/tests/ui/suggestions/suggest-remove-refs-4.rs
new file mode 100644 (file)
index 0000000..3c3d9b1
--- /dev/null
@@ -0,0 +1,5 @@
+// run-rustfix
+fn main() {
+    let foo = &[1,2,3].iter();
+    for _i in &foo {} //~ ERROR E0277
+}
diff --git a/tests/ui/suggestions/suggest-remove-refs-4.stderr b/tests/ui/suggestions/suggest-remove-refs-4.stderr
new file mode 100644 (file)
index 0000000..e4ad17e
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0277]: `&&std::slice::Iter<'_, {integer}>` is not an iterator
+  --> $DIR/suggest-remove-refs-4.rs:4:15
+   |
+LL |     for _i in &foo {}
+   |               ^^^^ `&&std::slice::Iter<'_, {integer}>` is not an iterator
+   |
+   = help: the trait `Iterator` is not implemented for `&&std::slice::Iter<'_, {integer}>`
+   = note: required for `&&std::slice::Iter<'_, {integer}>` to implement `IntoIterator`
+help: consider removing 2 leading `&`-references
+   |
+LL ~     let foo = [1,2,3].iter();
+LL ~     for _i in foo {}
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/suggest-remove-refs-5.fixed b/tests/ui/suggestions/suggest-remove-refs-5.fixed
new file mode 100644 (file)
index 0000000..9f59f9c
--- /dev/null
@@ -0,0 +1,8 @@
+// run-rustfix
+fn main() {
+    let v = &mut Vec::<i32>::new();
+    for _ in v {} //~ ERROR E0277
+
+    let v = &mut [1u8];
+    for _ in v {} //~ ERROR E0277
+}
diff --git a/tests/ui/suggestions/suggest-remove-refs-5.rs b/tests/ui/suggestions/suggest-remove-refs-5.rs
new file mode 100644 (file)
index 0000000..d56aa0c
--- /dev/null
@@ -0,0 +1,8 @@
+// run-rustfix
+fn main() {
+    let v = &mut &mut Vec::<i32>::new();
+    for _ in &mut &mut v {} //~ ERROR E0277
+
+    let v = &mut &mut [1u8];
+    for _ in &mut v {} //~ ERROR E0277
+}
diff --git a/tests/ui/suggestions/suggest-remove-refs-5.stderr b/tests/ui/suggestions/suggest-remove-refs-5.stderr
new file mode 100644 (file)
index 0000000..7de84d6
--- /dev/null
@@ -0,0 +1,37 @@
+error[E0277]: `Vec<i32>` is not an iterator
+  --> $DIR/suggest-remove-refs-5.rs:4:14
+   |
+LL |     for _ in &mut &mut v {}
+   |              ^^^^^^^^^^^ `Vec<i32>` is not an iterator; try calling `.into_iter()` or `.iter()`
+   |
+   = help: the trait `Iterator` is not implemented for `Vec<i32>`
+   = note: required for `&mut Vec<i32>` to implement `Iterator`
+   = note: 3 redundant requirements hidden
+   = note: required for `&mut &mut &mut &mut Vec<i32>` to implement `Iterator`
+   = note: required for `&mut &mut &mut &mut Vec<i32>` to implement `IntoIterator`
+help: consider removing 3 leading `&`-references
+   |
+LL ~     let v = &mut Vec::<i32>::new();
+LL ~     for _ in v {}
+   |
+
+error[E0277]: `[u8; 1]` is not an iterator
+  --> $DIR/suggest-remove-refs-5.rs:7:14
+   |
+LL |     for _ in &mut v {}
+   |              ^^^^^^ `[u8; 1]` is not an iterator; try calling `.into_iter()` or `.iter()`
+   |
+   = help: the trait `Iterator` is not implemented for `[u8; 1]`
+   = note: required for `&mut [u8; 1]` to implement `Iterator`
+   = note: 2 redundant requirements hidden
+   = note: required for `&mut &mut &mut [u8; 1]` to implement `Iterator`
+   = note: required for `&mut &mut &mut [u8; 1]` to implement `IntoIterator`
+help: consider removing 2 leading `&`-references
+   |
+LL ~     let v = &mut [1u8];
+LL ~     for _ in v {}
+   |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
index 5065ac32ad2b013e94adda0b90e7c6b52224a27b..a631dbb39fb8fa59ebfb9cf13e120d8f7b463bb0 100644 (file)
@@ -2,14 +2,17 @@ error[E0277]: `&mut ()` is not a tuple
   --> $DIR/issue-57404.rs:6:41
    |
 LL |     handlers.unwrap().as_mut().call_mut(&mut ());
-   |                                -------- -^^^^^^
-   |                                |        |
-   |                                |        the trait `Tuple` is not implemented for `&mut ()`
-   |                                |        help: consider removing the leading `&`-reference
+   |                                -------- ^^^^^^^ the trait `Tuple` is not implemented for `&mut ()`
+   |                                |
    |                                required by a bound introduced by this call
    |
 note: required by a bound in `call_mut`
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
+help: consider removing the leading `&`-reference
+   |
+LL -     handlers.unwrap().as_mut().call_mut(&mut ());
+LL +     handlers.unwrap().as_mut().call_mut(());
+   |
 
 error: aborting due to previous error