mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-09 05:23:07 +00:00
internal: Record mismatches of pattern types.
This commit is contained in:
parent
49a5d6a8d4
commit
472317c008
@ -211,7 +211,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
|
||||
|
||||
// FIXME: Due to shortcomings in the current type system implementation, only emit this
|
||||
// diagnostic if there are no type mismatches in the containing function.
|
||||
if self.infer.type_mismatches.iter().next().is_some() {
|
||||
if self.infer.expr_type_mismatches().next().is_some() {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -137,8 +137,12 @@ pub struct InferenceResult {
|
||||
assoc_resolutions: FxHashMap<ExprOrPatId, AssocItemId>,
|
||||
diagnostics: Vec<InferenceDiagnostic>,
|
||||
pub type_of_expr: ArenaMap<ExprId, Ty>,
|
||||
/// For each pattern record the type it resolves to.
|
||||
///
|
||||
/// **Note**: When a pattern type is resolved it may still contain
|
||||
/// unresolved or missing subpatterns or subpatterns of mismatched types.
|
||||
pub type_of_pat: ArenaMap<PatId, Ty>,
|
||||
pub(super) type_mismatches: ArenaMap<ExprId, TypeMismatch>,
|
||||
type_mismatches: FxHashMap<ExprOrPatId, TypeMismatch>,
|
||||
/// Interned Unknown to return references to.
|
||||
standard_types: InternedStandardTypes,
|
||||
}
|
||||
@ -163,7 +167,22 @@ impl InferenceResult {
|
||||
self.assoc_resolutions.get(&id.into()).copied()
|
||||
}
|
||||
pub fn type_mismatch_for_expr(&self, expr: ExprId) -> Option<&TypeMismatch> {
|
||||
self.type_mismatches.get(expr)
|
||||
self.type_mismatches.get(&expr.into())
|
||||
}
|
||||
pub fn type_mismatch_for_pat(&self, pat: PatId) -> Option<&TypeMismatch> {
|
||||
self.type_mismatches.get(&pat.into())
|
||||
}
|
||||
pub fn expr_type_mismatches(&self) -> impl Iterator<Item = (ExprId, &TypeMismatch)> {
|
||||
self.type_mismatches.iter().filter_map(|(expr_or_pat, mismatch)| match *expr_or_pat {
|
||||
ExprOrPatId::ExprId(expr) => Some((expr, mismatch)),
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
pub fn pat_type_mismatches(&self) -> impl Iterator<Item = (PatId, &TypeMismatch)> {
|
||||
self.type_mismatches.iter().filter_map(|(expr_or_pat, mismatch)| match *expr_or_pat {
|
||||
ExprOrPatId::PatId(pat) => Some((pat, mismatch)),
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
pub fn add_diagnostics(
|
||||
&self,
|
||||
|
@ -42,7 +42,7 @@ impl<'a> InferenceContext<'a> {
|
||||
let could_unify = self.unify(&ty, &expected.ty);
|
||||
if !could_unify {
|
||||
self.result.type_mismatches.insert(
|
||||
tgt_expr,
|
||||
tgt_expr.into(),
|
||||
TypeMismatch { expected: expected.ty.clone(), actual: ty.clone() },
|
||||
);
|
||||
}
|
||||
@ -54,9 +54,10 @@ impl<'a> InferenceContext<'a> {
|
||||
pub(super) fn infer_expr_coerce(&mut self, expr: ExprId, expected: &Expectation) -> Ty {
|
||||
let ty = self.infer_expr_inner(expr, &expected);
|
||||
let ty = if !self.coerce(&ty, &expected.coercion_target()) {
|
||||
self.result
|
||||
.type_mismatches
|
||||
.insert(expr, TypeMismatch { expected: expected.ty.clone(), actual: ty.clone() });
|
||||
self.result.type_mismatches.insert(
|
||||
expr.into(),
|
||||
TypeMismatch { expected: expected.ty.clone(), actual: ty.clone() },
|
||||
);
|
||||
// Return actual type when type mismatch.
|
||||
// This is needed for diagnostic when return type mismatch.
|
||||
ty
|
||||
|
@ -10,7 +10,7 @@ use hir_def::{
|
||||
};
|
||||
use hir_expand::name::Name;
|
||||
|
||||
use super::{BindingMode, Expectation, InferenceContext};
|
||||
use super::{BindingMode, Expectation, InferenceContext, TypeMismatch};
|
||||
use crate::{
|
||||
lower::lower_to_chalk_mutability, static_lifetime, Interner, Substitution, Ty, TyBuilder,
|
||||
TyExt, TyKind,
|
||||
@ -266,7 +266,10 @@ impl<'a> InferenceContext<'a> {
|
||||
// use a new type variable if we got error type here
|
||||
let ty = self.insert_type_vars_shallow(ty);
|
||||
if !self.unify(&ty, expected) {
|
||||
// FIXME record mismatch, we need to change the type of self.type_mismatches for that
|
||||
self.result.type_mismatches.insert(
|
||||
pat.into(),
|
||||
TypeMismatch { expected: expected.clone(), actual: ty.clone() },
|
||||
);
|
||||
}
|
||||
let ty = self.resolve_ty_as_possible(ty);
|
||||
self.write_pat_ty(pat, ty.clone());
|
||||
|
@ -130,7 +130,10 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
|
||||
}
|
||||
Err(SyntheticSyntax) => continue,
|
||||
};
|
||||
types.push((syntax_ptr, ty));
|
||||
types.push((syntax_ptr.clone(), ty));
|
||||
if let Some(mismatch) = inference_result.type_mismatch_for_pat(pat) {
|
||||
mismatches.push((syntax_ptr, mismatch));
|
||||
}
|
||||
}
|
||||
|
||||
for (expr, ty) in inference_result.type_of_expr.iter() {
|
||||
|
@ -546,7 +546,9 @@ fn infer_const_pattern() {
|
||||
273..276 'Bar': usize
|
||||
280..283 'Bar': usize
|
||||
200..223: expected (), got Foo
|
||||
211..214: expected (), got Foo
|
||||
262..285: expected (), got usize
|
||||
273..276: expected (), got usize
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
@ -703,7 +705,7 @@ fn box_pattern() {
|
||||
|
||||
#[test]
|
||||
fn tuple_ellipsis_pattern() {
|
||||
check_infer(
|
||||
check_infer_with_mismatches(
|
||||
r#"
|
||||
fn foo(tuple: (u8, i16, f32)) {
|
||||
match tuple {
|
||||
@ -744,6 +746,8 @@ fn foo(tuple: (u8, i16, f32)) {
|
||||
186..200 '{/*too long*/}': ()
|
||||
209..210 '_': (u8, i16, f32)
|
||||
214..216 '{}': ()
|
||||
136..142: expected (u8, i16, f32), got (u8, i16)
|
||||
170..182: expected (u8, i16, f32), got (u8, i16, f32, _)
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
@ -851,3 +855,55 @@ fn f(e: Enum) {
|
||||
"#,
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn type_mismatch_in_or_pattern() {
|
||||
check_infer_with_mismatches(
|
||||
r#"
|
||||
fn main() {
|
||||
match (false,) {
|
||||
(true | (),) => {}
|
||||
(() | true,) => {}
|
||||
(_ | (),) => {}
|
||||
(() | _,) => {}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
10..142 '{ ... } }': ()
|
||||
16..140 'match ... }': ()
|
||||
22..30 '(false,)': (bool,)
|
||||
23..28 'false': bool
|
||||
41..53 '(true | (),)': (bool,)
|
||||
42..46 'true': bool
|
||||
42..46 'true': bool
|
||||
42..51 'true | ()': bool
|
||||
49..51 '()': ()
|
||||
57..59 '{}': ()
|
||||
68..80 '(() | true,)': ((),)
|
||||
69..71 '()': ()
|
||||
69..78 '() | true': ()
|
||||
74..78 'true': bool
|
||||
74..78 'true': bool
|
||||
84..86 '{}': ()
|
||||
95..104 '(_ | (),)': (bool,)
|
||||
96..97 '_': bool
|
||||
96..102 '_ | ()': bool
|
||||
100..102 '()': ()
|
||||
108..110 '{}': ()
|
||||
119..128 '(() | _,)': ((),)
|
||||
120..122 '()': ()
|
||||
120..126 '() | _': ()
|
||||
125..126 '_': bool
|
||||
132..134 '{}': ()
|
||||
49..51: expected bool, got ()
|
||||
68..80: expected (bool,), got ((),)
|
||||
69..71: expected bool, got ()
|
||||
69..78: expected bool, got ()
|
||||
100..102: expected bool, got ()
|
||||
119..128: expected (bool,), got ((),)
|
||||
120..122: expected bool, got ()
|
||||
120..126: expected bool, got ()
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user