mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 04:44:57 +00:00
Merge #5023
5023: Fix string literal inference in match r=flodiebold a=lnicola Fixes #5020 r? @flodiebold Co-authored-by: Laurențiu Nicola <lnicola@dend.ro>
This commit is contained in:
commit
dff62def2e
2 changed files with 77 additions and 13 deletions
|
@ -4,7 +4,7 @@ use std::iter::repeat;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
expr::{BindingAnnotation, Pat, PatId, RecordFieldPat},
|
expr::{BindingAnnotation, Expr, Literal, Pat, PatId, RecordFieldPat},
|
||||||
path::Path,
|
path::Path,
|
||||||
type_ref::Mutability,
|
type_ref::Mutability,
|
||||||
FieldId,
|
FieldId,
|
||||||
|
@ -90,18 +90,7 @@ impl<'a> InferenceContext<'a> {
|
||||||
) -> Ty {
|
) -> Ty {
|
||||||
let body = Arc::clone(&self.body); // avoid borrow checker problem
|
let body = Arc::clone(&self.body); // avoid borrow checker problem
|
||||||
|
|
||||||
let is_non_ref_pat = match &body[pat] {
|
if is_non_ref_pat(&body, pat) {
|
||||||
Pat::Tuple { .. }
|
|
||||||
| Pat::Or(..)
|
|
||||||
| Pat::TupleStruct { .. }
|
|
||||||
| Pat::Record { .. }
|
|
||||||
| Pat::Range { .. }
|
|
||||||
| Pat::Slice { .. } => true,
|
|
||||||
// FIXME: Path/Lit might actually evaluate to ref, but inference is unimplemented.
|
|
||||||
Pat::Path(..) | Pat::Lit(..) => true,
|
|
||||||
Pat::Wild | Pat::Bind { .. } | Pat::Ref { .. } | Pat::Missing => false,
|
|
||||||
};
|
|
||||||
if is_non_ref_pat {
|
|
||||||
while let Some((inner, mutability)) = expected.as_reference() {
|
while let Some((inner, mutability)) = expected.as_reference() {
|
||||||
expected = inner;
|
expected = inner;
|
||||||
default_bm = match default_bm {
|
default_bm = match default_bm {
|
||||||
|
@ -227,3 +216,21 @@ impl<'a> InferenceContext<'a> {
|
||||||
ty
|
ty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_non_ref_pat(body: &hir_def::body::Body, pat: PatId) -> bool {
|
||||||
|
match &body[pat] {
|
||||||
|
Pat::Tuple { .. }
|
||||||
|
| Pat::TupleStruct { .. }
|
||||||
|
| Pat::Record { .. }
|
||||||
|
| Pat::Range { .. }
|
||||||
|
| Pat::Slice { .. } => true,
|
||||||
|
Pat::Or(pats) => pats.iter().all(|p| is_non_ref_pat(body, *p)),
|
||||||
|
// FIXME: Path/Lit might actually evaluate to ref, but inference is unimplemented.
|
||||||
|
Pat::Path(..) => true,
|
||||||
|
Pat::Lit(expr) => match body[*expr] {
|
||||||
|
Expr::Literal(Literal::String(..)) => false,
|
||||||
|
_ => true,
|
||||||
|
},
|
||||||
|
Pat::Wild | Pat::Bind { .. } | Pat::Ref { .. } | Pat::Missing => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -270,6 +270,63 @@ fn test() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn infer_pattern_match_string_literal() {
|
||||||
|
assert_snapshot!(
|
||||||
|
infer_with_mismatches(r#"
|
||||||
|
fn test() {
|
||||||
|
let s: &str = "hello";
|
||||||
|
match s {
|
||||||
|
"hello" => {}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#, true),
|
||||||
|
@r###"
|
||||||
|
10..98 '{ ... } }': ()
|
||||||
|
20..21 's': &str
|
||||||
|
30..37 '"hello"': &str
|
||||||
|
43..96 'match ... }': ()
|
||||||
|
49..50 's': &str
|
||||||
|
61..68 '"hello"': &str
|
||||||
|
61..68 '"hello"': &str
|
||||||
|
72..74 '{}': ()
|
||||||
|
83..84 '_': &str
|
||||||
|
88..90 '{}': ()
|
||||||
|
"###
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn infer_pattern_match_or() {
|
||||||
|
assert_snapshot!(
|
||||||
|
infer_with_mismatches(r#"
|
||||||
|
fn test() {
|
||||||
|
let s: &str = "hello";
|
||||||
|
match s {
|
||||||
|
"hello" | "world" => {}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#, true),
|
||||||
|
@r###"
|
||||||
|
10..108 '{ ... } }': ()
|
||||||
|
20..21 's': &str
|
||||||
|
30..37 '"hello"': &str
|
||||||
|
43..106 'match ... }': ()
|
||||||
|
49..50 's': &str
|
||||||
|
61..68 '"hello"': &str
|
||||||
|
61..68 '"hello"': &str
|
||||||
|
61..78 '"hello...world"': &str
|
||||||
|
71..78 '"world"': &str
|
||||||
|
71..78 '"world"': &str
|
||||||
|
82..84 '{}': ()
|
||||||
|
93..94 '_': &str
|
||||||
|
98..100 '{}': ()
|
||||||
|
"###
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn infer_pattern_match_arr() {
|
fn infer_pattern_match_arr() {
|
||||||
assert_snapshot!(
|
assert_snapshot!(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue