rustc_hir/
limit.rs

1use std::fmt;
2use std::ops::{Div, Mul};
3
4use rustc_error_messages::{DiagArgValue, IntoDiagArg};
5use rustc_macros::{Decodable, Encodable, HashStable_Generic};
6
7/// New-type wrapper around `usize` for representing limits. Ensures that comparisons against
8/// limits are consistent throughout the compiler.
9#[derive(Clone, Copy, Debug, HashStable_Generic, Encodable, Decodable)]
10pub struct Limit(pub usize);
11
12impl Limit {
13    /// Create a new limit from a `usize`.
14    pub fn new(value: usize) -> Self {
15        Limit(value)
16    }
17
18    /// Create a new unlimited limit.
19    pub fn unlimited() -> Self {
20        Limit(usize::MAX)
21    }
22
23    /// Check that `value` is within the limit. Ensures that the same comparisons are used
24    /// throughout the compiler, as mismatches can cause ICEs, see #72540.
25    #[inline]
26    pub fn value_within_limit(&self, value: usize) -> bool {
27        value <= self.0
28    }
29}
30
31impl From<usize> for Limit {
32    fn from(value: usize) -> Self {
33        Self::new(value)
34    }
35}
36
37impl fmt::Display for Limit {
38    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39        self.0.fmt(f)
40    }
41}
42
43impl Div<usize> for Limit {
44    type Output = Limit;
45
46    fn div(self, rhs: usize) -> Self::Output {
47        Limit::new(self.0 / rhs)
48    }
49}
50
51impl Mul<usize> for Limit {
52    type Output = Limit;
53
54    fn mul(self, rhs: usize) -> Self::Output {
55        Limit::new(self.0 * rhs)
56    }
57}
58
59impl IntoDiagArg for Limit {
60    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
61        self.to_string().into_diag_arg(&mut None)
62    }
63}