diff options
| author | bors <bors@rust-lang.org> | 2024-01-25 09:20:22 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-01-25 09:20:22 +0000 |
| commit | 5bd5d214effd494f4bafb29b3a7a2f6c2070ca5c (patch) | |
| tree | c2377bd46c3a4a0ae0479913f2e203ff8466fb81 /compiler/rustc_pattern_analysis | |
| parent | d93feccb35183fa66fee77e7a2c9d4bf4d01695c (diff) | |
| parent | 8c1ba5931c30b5102fa30202b44ba2a8c40f565e (diff) | |
| download | rust-5bd5d214effd494f4bafb29b3a7a2f6c2070ca5c.tar.gz rust-5bd5d214effd494f4bafb29b3a7a2f6c2070ca5c.zip | |
Auto merge of #120335 - matthiaskrgr:rollup-2a0y3rd, r=matthiaskrgr
Rollup of 10 pull requests Successful merges: - #119305 (Add `AsyncFn` family of traits) - #119389 (Provide more context on recursive `impl` evaluation overflow) - #119895 (Remove `track_errors` entirely) - #120230 (Assert that a single scope is passed to `for_scope`) - #120278 (Remove --fatal-warnings on wasm targets) - #120292 (coverage: Dismantle `Instrumentor` and flatten span refinement) - #120315 (On E0308 involving `dyn Trait`, mention trait objects) - #120317 (pattern_analysis: Let `ctor_sub_tys` return any Iterator they want) - #120318 (pattern_analysis: Reuse most of the `DeconstructedPat` `Debug` impl) - #120325 (rustc_data_structures: use either instead of itertools) r? `@ghost` `@rustbot` modify labels: rollup
Diffstat (limited to 'compiler/rustc_pattern_analysis')
| -rw-r--r-- | compiler/rustc_pattern_analysis/src/constructor.rs | 16 | ||||
| -rw-r--r-- | compiler/rustc_pattern_analysis/src/lib.rs | 14 | ||||
| -rw-r--r-- | compiler/rustc_pattern_analysis/src/pat.rs | 73 | ||||
| -rw-r--r-- | compiler/rustc_pattern_analysis/src/rustc.rs | 136 | ||||
| -rw-r--r-- | compiler/rustc_pattern_analysis/src/usefulness.rs | 8 |
5 files changed, 121 insertions, 126 deletions
diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs index eba71a23435..e94a0373c79 100644 --- a/compiler/rustc_pattern_analysis/src/constructor.rs +++ b/compiler/rustc_pattern_analysis/src/constructor.rs @@ -391,12 +391,18 @@ impl IntRange { /// first. impl fmt::Debug for IntRange { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if let Finite(lo) = self.lo { + if self.is_singleton() { + // Only finite ranges can be singletons. + let Finite(lo) = self.lo else { unreachable!() }; write!(f, "{lo}")?; - } - write!(f, "{}", RangeEnd::Excluded)?; - if let Finite(hi) = self.hi { - write!(f, "{hi}")?; + } else { + if let Finite(lo) = self.lo { + write!(f, "{lo}")?; + } + write!(f, "{}", RangeEnd::Excluded)?; + if let Finite(hi) = self.hi { + write!(f, "{hi}")?; + } } Ok(()) } diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs index 4fd01b5e638..a55d53dfdac 100644 --- a/compiler/rustc_pattern_analysis/src/lib.rs +++ b/compiler/rustc_pattern_analysis/src/lib.rs @@ -101,15 +101,23 @@ pub trait TypeCx: Sized + fmt::Debug { /// The types of the fields for this constructor. The result must have a length of /// `ctor_arity()`. - fn ctor_sub_tys(&self, ctor: &Constructor<Self>, ty: &Self::Ty) -> &[Self::Ty]; + fn ctor_sub_tys<'a>( + &'a self, + ctor: &'a Constructor<Self>, + ty: &'a Self::Ty, + ) -> impl Iterator<Item = Self::Ty> + ExactSizeIterator + Captures<'a>; /// The set of all the constructors for `ty`. /// /// This must follow the invariants of `ConstructorSet` fn ctors_for_ty(&self, ty: &Self::Ty) -> Result<ConstructorSet<Self>, Self::Error>; - /// Best-effort `Debug` implementation. - fn debug_pat(f: &mut fmt::Formatter<'_>, pat: &DeconstructedPat<'_, Self>) -> fmt::Result; + /// Write the name of the variant represented by `pat`. Used for the best-effort `Debug` impl of + /// `DeconstructedPat`. Only invoqued when `pat.ctor()` is `Struct | Variant(_) | UnionField`. + fn write_variant_name( + f: &mut fmt::Formatter<'_>, + pat: &crate::pat::DeconstructedPat<'_, Self>, + ) -> fmt::Result; /// Raise a bug. fn bug(&self, fmt: fmt::Arguments<'_>) -> !; diff --git a/compiler/rustc_pattern_analysis/src/pat.rs b/compiler/rustc_pattern_analysis/src/pat.rs index 8cd0ecb073c..1cc31074556 100644 --- a/compiler/rustc_pattern_analysis/src/pat.rs +++ b/compiler/rustc_pattern_analysis/src/pat.rs @@ -142,7 +142,75 @@ impl<'p, Cx: TypeCx> DeconstructedPat<'p, Cx> { /// This is best effort and not good enough for a `Display` impl. impl<'p, Cx: TypeCx> fmt::Debug for DeconstructedPat<'p, Cx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - Cx::debug_pat(f, self) + let pat = self; + let mut first = true; + let mut start_or_continue = |s| { + if first { + first = false; + "" + } else { + s + } + }; + let mut start_or_comma = || start_or_continue(", "); + + match pat.ctor() { + Struct | Variant(_) | UnionField => { + Cx::write_variant_name(f, pat)?; + // Without `cx`, we can't know which field corresponds to which, so we can't + // get the names of the fields. Instead we just display everything as a tuple + // struct, which should be good enough. + write!(f, "(")?; + for p in pat.iter_fields() { + write!(f, "{}", start_or_comma())?; + write!(f, "{p:?}")?; + } + write!(f, ")") + } + // Note: given the expansion of `&str` patterns done in `expand_pattern`, we should + // be careful to detect strings here. However a string literal pattern will never + // be reported as a non-exhaustiveness witness, so we can ignore this issue. + Ref => { + let subpattern = pat.iter_fields().next().unwrap(); + write!(f, "&{:?}", subpattern) + } + Slice(slice) => { + let mut subpatterns = pat.iter_fields(); + write!(f, "[")?; + match slice.kind { + SliceKind::FixedLen(_) => { + for p in subpatterns { + write!(f, "{}{:?}", start_or_comma(), p)?; + } + } + SliceKind::VarLen(prefix_len, _) => { + for p in subpatterns.by_ref().take(prefix_len) { + write!(f, "{}{:?}", start_or_comma(), p)?; + } + write!(f, "{}", start_or_comma())?; + write!(f, "..")?; + for p in subpatterns { + write!(f, "{}{:?}", start_or_comma(), p)?; + } + } + } + write!(f, "]") + } + Bool(b) => write!(f, "{b}"), + // Best-effort, will render signed ranges incorrectly + IntRange(range) => write!(f, "{range:?}"), + F32Range(lo, hi, end) => write!(f, "{lo}{end}{hi}"), + F64Range(lo, hi, end) => write!(f, "{lo}{end}{hi}"), + Str(value) => write!(f, "{value:?}"), + Opaque(..) => write!(f, "<constant pattern>"), + Or => { + for pat in pat.iter_fields() { + write!(f, "{}{:?}", start_or_continue(" | "), pat)?; + } + Ok(()) + } + Wildcard | Missing { .. } | NonExhaustive | Hidden => write!(f, "_ : {:?}", pat.ty()), + } } } @@ -241,8 +309,7 @@ impl<Cx: TypeCx> WitnessPat<Cx> { /// For example, if `ctor` is a `Constructor::Variant` for `Option::Some`, we get the pattern /// `Some(_)`. pub(crate) fn wild_from_ctor(pcx: &PlaceCtxt<'_, Cx>, ctor: Constructor<Cx>) -> Self { - let field_tys = pcx.ctor_sub_tys(&ctor); - let fields = field_tys.iter().cloned().map(|ty| Self::wildcard(ty)).collect(); + let fields = pcx.ctor_sub_tys(&ctor).map(|ty| Self::wildcard(ty)).collect(); Self::new(ctor, fields, pcx.ty.clone()) } diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index d8c3c010a2a..23cab5f43ab 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -3,7 +3,6 @@ use std::fmt; use std::iter::once; use rustc_arena::{DroplessArena, TypedArena}; -use rustc_data_structures::captures::Captures; use rustc_hir::def_id::DefId; use rustc_hir::HirId; use rustc_index::{Idx, IndexVec}; @@ -20,7 +19,7 @@ use rustc_target::abi::{FieldIdx, Integer, VariantIdx, FIRST_VARIANT}; use crate::constructor::{ IntRange, MaybeInfiniteInt, OpaqueId, RangeEnd, Slice, SliceKind, VariantVisibility, }; -use crate::{errors, TypeCx}; +use crate::{errors, Captures, TypeCx}; use crate::constructor::Constructor::*; @@ -210,11 +209,11 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { /// Returns the types of the fields for a given constructor. The result must have a length of /// `ctor.arity()`. #[instrument(level = "trace", skip(self))] - pub(crate) fn ctor_sub_tys( - &self, - ctor: &Constructor<'p, 'tcx>, + pub(crate) fn ctor_sub_tys<'a>( + &'a self, + ctor: &'a Constructor<'p, 'tcx>, ty: RevealedTy<'tcx>, - ) -> &[RevealedTy<'tcx>] { + ) -> impl Iterator<Item = RevealedTy<'tcx>> + ExactSizeIterator + Captures<'a> { fn reveal_and_alloc<'a, 'tcx>( cx: &'a RustcMatchCheckCtxt<'_, 'tcx>, iter: impl Iterator<Item = Ty<'tcx>>, @@ -222,7 +221,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { cx.dropless_arena.alloc_from_iter(iter.map(|ty| cx.reveal_opaque_ty(ty))) } let cx = self; - match ctor { + let slice = match ctor { Struct | Variant(_) | UnionField => match ty.kind() { ty::Tuple(fs) => reveal_and_alloc(cx, fs.iter()), ty::Adt(adt, args) => { @@ -263,7 +262,8 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { Or => { bug!("called `Fields::wildcards` on an `Or` ctor") } - } + }; + slice.iter().copied() } /// The number of fields for this constructor. @@ -850,103 +850,6 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { Pat { ty: pat.ty().inner(), span: DUMMY_SP, kind } } - - /// Best-effort `Debug` implementation. - pub(crate) fn debug_pat( - f: &mut fmt::Formatter<'_>, - pat: &crate::pat::DeconstructedPat<'_, Self>, - ) -> fmt::Result { - let mut first = true; - let mut start_or_continue = |s| { - if first { - first = false; - "" - } else { - s - } - }; - let mut start_or_comma = || start_or_continue(", "); - - match pat.ctor() { - Struct | Variant(_) | UnionField => match pat.ty().kind() { - ty::Adt(def, _) if def.is_box() => { - // Without `box_patterns`, the only legal pattern of type `Box` is `_` (outside - // of `std`). So this branch is only reachable when the feature is enabled and - // the pattern is a box pattern. - let subpattern = pat.iter_fields().next().unwrap(); - write!(f, "box {subpattern:?}") - } - ty::Adt(..) | ty::Tuple(..) => { - let variant = - match pat.ty().kind() { - ty::Adt(adt, _) => Some(adt.variant( - RustcMatchCheckCtxt::variant_index_for_adt(pat.ctor(), *adt), - )), - ty::Tuple(_) => None, - _ => unreachable!(), - }; - - if let Some(variant) = variant { - write!(f, "{}", variant.name)?; - } - - // Without `cx`, we can't know which field corresponds to which, so we can't - // get the names of the fields. Instead we just display everything as a tuple - // struct, which should be good enough. - write!(f, "(")?; - for p in pat.iter_fields() { - write!(f, "{}", start_or_comma())?; - write!(f, "{p:?}")?; - } - write!(f, ")") - } - _ => write!(f, "_"), - }, - // Note: given the expansion of `&str` patterns done in `expand_pattern`, we should - // be careful to detect strings here. However a string literal pattern will never - // be reported as a non-exhaustiveness witness, so we can ignore this issue. - Ref => { - let subpattern = pat.iter_fields().next().unwrap(); - write!(f, "&{:?}", subpattern) - } - Slice(slice) => { - let mut subpatterns = pat.iter_fields(); - write!(f, "[")?; - match slice.kind { - SliceKind::FixedLen(_) => { - for p in subpatterns { - write!(f, "{}{:?}", start_or_comma(), p)?; - } - } - SliceKind::VarLen(prefix_len, _) => { - for p in subpatterns.by_ref().take(prefix_len) { - write!(f, "{}{:?}", start_or_comma(), p)?; - } - write!(f, "{}", start_or_comma())?; - write!(f, "..")?; - for p in subpatterns { - write!(f, "{}{:?}", start_or_comma(), p)?; - } - } - } - write!(f, "]") - } - Bool(b) => write!(f, "{b}"), - // Best-effort, will render signed ranges incorrectly - IntRange(range) => write!(f, "{range:?}"), - F32Range(lo, hi, end) => write!(f, "{lo}{end}{hi}"), - F64Range(lo, hi, end) => write!(f, "{lo}{end}{hi}"), - Str(value) => write!(f, "{value}"), - Opaque(..) => write!(f, "<constant pattern>"), - Or => { - for pat in pat.iter_fields() { - write!(f, "{}{:?}", start_or_continue(" | "), pat)?; - } - Ok(()) - } - Wildcard | Missing { .. } | NonExhaustive | Hidden => write!(f, "_ : {:?}", pat.ty()), - } - } } impl<'p, 'tcx> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> { @@ -964,11 +867,11 @@ impl<'p, 'tcx> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> { fn ctor_arity(&self, ctor: &crate::constructor::Constructor<Self>, ty: &Self::Ty) -> usize { self.ctor_arity(ctor, *ty) } - fn ctor_sub_tys( - &self, - ctor: &crate::constructor::Constructor<Self>, - ty: &Self::Ty, - ) -> &[Self::Ty] { + fn ctor_sub_tys<'a>( + &'a self, + ctor: &'a crate::constructor::Constructor<Self>, + ty: &'a Self::Ty, + ) -> impl Iterator<Item = Self::Ty> + ExactSizeIterator + Captures<'a> { self.ctor_sub_tys(ctor, *ty) } fn ctors_for_ty( @@ -978,12 +881,21 @@ impl<'p, 'tcx> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> { self.ctors_for_ty(*ty) } - fn debug_pat( + fn write_variant_name( f: &mut fmt::Formatter<'_>, pat: &crate::pat::DeconstructedPat<'_, Self>, ) -> fmt::Result { - Self::debug_pat(f, pat) + if let ty::Adt(adt, _) = pat.ty().kind() { + if adt.is_box() { + write!(f, "Box")? + } else { + let variant = adt.variant(Self::variant_index_for_adt(pat.ctor(), *adt)); + write!(f, "{}", variant.name)?; + } + } + Ok(()) } + fn bug(&self, fmt: fmt::Arguments<'_>) -> ! { span_bug!(self.scrut_span, "{}", fmt) } diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index d7852a2b2cb..0de48c9f3c0 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -750,7 +750,10 @@ impl<'a, Cx: TypeCx> PlaceCtxt<'a, Cx> { pub(crate) fn ctor_arity(&self, ctor: &Constructor<Cx>) -> usize { self.mcx.tycx.ctor_arity(ctor, self.ty) } - pub(crate) fn ctor_sub_tys(&self, ctor: &Constructor<Cx>) -> &[Cx::Ty] { + pub(crate) fn ctor_sub_tys( + &'a self, + ctor: &'a Constructor<Cx>, + ) -> impl Iterator<Item = Cx::Ty> + ExactSizeIterator + Captures<'a> { self.mcx.tycx.ctor_sub_tys(ctor, self.ty) } pub(crate) fn ctors_for_ty(&self) -> Result<ConstructorSet<Cx>, Cx::Error> { @@ -1058,8 +1061,7 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> { ) -> Matrix<'p, Cx> { let ctor_sub_tys = pcx.ctor_sub_tys(ctor); let arity = ctor_sub_tys.len(); - let specialized_place_ty = - ctor_sub_tys.iter().chain(self.place_ty[1..].iter()).cloned().collect(); + let specialized_place_ty = ctor_sub_tys.chain(self.place_ty[1..].iter().cloned()).collect(); let ctor_sub_validity = self.place_validity[0].specialize(ctor); let specialized_place_validity = std::iter::repeat(ctor_sub_validity) .take(arity) |
