mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-15 22:54:00 +00:00
Record diverging match arms in InferenceResult
This commit is contained in:
parent
ba28e19b78
commit
319611b738
4 changed files with 30 additions and 0 deletions
|
@ -333,6 +333,8 @@ pub struct InferenceResult {
|
||||||
assoc_resolutions: FxHashMap<ExprOrPatId, AssocItemId>,
|
assoc_resolutions: FxHashMap<ExprOrPatId, AssocItemId>,
|
||||||
pub diagnostics: Vec<InferenceDiagnostic>,
|
pub diagnostics: Vec<InferenceDiagnostic>,
|
||||||
pub type_of_expr: ArenaMap<ExprId, Ty>,
|
pub type_of_expr: ArenaMap<ExprId, Ty>,
|
||||||
|
/// For each match expr, record diverging arm's expr.
|
||||||
|
pub diverging_arms: FxHashMap<ExprId, Vec<ExprId>>,
|
||||||
/// For each pattern record the type it resolves to.
|
/// For each pattern record the type it resolves to.
|
||||||
///
|
///
|
||||||
/// **Note**: When a pattern type is resolved it may still contain
|
/// **Note**: When a pattern type is resolved it may still contain
|
||||||
|
|
|
@ -375,6 +375,7 @@ impl<'a> InferenceContext<'a> {
|
||||||
|
|
||||||
let matchee_diverges = self.diverges;
|
let matchee_diverges = self.diverges;
|
||||||
let mut all_arms_diverge = Diverges::Always;
|
let mut all_arms_diverge = Diverges::Always;
|
||||||
|
let mut diverging_arms = Vec::new();
|
||||||
|
|
||||||
for arm in arms.iter() {
|
for arm in arms.iter() {
|
||||||
self.diverges = Diverges::Maybe;
|
self.diverges = Diverges::Maybe;
|
||||||
|
@ -387,11 +388,15 @@ impl<'a> InferenceContext<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let arm_ty = self.infer_expr_inner(arm.expr, &expected);
|
let arm_ty = self.infer_expr_inner(arm.expr, &expected);
|
||||||
|
if self.diverges.is_always() {
|
||||||
|
diverging_arms.push(arm.expr);
|
||||||
|
}
|
||||||
all_arms_diverge &= self.diverges;
|
all_arms_diverge &= self.diverges;
|
||||||
coerce.coerce(self, Some(arm.expr), &arm_ty);
|
coerce.coerce(self, Some(arm.expr), &arm_ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.diverges = matchee_diverges | all_arms_diverge;
|
self.diverges = matchee_diverges | all_arms_diverge;
|
||||||
|
self.result.diverging_arms.insert(tgt_expr, diverging_arms);
|
||||||
|
|
||||||
coerce.complete()
|
coerce.complete()
|
||||||
}
|
}
|
||||||
|
|
|
@ -481,6 +481,10 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
|
||||||
pub fn is_unsafe_ident_pat(&self, ident_pat: &ast::IdentPat) -> bool {
|
pub fn is_unsafe_ident_pat(&self, ident_pat: &ast::IdentPat) -> bool {
|
||||||
self.imp.is_unsafe_ident_pat(ident_pat)
|
self.imp.is_unsafe_ident_pat(ident_pat)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_diverging_match_arm(&self, match_arm: &ast::MatchArm) -> Option<bool> {
|
||||||
|
self.imp.is_diverging_match_arm(match_arm)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'db> SemanticsImpl<'db> {
|
impl<'db> SemanticsImpl<'db> {
|
||||||
|
@ -1421,6 +1425,10 @@ impl<'db> SemanticsImpl<'db> {
|
||||||
.map(|ty| ty.original.is_packed(self.db))
|
.map(|ty| ty.original.is_packed(self.db))
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_diverging_match_arm(&self, match_arm: &ast::MatchArm) -> Option<bool> {
|
||||||
|
self.analyze(match_arm.syntax())?.is_diverging_match_arm(self.db, match_arm)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn macro_call_to_macro_id(
|
fn macro_call_to_macro_id(
|
||||||
|
|
|
@ -782,6 +782,21 @@ impl SourceAnalyzer {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn is_diverging_match_arm(
|
||||||
|
&self,
|
||||||
|
db: &dyn HirDatabase,
|
||||||
|
match_arm: &ast::MatchArm,
|
||||||
|
) -> Option<bool> {
|
||||||
|
let infer = self.infer.as_ref()?;
|
||||||
|
let match_expr = match_arm.syntax().ancestors().find_map(ast::MatchExpr::cast)?;
|
||||||
|
let match_id = self.expr_id(db, &match_expr.into())?;
|
||||||
|
let diverging_arms = infer.diverging_arms.get(&match_id)?;
|
||||||
|
let match_arm_expr = match_arm.expr()?;
|
||||||
|
let match_arm_expr_id = self.expr_id(db, &match_arm_expr)?;
|
||||||
|
|
||||||
|
Some(diverging_arms.contains(&match_arm_expr_id))
|
||||||
|
}
|
||||||
|
|
||||||
fn resolve_impl_method_or_trait_def(
|
fn resolve_impl_method_or_trait_def(
|
||||||
&self,
|
&self,
|
||||||
db: &dyn HirDatabase,
|
db: &dyn HirDatabase,
|
||||||
|
|
Loading…
Reference in a new issue