-
Notifications
You must be signed in to change notification settings - Fork 13.3k
typeck: simplify the handling of diverges
#68422
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -50,30 +50,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | |
|
||
self.warn_arms_when_scrutinee_diverges(arms, match_src); | ||
|
||
// Otherwise, we have to union together the types that the | ||
// arms produce and so forth. | ||
let scrut_diverges = self.diverges.get(); | ||
self.diverges.set(Diverges::Maybe); | ||
// Otherwise, we have to union together the types that the arms produce and so forth. | ||
let scrut_diverges = self.diverges.replace(Diverges::Maybe); | ||
|
||
// rust-lang/rust#55810: Typecheck patterns first (via eager | ||
// collection into `Vec`), so we get types for all bindings. | ||
let all_arm_pats_diverge: Vec<_> = arms | ||
.iter() | ||
.map(|arm| { | ||
let mut all_pats_diverge = Diverges::WarnedAlways; | ||
self.diverges.set(Diverges::Maybe); | ||
self.check_pat_top(&arm.pat, scrut_ty, Some(scrut.span), true); | ||
all_pats_diverge &= self.diverges.get(); | ||
|
||
// As discussed with @eddyb, this is for disabling unreachable_code | ||
// warnings on patterns (they're now subsumed by unreachable_patterns | ||
// warnings). | ||
match all_pats_diverge { | ||
Diverges::Maybe => Diverges::Maybe, | ||
Diverges::Always { .. } | Diverges::WarnedAlways => Diverges::WarnedAlways, | ||
} | ||
}) | ||
.collect(); | ||
// #55810: Type check patterns first so we get types for all bindings. | ||
for arm in arms { | ||
self.check_pat_top(&arm.pat, scrut_ty, Some(scrut.span), true); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I assume "they're now subsumed by There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Filed #68429. (To recap what I said in private: |
||
|
||
// Now typecheck the blocks. | ||
// | ||
|
@@ -104,19 +87,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | |
CoerceMany::with_coercion_sites(coerce_first, arms) | ||
}; | ||
|
||
let mut other_arms = vec![]; // used only for diagnostics | ||
let mut other_arms = vec![]; // Used only for diagnostics. | ||
let mut prior_arm_ty = None; | ||
for (i, (arm, pats_diverge)) in arms.iter().zip(all_arm_pats_diverge).enumerate() { | ||
for (i, arm) in arms.iter().enumerate() { | ||
if let Some(g) = &arm.guard { | ||
self.diverges.set(pats_diverge); | ||
self.diverges.set(Diverges::Maybe); | ||
match g { | ||
hir::Guard::If(e) => { | ||
self.check_expr_has_type_or_error(e, tcx.types.bool, |_| {}) | ||
} | ||
}; | ||
} | ||
|
||
self.diverges.set(pats_diverge); | ||
self.diverges.set(Diverges::Maybe); | ||
let arm_ty = if source_if | ||
&& if_no_else | ||
&& i != 0 | ||
|
@@ -200,16 +183,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | |
arms: &'tcx [hir::Arm<'tcx>], | ||
source: hir::MatchSource, | ||
) { | ||
if self.diverges.get().is_always() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this was a performance microopt? |
||
use hir::MatchSource::*; | ||
let msg = match source { | ||
IfDesugar { .. } | IfLetDesugar { .. } => "block in `if` expression", | ||
WhileDesugar { .. } | WhileLetDesugar { .. } => "block in `while` expression", | ||
_ => "arm", | ||
}; | ||
for arm in arms { | ||
self.warn_if_unreachable(arm.body.hir_id, arm.body.span, msg); | ||
} | ||
use hir::MatchSource::*; | ||
let msg = match source { | ||
IfDesugar { .. } | IfLetDesugar { .. } => "block in `if` expression", | ||
WhileDesugar { .. } | WhileLetDesugar { .. } => "block in `while` expression", | ||
_ => "arm", | ||
}; | ||
for arm in arms { | ||
self.warn_if_unreachable(arm.body.hir_id, arm.body.span, msg); | ||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ohh, we might have more similar places where we use
get
andset
, predatingCell::replace
.I found some in these two files, if someone wants to take them:
src/librustc/ty/print/pretty.rs
src/librustc/infer/mod.rs
(there's others, but they use the result of
get()
to compute the value toset
, and I don't think we have a nice abstraction for that)