Iron out last rustc-specific details
This commit is contained in:
parent
cb622f3994
commit
42f4393824
5 changed files with 43 additions and 18 deletions
|
@ -429,7 +429,8 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> {
|
||||||
let arm = &self.thir.arms[arm];
|
let arm = &self.thir.arms[arm];
|
||||||
let got_error = self.with_lint_level(arm.lint_level, |this| {
|
let got_error = self.with_lint_level(arm.lint_level, |this| {
|
||||||
let Ok(pat) = this.lower_pattern(&cx, &arm.pattern) else { return true };
|
let Ok(pat) = this.lower_pattern(&cx, &arm.pattern) else { return true };
|
||||||
let arm = MatchArm { pat, hir_id: this.lint_level, has_guard: arm.guard.is_some() };
|
let arm =
|
||||||
|
MatchArm { pat, arm_data: this.lint_level, has_guard: arm.guard.is_some() };
|
||||||
tarms.push(arm);
|
tarms.push(arm);
|
||||||
false
|
false
|
||||||
});
|
});
|
||||||
|
@ -552,7 +553,7 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> {
|
||||||
) -> Result<(MatchCheckCtxt<'p, 'tcx>, UsefulnessReport<'p, 'tcx>), ErrorGuaranteed> {
|
) -> Result<(MatchCheckCtxt<'p, 'tcx>, UsefulnessReport<'p, 'tcx>), ErrorGuaranteed> {
|
||||||
let cx = self.new_cx(refutability, None, scrut, pat.span);
|
let cx = self.new_cx(refutability, None, scrut, pat.span);
|
||||||
let pat = self.lower_pattern(&cx, pat)?;
|
let pat = self.lower_pattern(&cx, pat)?;
|
||||||
let arms = [MatchArm { pat, hir_id: self.lint_level, has_guard: false }];
|
let arms = [MatchArm { pat, arm_data: self.lint_level, has_guard: false }];
|
||||||
let report = analyze_match(&cx, &arms, pat.ty());
|
let report = analyze_match(&cx, &arms, pat.ty());
|
||||||
Ok((cx, report))
|
Ok((cx, report))
|
||||||
}
|
}
|
||||||
|
@ -855,7 +856,7 @@ fn report_arm_reachability<'p, 'tcx>(
|
||||||
for (arm, is_useful) in report.arm_usefulness.iter() {
|
for (arm, is_useful) in report.arm_usefulness.iter() {
|
||||||
match is_useful {
|
match is_useful {
|
||||||
Usefulness::Redundant => {
|
Usefulness::Redundant => {
|
||||||
report_unreachable_pattern(*arm.pat.span(), arm.hir_id, catchall)
|
report_unreachable_pattern(*arm.pat.span(), arm.arm_data, catchall)
|
||||||
}
|
}
|
||||||
Usefulness::Useful(redundant_spans) if redundant_spans.is_empty() => {}
|
Usefulness::Useful(redundant_spans) if redundant_spans.is_empty() => {}
|
||||||
// The arm is reachable, but contains redundant subpatterns (from or-patterns).
|
// The arm is reachable, but contains redundant subpatterns (from or-patterns).
|
||||||
|
@ -864,7 +865,7 @@ fn report_arm_reachability<'p, 'tcx>(
|
||||||
// Emit lints in the order in which they occur in the file.
|
// Emit lints in the order in which they occur in the file.
|
||||||
redundant_spans.sort_unstable();
|
redundant_spans.sort_unstable();
|
||||||
for span in redundant_spans {
|
for span in redundant_spans {
|
||||||
report_unreachable_pattern(span, arm.hir_id, None);
|
report_unreachable_pattern(span, arm.arm_data, None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -156,7 +156,6 @@ use smallvec::SmallVec;
|
||||||
|
|
||||||
use rustc_apfloat::ieee::{DoubleS, IeeeFloat, SingleS};
|
use rustc_apfloat::ieee::{DoubleS, IeeeFloat, SingleS};
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_hir::RangeEnd;
|
|
||||||
use rustc_index::IndexVec;
|
use rustc_index::IndexVec;
|
||||||
|
|
||||||
use self::Constructor::*;
|
use self::Constructor::*;
|
||||||
|
@ -173,6 +172,21 @@ enum Presence {
|
||||||
Seen,
|
Seen,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
pub enum RangeEnd {
|
||||||
|
Included,
|
||||||
|
Excluded,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for RangeEnd {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
f.write_str(match self {
|
||||||
|
RangeEnd::Included => "..=",
|
||||||
|
RangeEnd::Excluded => "..",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A possibly infinite integer. Values are encoded such that the ordering on `u128` matches the
|
/// A possibly infinite integer. Values are encoded such that the ordering on `u128` matches the
|
||||||
/// natural order on the original type. For example, `-128i8` is encoded as `0` and `127i8` as
|
/// natural order on the original type. For example, `-128i8` is encoded as `0` and `127i8` as
|
||||||
/// `255`. See `signed_bias` for details.
|
/// `255`. See `signed_bias` for details.
|
||||||
|
@ -220,7 +234,7 @@ impl MaybeInfiniteInt {
|
||||||
match self {
|
match self {
|
||||||
Finite(n) => match n.checked_sub(1) {
|
Finite(n) => match n.checked_sub(1) {
|
||||||
Some(m) => Finite(m),
|
Some(m) => Finite(m),
|
||||||
None => bug!(),
|
None => panic!("Called `MaybeInfiniteInt::minus_one` on 0"),
|
||||||
},
|
},
|
||||||
JustAfterMax => Finite(u128::MAX),
|
JustAfterMax => Finite(u128::MAX),
|
||||||
x => x,
|
x => x,
|
||||||
|
@ -233,7 +247,7 @@ impl MaybeInfiniteInt {
|
||||||
Some(m) => Finite(m),
|
Some(m) => Finite(m),
|
||||||
None => JustAfterMax,
|
None => JustAfterMax,
|
||||||
},
|
},
|
||||||
JustAfterMax => bug!(),
|
JustAfterMax => panic!("Called `MaybeInfiniteInt::plus_one` on u128::MAX+1"),
|
||||||
x => x,
|
x => x,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -270,7 +284,7 @@ impl IntRange {
|
||||||
}
|
}
|
||||||
if lo >= hi {
|
if lo >= hi {
|
||||||
// This should have been caught earlier by E0030.
|
// This should have been caught earlier by E0030.
|
||||||
bug!("malformed range pattern: {lo:?}..{hi:?}");
|
panic!("malformed range pattern: {lo:?}..{hi:?}");
|
||||||
}
|
}
|
||||||
IntRange { lo, hi }
|
IntRange { lo, hi }
|
||||||
}
|
}
|
||||||
|
@ -431,7 +445,7 @@ impl Slice {
|
||||||
let kind = match (array_len, kind) {
|
let kind = match (array_len, kind) {
|
||||||
// If the middle `..` has length 0, we effectively have a fixed-length pattern.
|
// If the middle `..` has length 0, we effectively have a fixed-length pattern.
|
||||||
(Some(len), VarLen(prefix, suffix)) if prefix + suffix == len => FixedLen(len),
|
(Some(len), VarLen(prefix, suffix)) if prefix + suffix == len => FixedLen(len),
|
||||||
(Some(len), VarLen(prefix, suffix)) if prefix + suffix > len => bug!(
|
(Some(len), VarLen(prefix, suffix)) if prefix + suffix > len => panic!(
|
||||||
"Slice pattern of length {} longer than its array length {len}",
|
"Slice pattern of length {} longer than its array length {len}",
|
||||||
prefix + suffix
|
prefix + suffix
|
||||||
),
|
),
|
||||||
|
|
|
@ -30,8 +30,12 @@ use crate::rustc::RustcCtxt;
|
||||||
pub trait MatchCx: Sized + Clone + fmt::Debug {
|
pub trait MatchCx: Sized + Clone + fmt::Debug {
|
||||||
type Ty: Copy + Clone + fmt::Debug; // FIXME: remove Copy
|
type Ty: Copy + Clone + fmt::Debug; // FIXME: remove Copy
|
||||||
type Span: Clone + Default;
|
type Span: Clone + Default;
|
||||||
|
/// The index of an enum variant.
|
||||||
type VariantIdx: Clone + Idx;
|
type VariantIdx: Clone + Idx;
|
||||||
|
/// A string literal
|
||||||
type StrLit: Clone + PartialEq + fmt::Debug;
|
type StrLit: Clone + PartialEq + fmt::Debug;
|
||||||
|
/// Extra data to store on a match arm.
|
||||||
|
type ArmData: Copy + Clone + fmt::Debug;
|
||||||
|
|
||||||
fn is_opaque_ty(ty: Self::Ty) -> bool;
|
fn is_opaque_ty(ty: Self::Ty) -> bool;
|
||||||
fn is_exhaustive_patterns_feature_on(&self) -> bool;
|
fn is_exhaustive_patterns_feature_on(&self) -> bool;
|
||||||
|
@ -60,8 +64,8 @@ pub trait MatchCx: Sized + Clone + fmt::Debug {
|
||||||
pub struct MatchArm<'p, Cx: MatchCx> {
|
pub struct MatchArm<'p, Cx: MatchCx> {
|
||||||
/// The pattern must have been lowered through `check_match::MatchVisitor::lower_pattern`.
|
/// The pattern must have been lowered through `check_match::MatchVisitor::lower_pattern`.
|
||||||
pub pat: &'p DeconstructedPat<'p, Cx>,
|
pub pat: &'p DeconstructedPat<'p, Cx>,
|
||||||
pub hir_id: HirId,
|
|
||||||
pub has_guard: bool,
|
pub has_guard: bool,
|
||||||
|
pub arm_data: Cx::ArmData,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'p, Cx: MatchCx> Copy for MatchArm<'p, Cx> {}
|
impl<'p, Cx: MatchCx> Copy for MatchArm<'p, Cx> {}
|
||||||
|
|
|
@ -205,7 +205,7 @@ pub(crate) fn lint_nonexhaustive_missing_variants<'a, 'p, 'tcx>(
|
||||||
// usage of the lint.
|
// usage of the lint.
|
||||||
for arm in arms {
|
for arm in arms {
|
||||||
let (lint_level, lint_level_source) =
|
let (lint_level, lint_level_source) =
|
||||||
cx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, arm.hir_id);
|
cx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, arm.arm_data);
|
||||||
if !matches!(lint_level, rustc_session::lint::Level::Allow) {
|
if !matches!(lint_level, rustc_session::lint::Level::Allow) {
|
||||||
let decorator = NonExhaustiveOmittedPatternLintOnArm {
|
let decorator = NonExhaustiveOmittedPatternLintOnArm {
|
||||||
lint_span: lint_level_source.span(),
|
lint_span: lint_level_source.span(),
|
||||||
|
|
|
@ -4,7 +4,7 @@ use std::iter::once;
|
||||||
use rustc_arena::{DroplessArena, TypedArena};
|
use rustc_arena::{DroplessArena, TypedArena};
|
||||||
use rustc_data_structures::captures::Captures;
|
use rustc_data_structures::captures::Captures;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_hir::{HirId, RangeEnd};
|
use rustc_hir::HirId;
|
||||||
use rustc_index::Idx;
|
use rustc_index::Idx;
|
||||||
use rustc_index::IndexVec;
|
use rustc_index::IndexVec;
|
||||||
use rustc_middle::middle::stability::EvalResult;
|
use rustc_middle::middle::stability::EvalResult;
|
||||||
|
@ -18,12 +18,13 @@ use rustc_target::abi::{FieldIdx, Integer, VariantIdx, FIRST_VARIANT};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
use crate::constructor::{
|
use crate::constructor::{
|
||||||
IntRange, MaybeInfiniteInt, OpaqueId, Slice, SliceKind, VariantVisibility,
|
IntRange, MaybeInfiniteInt, OpaqueId, RangeEnd, Slice, SliceKind, VariantVisibility,
|
||||||
};
|
};
|
||||||
use crate::MatchCx;
|
use crate::MatchCx;
|
||||||
|
|
||||||
use crate::constructor::Constructor::*;
|
use crate::constructor::Constructor::*;
|
||||||
|
|
||||||
|
// Re-export rustc-specific versions of all these types.
|
||||||
pub type Constructor<'p, 'tcx> = crate::constructor::Constructor<RustcCtxt<'p, 'tcx>>;
|
pub type Constructor<'p, 'tcx> = crate::constructor::Constructor<RustcCtxt<'p, 'tcx>>;
|
||||||
pub type ConstructorSet<'p, 'tcx> = crate::constructor::ConstructorSet<RustcCtxt<'p, 'tcx>>;
|
pub type ConstructorSet<'p, 'tcx> = crate::constructor::ConstructorSet<RustcCtxt<'p, 'tcx>>;
|
||||||
pub type DeconstructedPat<'p, 'tcx> = crate::pat::DeconstructedPat<'p, RustcCtxt<'p, 'tcx>>;
|
pub type DeconstructedPat<'p, 'tcx> = crate::pat::DeconstructedPat<'p, RustcCtxt<'p, 'tcx>>;
|
||||||
|
@ -520,12 +521,16 @@ impl<'p, 'tcx> RustcCtxt<'p, 'tcx> {
|
||||||
}
|
}
|
||||||
PatKind::Range(patrange) => {
|
PatKind::Range(patrange) => {
|
||||||
let PatRange { lo, hi, end, .. } = patrange.as_ref();
|
let PatRange { lo, hi, end, .. } = patrange.as_ref();
|
||||||
|
let end = match end {
|
||||||
|
rustc_hir::RangeEnd::Included => RangeEnd::Included,
|
||||||
|
rustc_hir::RangeEnd::Excluded => RangeEnd::Excluded,
|
||||||
|
};
|
||||||
let ty = pat.ty;
|
let ty = pat.ty;
|
||||||
ctor = match ty.kind() {
|
ctor = match ty.kind() {
|
||||||
ty::Char | ty::Int(_) | ty::Uint(_) => {
|
ty::Char | ty::Int(_) | ty::Uint(_) => {
|
||||||
let lo = cx.lower_pat_range_bdy(*lo, ty);
|
let lo = cx.lower_pat_range_bdy(*lo, ty);
|
||||||
let hi = cx.lower_pat_range_bdy(*hi, ty);
|
let hi = cx.lower_pat_range_bdy(*hi, ty);
|
||||||
IntRange(IntRange::from_range(lo, hi, *end))
|
IntRange(IntRange::from_range(lo, hi, end))
|
||||||
}
|
}
|
||||||
ty::Float(fty) => {
|
ty::Float(fty) => {
|
||||||
use rustc_apfloat::Float;
|
use rustc_apfloat::Float;
|
||||||
|
@ -536,13 +541,13 @@ impl<'p, 'tcx> RustcCtxt<'p, 'tcx> {
|
||||||
use rustc_apfloat::ieee::Single;
|
use rustc_apfloat::ieee::Single;
|
||||||
let lo = lo.map(Single::from_bits).unwrap_or(-Single::INFINITY);
|
let lo = lo.map(Single::from_bits).unwrap_or(-Single::INFINITY);
|
||||||
let hi = hi.map(Single::from_bits).unwrap_or(Single::INFINITY);
|
let hi = hi.map(Single::from_bits).unwrap_or(Single::INFINITY);
|
||||||
F32Range(lo, hi, *end)
|
F32Range(lo, hi, end)
|
||||||
}
|
}
|
||||||
ty::FloatTy::F64 => {
|
ty::FloatTy::F64 => {
|
||||||
use rustc_apfloat::ieee::Double;
|
use rustc_apfloat::ieee::Double;
|
||||||
let lo = lo.map(Double::from_bits).unwrap_or(-Double::INFINITY);
|
let lo = lo.map(Double::from_bits).unwrap_or(-Double::INFINITY);
|
||||||
let hi = hi.map(Double::from_bits).unwrap_or(Double::INFINITY);
|
let hi = hi.map(Double::from_bits).unwrap_or(Double::INFINITY);
|
||||||
F64Range(lo, hi, *end)
|
F64Range(lo, hi, end)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -634,7 +639,7 @@ impl<'p, 'tcx> RustcCtxt<'p, 'tcx> {
|
||||||
PatKind::Constant { value }
|
PatKind::Constant { value }
|
||||||
} else {
|
} else {
|
||||||
// We convert to an inclusive range for diagnostics.
|
// We convert to an inclusive range for diagnostics.
|
||||||
let mut end = RangeEnd::Included;
|
let mut end = rustc_hir::RangeEnd::Included;
|
||||||
let mut lo = cx.hoist_pat_range_bdy(range.lo, ty);
|
let mut lo = cx.hoist_pat_range_bdy(range.lo, ty);
|
||||||
if matches!(lo, PatRangeBoundary::PosInfinity) {
|
if matches!(lo, PatRangeBoundary::PosInfinity) {
|
||||||
// The only reason to get `PosInfinity` here is the special case where
|
// The only reason to get `PosInfinity` here is the special case where
|
||||||
|
@ -648,7 +653,7 @@ impl<'p, 'tcx> RustcCtxt<'p, 'tcx> {
|
||||||
}
|
}
|
||||||
let hi = if matches!(range.hi, Finite(0)) {
|
let hi = if matches!(range.hi, Finite(0)) {
|
||||||
// The range encodes `..ty::MIN`, so we can't convert it to an inclusive range.
|
// The range encodes `..ty::MIN`, so we can't convert it to an inclusive range.
|
||||||
end = RangeEnd::Excluded;
|
end = rustc_hir::RangeEnd::Excluded;
|
||||||
range.hi
|
range.hi
|
||||||
} else {
|
} else {
|
||||||
range.hi.minus_one()
|
range.hi.minus_one()
|
||||||
|
@ -853,6 +858,7 @@ impl<'p, 'tcx> MatchCx for RustcCtxt<'p, 'tcx> {
|
||||||
type Span = Span;
|
type Span = Span;
|
||||||
type VariantIdx = VariantIdx;
|
type VariantIdx = VariantIdx;
|
||||||
type StrLit = Const<'tcx>;
|
type StrLit = Const<'tcx>;
|
||||||
|
type ArmData = HirId;
|
||||||
|
|
||||||
fn is_exhaustive_patterns_feature_on(&self) -> bool {
|
fn is_exhaustive_patterns_feature_on(&self) -> bool {
|
||||||
self.tcx.features().exhaustive_patterns
|
self.tcx.features().exhaustive_patterns
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue