diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index d62ba9cf804eb..bc26c72a923eb 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -902,6 +902,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Type check the pattern. Override if necessary to avoid knock-on errors. self.check_pat_top(decl.pat, decl_ty, ty_span, origin_expr, Some(decl.origin)); + let mut pat_has_ref_binding = false; + decl.pat.walk_short(|pat| { + pat_has_ref_binding |= matches!( + pat.kind, + hir::PatKind::Binding(hir::BindingMode(hir::ByRef::Yes(..), _), ..) + ); + !pat_has_ref_binding + }); + if decl.ty.is_none() && pat_has_ref_binding { + self.register_wf_obligation( + decl_ty.into(), + decl.pat.span, + ObligationCauseCode::WellFormed(None), + ); + } let pat_ty = self.node_ty(decl.pat.hir_id); self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, pat_ty); diff --git a/tests/ui/wf/let-pat-inferred-non-wf.rs b/tests/ui/wf/let-pat-inferred-non-wf.rs new file mode 100644 index 0000000000000..89203a17e2e33 --- /dev/null +++ b/tests/ui/wf/let-pat-inferred-non-wf.rs @@ -0,0 +1,53 @@ +#![allow(unused)] + +struct S(T); + +fn should_fail_1() { + let ref y @ [ref x, _]; //~ ERROR E0277 + x = ""; +} + +fn should_fail_2() { + let [ref x]; //~ ERROR E0277 + x = ""; +} + +fn should_fail_3() { + let [[ref x], [_, y @ ..]]; //~ ERROR E0277 + x = ""; + y = []; +} + +fn should_fail_4() { + let [(ref a, b), x]; //~ ERROR E0277 + a = ""; + b = 5; +} + +fn should_fail_5() { + let (ref a, b); //~ ERROR E0277 + a = ""; + b = 5; +} + +fn should_fail_6() { + let [S(ref x)]; //~ ERROR E0277 + x = ""; +} + +fn should_pass_1() { + let ref x; + x = ""; +} + +fn should_pass_2() { + let ref y @ (ref x,); + x = ""; +} + +fn should_pass_3() { + let S(ref x); + x = ""; +} + +fn main() {} diff --git a/tests/ui/wf/let-pat-inferred-non-wf.stderr b/tests/ui/wf/let-pat-inferred-non-wf.stderr new file mode 100644 index 0000000000000..5d7d630a594ec --- /dev/null +++ b/tests/ui/wf/let-pat-inferred-non-wf.stderr @@ -0,0 +1,62 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/let-pat-inferred-non-wf.rs:6:9 + | +LL | let ref y @ [ref x, _]; + | ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: slice and array elements must have `Sized` type + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/let-pat-inferred-non-wf.rs:11:9 + | +LL | let [ref x]; + | ^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: slice and array elements must have `Sized` type + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/let-pat-inferred-non-wf.rs:16:9 + | +LL | let [[ref x], [_, y @ ..]]; + | ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: slice and array elements must have `Sized` type + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/let-pat-inferred-non-wf.rs:22:9 + | +LL | let [(ref a, b), x]; + | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: only the last element of a tuple may have a dynamically sized type + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/let-pat-inferred-non-wf.rs:28:9 + | +LL | let (ref a, b); + | ^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: only the last element of a tuple may have a dynamically sized type + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/let-pat-inferred-non-wf.rs:34:9 + | +LL | let [S(ref x)]; + | ^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `S`, the trait `Sized` is not implemented for `str` +note: required because it appears within the type `S` + --> $DIR/let-pat-inferred-non-wf.rs:3:8 + | +LL | struct S(T); + | ^ + = note: slice and array elements must have `Sized` type + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0277`.