diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index d7f15222376c8..3d36a3513b2bb 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -1352,7 +1352,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } /// Precondition: pat is a `Ref(_)` pattern - // FIXME(pin_ergonomics): add suggestions for `&pin mut` or `&pin const` patterns fn borrow_pat_suggestion(&self, err: &mut Diag<'_>, pat: &Pat<'_>) { let tcx = self.tcx; if let PatKind::Ref(inner, pinned, mutbl) = pat.kind @@ -1407,6 +1406,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; match binding_parent { + hir::Node::Param(hir::Param { ty_span, pat, .. }) + if pat.span != *ty_span + && pinned.is_pinned() + && !tcx.features().pin_ergonomics() => + { + // FIXME(pin_ergonomics): Once `pin_ergonomics` is stabilized, remove this + // gate and allow the pinned reference type-position suggestion unconditionally. + } // Check that there is explicit type (ie this is not a closure param with inferred type) // so we don't suggest moving something to the type that does not exist hir::Node::Param(hir::Param { ty_span, pat, .. }) if pat.span != *ty_span => { @@ -1414,7 +1421,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { format!("to take parameter `{binding}` by reference, move `&{pin_and_mut}` to the type"), vec![ (pat.span.until(inner.span), "".to_owned()), - (ty_span.shrink_to_lo(), mutbl.ref_prefix_str().to_owned()), + (ty_span.shrink_to_lo(), format!("&{}", pinned.prefix_str(mutbl))), ], Applicability::MachineApplicable ); diff --git a/tests/ui/pin-ergonomics/ref-pat-suggestions.fixed b/tests/ui/pin-ergonomics/ref-pat-suggestions.fixed new file mode 100644 index 0000000000000..9fa71f05b125a --- /dev/null +++ b/tests/ui/pin-ergonomics/ref-pat-suggestions.fixed @@ -0,0 +1,12 @@ +//@ run-rustfix + +#![feature(pin_ergonomics)] +#![allow(unused)] + +fn pin_mut_param(x: &pin mut i32) {} +//~^ ERROR mismatched types + +fn pin_const_param(x: &pin const i32) {} +//~^ ERROR mismatched types + +fn main() {} diff --git a/tests/ui/pin-ergonomics/ref-pat-suggestions.rs b/tests/ui/pin-ergonomics/ref-pat-suggestions.rs new file mode 100644 index 0000000000000..1022f7762816d --- /dev/null +++ b/tests/ui/pin-ergonomics/ref-pat-suggestions.rs @@ -0,0 +1,12 @@ +//@ run-rustfix + +#![feature(pin_ergonomics)] +#![allow(unused)] + +fn pin_mut_param(&pin mut x: i32) {} +//~^ ERROR mismatched types + +fn pin_const_param(&pin const x: i32) {} +//~^ ERROR mismatched types + +fn main() {} diff --git a/tests/ui/pin-ergonomics/ref-pat-suggestions.stderr b/tests/ui/pin-ergonomics/ref-pat-suggestions.stderr new file mode 100644 index 0000000000000..f966b214c24c1 --- /dev/null +++ b/tests/ui/pin-ergonomics/ref-pat-suggestions.stderr @@ -0,0 +1,40 @@ +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:6:18 + | +LL | fn pin_mut_param(&pin mut x: i32) {} + | ^^^^^^^^^^ --- expected due to this + | | + | expected `i32`, found `Pin<&mut _>` + | + = note: expected type `i32` + found struct `Pin<&mut _>` +note: to declare a mutable parameter use: `mut x` + --> $DIR/ref-pat-suggestions.rs:6:18 + | +LL | fn pin_mut_param(&pin mut x: i32) {} + | ^^^^^^^^^^ +help: to take parameter `x` by reference, move `&pin mut` to the type + | +LL - fn pin_mut_param(&pin mut x: i32) {} +LL + fn pin_mut_param(x: &pin mut i32) {} + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:9:20 + | +LL | fn pin_const_param(&pin const x: i32) {} + | ^^^^^^^^^^^^ --- expected due to this + | | + | expected `i32`, found `Pin<&_>` + | + = note: expected type `i32` + found struct `Pin<&_>` +help: to take parameter `x` by reference, move `&pin const` to the type + | +LL - fn pin_const_param(&pin const x: i32) {} +LL + fn pin_const_param(x: &pin const i32) {} + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`.