diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index e06fab410c887..f3f07f860ef0d 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -1007,7 +1007,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // // then that's equivalent to there existing a LUB. let cause = self.pattern_cause(ti, span); - if let Err(err) = self.demand_suptype_with_origin(&cause, expected, pat_ty) { + if let Err(mut err) = self.demand_suptype_with_origin(&cause, expected, pat_ty) { + // If scrutinee is String and pattern is &str, suggest .as_str() + let expected = self.resolve_vars_with_obligations(expected); + if let ty::Adt(adt, _) = expected.kind() + && self.tcx.is_lang_item(adt.did(), LangItem::String) + && pat_ty.is_ref() + && pat_ty.peel_refs().is_str() + && let Some(origin_expr) = ti.origin_expr + { + err.span_suggestion( + origin_expr.span.shrink_to_hi(), + "consider converting the `String` to a `&str`", + ".as_str()", + Applicability::MachineApplicable, + ); + } err.emit(); } diff --git a/tests/ui/pattern/deref-patterns/needs-gate.stderr b/tests/ui/pattern/deref-patterns/needs-gate.stderr index edc70048ecf2f..e70c0ed609d1e 100644 --- a/tests/ui/pattern/deref-patterns/needs-gate.stderr +++ b/tests/ui/pattern/deref-patterns/needs-gate.stderr @@ -73,7 +73,9 @@ error[E0308]: mismatched types --> $DIR/needs-gate.rs:45:9 | LL | match "str".to_owned() { - | ---------------- this expression has type `String` + | ----------------- help: consider converting the `String` to a `&str`: `.as_str()` + | | + | this expression has type `String` LL | "str" => {} | ^^^^^ expected `String`, found `&str` diff --git a/tests/ui/pattern/string-match-as-str-suggestion.fixed b/tests/ui/pattern/string-match-as-str-suggestion.fixed new file mode 100644 index 0000000000000..620c35fb270cc --- /dev/null +++ b/tests/ui/pattern/string-match-as-str-suggestion.fixed @@ -0,0 +1,18 @@ +//@ run-rustfix + +fn main() { + let s = "yes".to_owned(); + + let _ = match s.as_str() { + "yes" => Some(true), + //~^ ERROR mismatched types + "no" => Some(false), + //~^ ERROR mismatched types + _ => None, + }; + + let s2 = String::from("hello"); + if let "hello" = s2.as_str() { + //~^ ERROR mismatched types + } +} diff --git a/tests/ui/pattern/string-match-as-str-suggestion.rs b/tests/ui/pattern/string-match-as-str-suggestion.rs new file mode 100644 index 0000000000000..5f319e417e4ef --- /dev/null +++ b/tests/ui/pattern/string-match-as-str-suggestion.rs @@ -0,0 +1,18 @@ +//@ run-rustfix + +fn main() { + let s = "yes".to_owned(); + + let _ = match s { + "yes" => Some(true), + //~^ ERROR mismatched types + "no" => Some(false), + //~^ ERROR mismatched types + _ => None, + }; + + let s2 = String::from("hello"); + if let "hello" = s2 { + //~^ ERROR mismatched types + } +} diff --git a/tests/ui/pattern/string-match-as-str-suggestion.stderr b/tests/ui/pattern/string-match-as-str-suggestion.stderr new file mode 100644 index 0000000000000..65800ceba8fb9 --- /dev/null +++ b/tests/ui/pattern/string-match-as-str-suggestion.stderr @@ -0,0 +1,33 @@ +error[E0308]: mismatched types + --> $DIR/string-match-as-str-suggestion.rs:7:9 + | +LL | let _ = match s { + | -- help: consider converting the `String` to a `&str`: `.as_str()` + | | + | this expression has type `String` +LL | "yes" => Some(true), + | ^^^^^ expected `String`, found `&str` + +error[E0308]: mismatched types + --> $DIR/string-match-as-str-suggestion.rs:9:9 + | +LL | let _ = match s { + | -- help: consider converting the `String` to a `&str`: `.as_str()` + | | + | this expression has type `String` +... +LL | "no" => Some(false), + | ^^^^ expected `String`, found `&str` + +error[E0308]: mismatched types + --> $DIR/string-match-as-str-suggestion.rs:15:12 + | +LL | if let "hello" = s2 { + | ^^^^^^^ --- help: consider converting the `String` to a `&str`: `.as_str()` + | | | + | | this expression has type `String` + | expected `String`, found `&str` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`.