diff options
Diffstat (limited to 'crates/ra_hir_ty/src/expr.rs')
-rw-r--r-- | crates/ra_hir_ty/src/expr.rs | 68 |
1 files changed, 32 insertions, 36 deletions
diff --git a/crates/ra_hir_ty/src/expr.rs b/crates/ra_hir_ty/src/expr.rs index 827b687de..21abbcf1e 100644 --- a/crates/ra_hir_ty/src/expr.rs +++ b/crates/ra_hir_ty/src/expr.rs | |||
@@ -89,21 +89,19 @@ impl<'a, 'b> ExprValidator<'a, 'b> { | |||
89 | let (_, source_map) = db.body_with_source_map(self.func.into()); | 89 | let (_, source_map) = db.body_with_source_map(self.func.into()); |
90 | 90 | ||
91 | if let Ok(source_ptr) = source_map.expr_syntax(id) { | 91 | if let Ok(source_ptr) = source_map.expr_syntax(id) { |
92 | if let Some(expr) = source_ptr.value.as_ref().left() { | 92 | let root = source_ptr.file_syntax(db.upcast()); |
93 | let root = source_ptr.file_syntax(db.upcast()); | 93 | if let ast::Expr::RecordLit(record_lit) = &source_ptr.value.to_node(&root) { |
94 | if let ast::Expr::RecordLit(record_lit) = expr.to_node(&root) { | 94 | if let Some(field_list) = record_lit.record_field_list() { |
95 | if let Some(field_list) = record_lit.record_field_list() { | 95 | let variant_data = variant_data(db.upcast(), variant_def); |
96 | let variant_data = variant_data(db.upcast(), variant_def); | 96 | let missed_fields = missed_fields |
97 | let missed_fields = missed_fields | 97 | .into_iter() |
98 | .into_iter() | 98 | .map(|idx| variant_data.fields()[idx].name.clone()) |
99 | .map(|idx| variant_data.fields()[idx].name.clone()) | 99 | .collect(); |
100 | .collect(); | 100 | self.sink.push(MissingFields { |
101 | self.sink.push(MissingFields { | 101 | file: source_ptr.file_id, |
102 | file: source_ptr.file_id, | 102 | field_list: AstPtr::new(&field_list), |
103 | field_list: AstPtr::new(&field_list), | 103 | missed_fields, |
104 | missed_fields, | 104 | }) |
105 | }) | ||
106 | } | ||
107 | } | 105 | } |
108 | } | 106 | } |
109 | } | 107 | } |
@@ -163,12 +161,6 @@ impl<'a, 'b> ExprValidator<'a, 'b> { | |||
163 | 161 | ||
164 | let mut seen = Matrix::empty(); | 162 | let mut seen = Matrix::empty(); |
165 | for pat in pats { | 163 | for pat in pats { |
166 | // We skip any patterns whose type we cannot resolve. | ||
167 | // | ||
168 | // This could lead to false positives in this diagnostic, so | ||
169 | // it might be better to skip the entire diagnostic if we either | ||
170 | // cannot resolve a match arm or determine that the match arm has | ||
171 | // the wrong type. | ||
172 | if let Some(pat_ty) = infer.type_of_pat.get(pat) { | 164 | if let Some(pat_ty) = infer.type_of_pat.get(pat) { |
173 | // We only include patterns whose type matches the type | 165 | // We only include patterns whose type matches the type |
174 | // of the match expression. If we had a InvalidMatchArmPattern | 166 | // of the match expression. If we had a InvalidMatchArmPattern |
@@ -191,8 +183,15 @@ impl<'a, 'b> ExprValidator<'a, 'b> { | |||
191 | // to the matrix here. | 183 | // to the matrix here. |
192 | let v = PatStack::from_pattern(pat); | 184 | let v = PatStack::from_pattern(pat); |
193 | seen.push(&cx, v); | 185 | seen.push(&cx, v); |
186 | continue; | ||
194 | } | 187 | } |
195 | } | 188 | } |
189 | |||
190 | // If we can't resolve the type of a pattern, or the pattern type doesn't | ||
191 | // fit the match expression, we skip this diagnostic. Skipping the entire | ||
192 | // diagnostic rather than just not including this match arm is preferred | ||
193 | // to avoid the chance of false positives. | ||
194 | return; | ||
196 | } | 195 | } |
197 | 196 | ||
198 | match is_useful(&cx, &seen, &PatStack::from_wild()) { | 197 | match is_useful(&cx, &seen, &PatStack::from_wild()) { |
@@ -205,18 +204,16 @@ impl<'a, 'b> ExprValidator<'a, 'b> { | |||
205 | } | 204 | } |
206 | 205 | ||
207 | if let Ok(source_ptr) = source_map.expr_syntax(id) { | 206 | if let Ok(source_ptr) = source_map.expr_syntax(id) { |
208 | if let Some(expr) = source_ptr.value.as_ref().left() { | 207 | let root = source_ptr.file_syntax(db.upcast()); |
209 | let root = source_ptr.file_syntax(db.upcast()); | 208 | if let ast::Expr::MatchExpr(match_expr) = &source_ptr.value.to_node(&root) { |
210 | if let ast::Expr::MatchExpr(match_expr) = expr.to_node(&root) { | 209 | if let (Some(match_expr), Some(arms)) = |
211 | if let (Some(match_expr), Some(arms)) = | 210 | (match_expr.expr(), match_expr.match_arm_list()) |
212 | (match_expr.expr(), match_expr.match_arm_list()) | 211 | { |
213 | { | 212 | self.sink.push(MissingMatchArms { |
214 | self.sink.push(MissingMatchArms { | 213 | file: source_ptr.file_id, |
215 | file: source_ptr.file_id, | 214 | match_expr: AstPtr::new(&match_expr), |
216 | match_expr: AstPtr::new(&match_expr), | 215 | arms: AstPtr::new(&arms), |
217 | arms: AstPtr::new(&arms), | 216 | }) |
218 | }) | ||
219 | } | ||
220 | } | 217 | } |
221 | } | 218 | } |
222 | } | 219 | } |
@@ -247,9 +244,8 @@ impl<'a, 'b> ExprValidator<'a, 'b> { | |||
247 | let (_, source_map) = db.body_with_source_map(self.func.into()); | 244 | let (_, source_map) = db.body_with_source_map(self.func.into()); |
248 | 245 | ||
249 | if let Ok(source_ptr) = source_map.expr_syntax(id) { | 246 | if let Ok(source_ptr) = source_map.expr_syntax(id) { |
250 | if let Some(expr) = source_ptr.value.left() { | 247 | self.sink |
251 | self.sink.push(MissingOkInTailExpr { file: source_ptr.file_id, expr }); | 248 | .push(MissingOkInTailExpr { file: source_ptr.file_id, expr: source_ptr.value }); |
252 | } | ||
253 | } | 249 | } |
254 | } | 250 | } |
255 | } | 251 | } |