Skip to content

Commit b023671

Browse files
committed
Add pattern_complexity_limit to Limits.
It's similar to the other limits, e.g. obtained via `get_limit`. So it makes sense to handle it consistently with the other limits. We now use `Limit`/`usize` in most places instead of `Option<usize>`, so we use `Limit::new(usize::MAX)`/`usize::MAX` to emulate how `None` used to work. The commit also adds `Limit::unlimited`.
1 parent 5bc6231 commit b023671

File tree

11 files changed

+51
-35
lines changed

11 files changed

+51
-35
lines changed

compiler/rustc_middle/src/middle/limits.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,30 +24,36 @@ pub fn provide(providers: &mut Providers) {
2424
tcx.hir().krate_attrs(),
2525
tcx.sess,
2626
sym::move_size_limit,
27-
tcx.sess.opts.unstable_opts.move_size_limit.unwrap_or(0),
27+
Limit::new(tcx.sess.opts.unstable_opts.move_size_limit.unwrap_or(0)),
2828
),
2929
type_length_limit: get_limit(
3030
tcx.hir().krate_attrs(),
3131
tcx.sess,
3232
sym::type_length_limit,
33-
2usize.pow(24),
33+
Limit::new(2usize.pow(24)),
34+
),
35+
pattern_complexity_limit: get_limit(
36+
tcx.hir().krate_attrs(),
37+
tcx.sess,
38+
sym::pattern_complexity,
39+
Limit::unlimited(),
3440
),
3541
}
3642
}
3743

3844
pub fn get_recursion_limit(krate_attrs: &[impl AttributeExt], sess: &Session) -> Limit {
39-
get_limit(krate_attrs, sess, sym::recursion_limit, 128)
45+
get_limit(krate_attrs, sess, sym::recursion_limit, Limit::new(128))
4046
}
4147

4248
fn get_limit(
4349
krate_attrs: &[impl AttributeExt],
4450
sess: &Session,
4551
name: Symbol,
46-
default: usize,
52+
default: Limit,
4753
) -> Limit {
4854
match get_limit_size(krate_attrs, sess, name) {
4955
Some(size) => Limit::new(size),
50-
None => Limit::new(default),
56+
None => default,
5157
}
5258
}
5359

compiler/rustc_middle/src/ty/context.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2168,6 +2168,10 @@ impl<'tcx> TyCtxt<'tcx> {
21682168
self.limits(()).move_size_limit
21692169
}
21702170

2171+
pub fn pattern_complexity_limit(self) -> Limit {
2172+
self.limits(()).pattern_complexity_limit
2173+
}
2174+
21712175
/// All traits in the crate graph, including those not visible to the user.
21722176
pub fn all_traits(self) -> impl Iterator<Item = DefId> + 'tcx {
21732177
iter::once(LOCAL_CRATE)

compiler/rustc_mir_build/src/thir/pattern/check_match.rs

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ use rustc_hir::{self as hir, BindingMode, ByRef, HirId};
1010
use rustc_infer::infer::TyCtxtInferExt;
1111
use rustc_lint::Level;
1212
use rustc_middle::bug;
13-
use rustc_middle::middle::limits::get_limit_size;
1413
use rustc_middle::thir::visit::Visitor;
1514
use rustc_middle::thir::*;
1615
use rustc_middle::ty::print::with_no_trimmed_paths;
@@ -25,7 +24,7 @@ use rustc_session::lint::builtin::{
2524
};
2625
use rustc_span::edit_distance::find_best_match_for_name;
2726
use rustc_span::hygiene::DesugaringKind;
28-
use rustc_span::{Ident, Span, sym};
27+
use rustc_span::{Ident, Span};
2928
use rustc_trait_selection::infer::InferCtxtExt;
3029
use tracing::instrument;
3130

@@ -404,18 +403,11 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
404403
arms: &[MatchArm<'p, 'tcx>],
405404
scrut_ty: Ty<'tcx>,
406405
) -> Result<UsefulnessReport<'p, 'tcx>, ErrorGuaranteed> {
407-
let pattern_complexity_limit =
408-
get_limit_size(cx.tcx.hir().krate_attrs(), cx.tcx.sess, sym::pattern_complexity);
409-
let report = rustc_pattern_analysis::rustc::analyze_match(
410-
&cx,
411-
&arms,
412-
scrut_ty,
413-
pattern_complexity_limit,
414-
)
415-
.map_err(|err| {
416-
self.error = Err(err);
417-
err
418-
})?;
406+
let report =
407+
rustc_pattern_analysis::rustc::analyze_match(&cx, &arms, scrut_ty).map_err(|err| {
408+
self.error = Err(err);
409+
err
410+
})?;
419411

420412
// Warn unreachable subpatterns.
421413
for (arm, is_useful) in report.arm_usefulness.iter() {

compiler/rustc_pattern_analysis/src/rustc.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1084,12 +1084,16 @@ pub fn analyze_match<'p, 'tcx>(
10841084
tycx: &RustcPatCtxt<'p, 'tcx>,
10851085
arms: &[MatchArm<'p, 'tcx>],
10861086
scrut_ty: Ty<'tcx>,
1087-
pattern_complexity_limit: Option<usize>,
10881087
) -> Result<UsefulnessReport<'p, 'tcx>, ErrorGuaranteed> {
10891088
let scrut_ty = tycx.reveal_opaque_ty(scrut_ty);
10901089
let scrut_validity = PlaceValidity::from_bool(tycx.known_valid_scrutinee);
1091-
let report =
1092-
compute_match_usefulness(tycx, arms, scrut_ty, scrut_validity, pattern_complexity_limit)?;
1090+
let report = compute_match_usefulness(
1091+
tycx,
1092+
arms,
1093+
scrut_ty,
1094+
scrut_validity,
1095+
tycx.tcx.pattern_complexity_limit().0,
1096+
)?;
10931097

10941098
// Run the non_exhaustive_omitted_patterns lint. Only run on refutable patterns to avoid hitting
10951099
// `if let`s. Only run if the match is exhaustive otherwise the error is redundant.

compiler/rustc_pattern_analysis/src/usefulness.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -795,20 +795,21 @@ struct UsefulnessCtxt<'a, 'p, Cx: PatCx> {
795795
/// Track information about the usefulness of branch patterns (see definition of "branch
796796
/// pattern" at [`BranchPatUsefulness`]).
797797
branch_usefulness: FxHashMap<PatId, BranchPatUsefulness<'p, Cx>>,
798-
complexity_limit: Option<usize>,
798+
// Ideally this field would have type `Limit`, but this crate is used by
799+
// rust-analyzer which cannot have a dependency on `Limit`, because `Limit`
800+
// is from crate `rustc_session` which uses unstable Rust features.
801+
complexity_limit: usize,
799802
complexity_level: usize,
800803
}
801804

802805
impl<'a, 'p, Cx: PatCx> UsefulnessCtxt<'a, 'p, Cx> {
803806
fn increase_complexity_level(&mut self, complexity_add: usize) -> Result<(), Cx::Error> {
804807
self.complexity_level += complexity_add;
805-
if self
806-
.complexity_limit
807-
.is_some_and(|complexity_limit| complexity_limit < self.complexity_level)
808-
{
809-
return self.tycx.complexity_exceeded();
808+
if self.complexity_level <= self.complexity_limit {
809+
Ok(())
810+
} else {
811+
self.tycx.complexity_exceeded()
810812
}
811-
Ok(())
812813
}
813814
}
814815

@@ -1834,7 +1835,7 @@ pub fn compute_match_usefulness<'p, Cx: PatCx>(
18341835
arms: &[MatchArm<'p, Cx>],
18351836
scrut_ty: Cx::Ty,
18361837
scrut_validity: PlaceValidity,
1837-
complexity_limit: Option<usize>,
1838+
complexity_limit: usize,
18381839
) -> Result<UsefulnessReport<'p, Cx>, Cx::Error> {
18391840
let mut cx = UsefulnessCtxt {
18401841
tycx,

compiler/rustc_pattern_analysis/tests/common/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ pub fn compute_match_usefulness<'p>(
124124
arms: &[MatchArm<'p, Cx>],
125125
ty: Ty,
126126
scrut_validity: PlaceValidity,
127-
complexity_limit: Option<usize>,
127+
complexity_limit: usize,
128128
) -> Result<UsefulnessReport<'p, Cx>, ()> {
129129
init_tracing();
130130
rustc_pattern_analysis::usefulness::compute_match_usefulness(

compiler/rustc_pattern_analysis/tests/complexity.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ fn check(patterns: &[DeconstructedPat<Cx>], complexity_limit: usize) -> Result<(
1414
let ty = *patterns[0].ty();
1515
let arms: Vec<_> =
1616
patterns.iter().map(|pat| MatchArm { pat, has_guard: false, arm_data: () }).collect();
17-
compute_match_usefulness(arms.as_slice(), ty, PlaceValidity::ValidOnly, Some(complexity_limit))
17+
compute_match_usefulness(arms.as_slice(), ty, PlaceValidity::ValidOnly, complexity_limit)
1818
.map(|_report| ())
1919
}
2020

compiler/rustc_pattern_analysis/tests/exhaustiveness.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ fn check(patterns: Vec<DeconstructedPat<Cx>>) -> Vec<WitnessPat<Cx>> {
1414
let arms: Vec<_> =
1515
patterns.iter().map(|pat| MatchArm { pat, has_guard: false, arm_data: () }).collect();
1616
let report =
17-
compute_match_usefulness(arms.as_slice(), ty, PlaceValidity::ValidOnly, None).unwrap();
17+
compute_match_usefulness(arms.as_slice(), ty, PlaceValidity::ValidOnly, usize::MAX)
18+
.unwrap();
1819
report.non_exhaustiveness_witnesses
1920
}
2021

compiler/rustc_pattern_analysis/tests/intersection.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ fn check(patterns: Vec<DeconstructedPat<Cx>>) -> Vec<Vec<usize>> {
1414
let arms: Vec<_> =
1515
patterns.iter().map(|pat| MatchArm { pat, has_guard: false, arm_data: () }).collect();
1616
let report =
17-
compute_match_usefulness(arms.as_slice(), ty, PlaceValidity::ValidOnly, None).unwrap();
17+
compute_match_usefulness(arms.as_slice(), ty, PlaceValidity::ValidOnly, usize::MAX)
18+
.unwrap();
1819
report.arm_intersections.into_iter().map(|bitset| bitset.iter().collect()).collect()
1920
}
2021

compiler/rustc_session/src/session.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@ impl Limit {
6767
Limit(value)
6868
}
6969

70+
/// Create a new unlimited limit.
71+
pub fn unlimited() -> Self {
72+
Limit(usize::MAX)
73+
}
74+
7075
/// Check that `value` is within the limit. Ensures that the same comparisons are used
7176
/// throughout the compiler, as mismatches can cause ICEs, see #72540.
7277
#[inline]
@@ -119,6 +124,8 @@ pub struct Limits {
119124
pub move_size_limit: Limit,
120125
/// The maximum length of types during monomorphization.
121126
pub type_length_limit: Limit,
127+
/// The maximum pattern complexity allowed (internal only).
128+
pub pattern_complexity_limit: Limit,
122129
}
123130

124131
pub struct CompilerIO {

src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ impl<'db> MatchCheckCtx<'db> {
9595

9696
let place_validity = PlaceValidity::from_bool(known_valid_scrutinee.unwrap_or(true));
9797
// Measured to take ~100ms on modern hardware.
98-
let complexity_limit = Some(500000);
98+
let complexity_limit = 500000;
9999
compute_match_usefulness(self, arms, scrut_ty, place_validity, complexity_limit)
100100
}
101101

0 commit comments

Comments
 (0)