Skip to content

Commit

Permalink
Abort analysis on type error
Browse files Browse the repository at this point in the history
  • Loading branch information
Nadrieril committed Jan 7, 2024
1 parent 07d5f19 commit 4b2e8bc
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 11 deletions.
2 changes: 1 addition & 1 deletion compiler/rustc_pattern_analysis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ pub trait TypeCx: Sized + fmt::Debug {
/// The set of all the constructors for `ty`.
///
/// This must follow the invariants of `ConstructorSet`
fn ctors_for_ty(&self, ty: Self::Ty) -> ConstructorSet<Self>;
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;
Expand Down
12 changes: 8 additions & 4 deletions compiler/rustc_pattern_analysis/src/lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,13 @@ impl<'p, 'tcx> PatternColumn<'p, 'tcx> {
}

/// Do constructor splitting on the constructors of the column.
fn analyze_ctors(&self, pcx: &PlaceCtxt<'_, 'p, 'tcx>) -> SplitConstructorSet<'p, 'tcx> {
fn analyze_ctors(
&self,
pcx: &PlaceCtxt<'_, 'p, 'tcx>,
) -> Result<SplitConstructorSet<'p, 'tcx>, ErrorGuaranteed> {
let column_ctors = self.patterns.iter().map(|p| p.ctor());
pcx.ctors_for_ty().split(pcx, column_ctors)
let ctors_for_ty = &pcx.ctors_for_ty()?;
Ok(ctors_for_ty.split(pcx, column_ctors))
}

fn iter(&self) -> impl Iterator<Item = &'p DeconstructedPat<'p, 'tcx>> + Captures<'_> {
Expand Down Expand Up @@ -116,7 +120,7 @@ fn collect_nonexhaustive_missing_variants<'a, 'p, 'tcx>(
};
let pcx = &PlaceCtxt::new_dummy(cx, ty);

let set = column.analyze_ctors(pcx);
let set = column.analyze_ctors(pcx)?;
if set.present.is_empty() {
// We can't consistently handle the case where no constructors are present (since this would
// require digging deep through any type in case there's a non_exhaustive enum somewhere),
Expand Down Expand Up @@ -219,7 +223,7 @@ pub(crate) fn lint_overlapping_range_endpoints<'a, 'p, 'tcx>(
let pcx = &PlaceCtxt::new_dummy(cx, ty);
let rcx: &RustcMatchCheckCtxt<'_, '_> = cx.tycx;

let set = column.analyze_ctors(pcx);
let set = column.analyze_ctors(pcx)?;

if matches!(ty.kind(), ty::Char | ty::Int(_) | ty::Uint(_)) {
let emit_lint = |overlap: &IntRange, this_span: Span, overlapped_spans: &[Span]| {
Expand Down
17 changes: 13 additions & 4 deletions compiler/rustc_pattern_analysis/src/rustc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use rustc_middle::mir::interpret::Scalar;
use rustc_middle::mir::{self, Const};
use rustc_middle::thir::{FieldPat, Pat, PatKind, PatRange, PatRangeBoundary};
use rustc_middle::ty::layout::IntegerExt;
use rustc_middle::ty::TypeVisitableExt;
use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, VariantDef};
use rustc_span::ErrorGuaranteed;
use rustc_span::{Span, DUMMY_SP};
Expand Down Expand Up @@ -303,7 +304,10 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> {
///
/// See [`crate::constructor`] for considerations of emptiness.
#[instrument(level = "debug", skip(self), ret)]
pub fn ctors_for_ty(&self, ty: RevealedTy<'tcx>) -> ConstructorSet<'p, 'tcx> {
pub fn ctors_for_ty(
&self,
ty: RevealedTy<'tcx>,
) -> Result<ConstructorSet<'p, 'tcx>, ErrorGuaranteed> {
let cx = self;
let make_uint_range = |start, end| {
IntRange::from_range(
Expand All @@ -312,9 +316,11 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> {
RangeEnd::Included,
)
};
// Abort on type error.
ty.error_reported()?;
// This determines the set of all possible constructors for the type `ty`. For numbers,
// arrays and slices we use ranges and variable-length slices when appropriate.
match ty.kind() {
Ok(match ty.kind() {
ty::Bool => ConstructorSet::Bool,
ty::Char => {
// The valid Unicode Scalar Value ranges.
Expand Down Expand Up @@ -424,7 +430,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> {
ty::CoroutineWitness(_, _) | ty::Bound(_, _) | ty::Placeholder(_) | ty::Infer(_) => {
bug!("Encountered unexpected type in `ConstructorSet::for_ty`: {ty:?}")
}
}
})
}

pub(crate) fn lower_pat_range_bdy(
Expand Down Expand Up @@ -965,7 +971,10 @@ impl<'p, 'tcx> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> {
) -> &[Self::Ty] {
self.ctor_sub_tys(ctor, ty)
}
fn ctors_for_ty(&self, ty: Self::Ty) -> crate::constructor::ConstructorSet<Self> {
fn ctors_for_ty(
&self,
ty: Self::Ty,
) -> Result<crate::constructor::ConstructorSet<Self>, Self::Error> {
self.ctors_for_ty(ty)
}

Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_pattern_analysis/src/usefulness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -753,7 +753,7 @@ impl<'a, 'p, Cx: TypeCx> PlaceCtxt<'a, 'p, Cx> {
pub(crate) fn ctor_sub_tys(&self, ctor: &Constructor<Cx>) -> &[Cx::Ty] {
self.mcx.tycx.ctor_sub_tys(ctor, self.ty)
}
pub(crate) fn ctors_for_ty(&self) -> ConstructorSet<Cx> {
pub(crate) fn ctors_for_ty(&self) -> Result<ConstructorSet<Cx>, Cx::Error> {
self.mcx.tycx.ctors_for_ty(self.ty)
}
}
Expand Down Expand Up @@ -1383,7 +1383,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(

// Analyze the constructors present in this column.
let ctors = matrix.heads().map(|p| p.ctor());
let ctors_for_ty = pcx.ctors_for_ty();
let ctors_for_ty = pcx.ctors_for_ty()?;
let is_integers = matches!(ctors_for_ty, ConstructorSet::Integers { .. }); // For diagnostics.
let split_set = ctors_for_ty.split(pcx, ctors);
let all_missing = split_set.present.is_empty();
Expand Down
13 changes: 13 additions & 0 deletions tests/ui/pattern/usefulness/issue-119493-type-error-ice.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
fn main() {}

fn foo() {
#[derive(Copy, Clone)]
struct Foo(NonExistent);
//~^ ERROR cannot find type
//~| ERROR cannot find type

type U = impl Copy;
//~^ ERROR `impl Trait` in type aliases is unstable
let foo: U = Foo(());
let Foo(()) = foo;
}
30 changes: 30 additions & 0 deletions tests/ui/pattern/usefulness/issue-119493-type-error-ice.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
error[E0412]: cannot find type `NonExistent` in this scope
--> $DIR/issue-119493-type-error-ice.rs:5:16
|
LL | struct Foo(NonExistent);
| ^^^^^^^^^^^ not found in this scope

error[E0412]: cannot find type `NonExistent` in this scope
--> $DIR/issue-119493-type-error-ice.rs:5:16
|
LL | struct Foo(NonExistent);
| ^^^^^^^^^^^ not found in this scope
|
help: you might be missing a type parameter
|
LL | struct Foo<NonExistent>(NonExistent);
| +++++++++++++

error[E0658]: `impl Trait` in type aliases is unstable
--> $DIR/issue-119493-type-error-ice.rs:9:14
|
LL | type U = impl Copy;
| ^^^^^^^^^
|
= note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
= help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable

error: aborting due to 3 previous errors

Some errors have detailed explanations: E0412, E0658.
For more information about an error, try `rustc --explain E0412`.

0 comments on commit 4b2e8bc

Please sign in to comment.