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
@ -4,7 +4,7 @@ use std::iter::repeat;
|
||||
use std::sync::Arc;
|
||||
|
||||
use hir_def::{
|
||||
expr::{BindingAnnotation, Pat, PatId, RecordFieldPat},
|
||||
expr::{BindingAnnotation, Expr, Literal, Pat, PatId, RecordFieldPat},
|
||||
path::Path,
|
||||
type_ref::Mutability,
|
||||
FieldId,
|
||||
@ -90,18 +90,7 @@ impl<'a> InferenceContext<'a> {
|
||||
) -> Ty {
|
||||
let body = Arc::clone(&self.body); // avoid borrow checker problem
|
||||
|
||||
let is_non_ref_pat = match &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 {
|
||||
if is_non_ref_pat(&body, pat) {
|
||||
while let Some((inner, mutability)) = expected.as_reference() {
|
||||
expected = inner;
|
||||
default_bm = match default_bm {
|
||||
@ -227,3 +216,21 @@ impl<'a> InferenceContext<'a> {
|
||||
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]
|
||||
fn infer_pattern_match_arr() {
|
||||
assert_snapshot!(
|
||||
|
Loading…
x
Reference in New Issue
Block a user