Skip to content

Commit 319611b

Browse files
committed
Record diverging match arms in InferenceResult
1 parent ba28e19 commit 319611b

File tree

4 files changed

+30
-0
lines changed

4 files changed

+30
-0
lines changed

crates/hir-ty/src/infer.rs

+2
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,8 @@ pub struct InferenceResult {
333333
assoc_resolutions: FxHashMap<ExprOrPatId, AssocItemId>,
334334
pub diagnostics: Vec<InferenceDiagnostic>,
335335
pub type_of_expr: ArenaMap<ExprId, Ty>,
336+
/// For each match expr, record diverging arm's expr.
337+
pub diverging_arms: FxHashMap<ExprId, Vec<ExprId>>,
336338
/// For each pattern record the type it resolves to.
337339
///
338340
/// **Note**: When a pattern type is resolved it may still contain

crates/hir-ty/src/infer/expr.rs

+5
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,7 @@ impl<'a> InferenceContext<'a> {
375375

376376
let matchee_diverges = self.diverges;
377377
let mut all_arms_diverge = Diverges::Always;
378+
let mut diverging_arms = Vec::new();
378379

379380
for arm in arms.iter() {
380381
self.diverges = Diverges::Maybe;
@@ -387,11 +388,15 @@ impl<'a> InferenceContext<'a> {
387388
}
388389

389390
let arm_ty = self.infer_expr_inner(arm.expr, &expected);
391+
if self.diverges.is_always() {
392+
diverging_arms.push(arm.expr);
393+
}
390394
all_arms_diverge &= self.diverges;
391395
coerce.coerce(self, Some(arm.expr), &arm_ty);
392396
}
393397

394398
self.diverges = matchee_diverges | all_arms_diverge;
399+
self.result.diverging_arms.insert(tgt_expr, diverging_arms);
395400

396401
coerce.complete()
397402
}

crates/hir/src/semantics.rs

+8
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,10 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
481481
pub fn is_unsafe_ident_pat(&self, ident_pat: &ast::IdentPat) -> bool {
482482
self.imp.is_unsafe_ident_pat(ident_pat)
483483
}
484+
485+
pub fn is_diverging_match_arm(&self, match_arm: &ast::MatchArm) -> Option<bool> {
486+
self.imp.is_diverging_match_arm(match_arm)
487+
}
484488
}
485489

486490
impl<'db> SemanticsImpl<'db> {
@@ -1421,6 +1425,10 @@ impl<'db> SemanticsImpl<'db> {
14211425
.map(|ty| ty.original.is_packed(self.db))
14221426
.unwrap_or(false)
14231427
}
1428+
1429+
fn is_diverging_match_arm(&self, match_arm: &ast::MatchArm) -> Option<bool> {
1430+
self.analyze(match_arm.syntax())?.is_diverging_match_arm(self.db, match_arm)
1431+
}
14241432
}
14251433

14261434
fn macro_call_to_macro_id(

crates/hir/src/source_analyzer.rs

+15
Original file line numberDiff line numberDiff line change
@@ -782,6 +782,21 @@ impl SourceAnalyzer {
782782
false
783783
}
784784

785+
pub(crate) fn is_diverging_match_arm(
786+
&self,
787+
db: &dyn HirDatabase,
788+
match_arm: &ast::MatchArm,
789+
) -> Option<bool> {
790+
let infer = self.infer.as_ref()?;
791+
let match_expr = match_arm.syntax().ancestors().find_map(ast::MatchExpr::cast)?;
792+
let match_id = self.expr_id(db, &match_expr.into())?;
793+
let diverging_arms = infer.diverging_arms.get(&match_id)?;
794+
let match_arm_expr = match_arm.expr()?;
795+
let match_arm_expr_id = self.expr_id(db, &match_arm_expr)?;
796+
797+
Some(diverging_arms.contains(&match_arm_expr_id))
798+
}
799+
785800
fn resolve_impl_method_or_trait_def(
786801
&self,
787802
db: &dyn HirDatabase,

0 commit comments

Comments
 (0)