Skip to content

Commit

Permalink
Turn eager normalization errors to delayed errors
Browse files Browse the repository at this point in the history
When normalizing `union`s with fields coming from associated types that
don't satisfy trait bounds, avoid ICEing by using `delay_span_bug()`
instead of `bug!()`.

Fix #81199.
  • Loading branch information
estebank committed Aug 25, 2021
1 parent 958d788 commit 717f97c
Show file tree
Hide file tree
Showing 9 changed files with 150 additions and 2 deletions.
8 changes: 7 additions & 1 deletion compiler/rustc_passes/src/stability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -835,7 +835,13 @@ impl Visitor<'tcx> for Checker<'tcx> {
let ty = self.tcx.type_of(item.def_id);
let (adt_def, substs) = match ty.kind() {
ty::Adt(adt_def, substs) => (adt_def, substs),
_ => bug!(),
_ => {
self.tcx.sess.delay_span_bug(
item.span,
&format!("unexpected type kind {:?} (`{:?}`)", ty, ty.kind()),
);
return;
}
};

// Non-`Copy` fields are unstable, except for `ManuallyDrop`.
Expand Down
9 changes: 8 additions & 1 deletion compiler/rustc_traits/src/normalize_erasing_regions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt, TypeFoldable};
use rustc_span::DUMMY_SP;
use rustc_trait_selection::traits::query::normalize::AtExt;
use rustc_trait_selection::traits::{Normalized, ObligationCause};
use std::sync::atomic::Ordering;
Expand Down Expand Up @@ -51,7 +52,13 @@ fn normalize_after_erasing_regions<'tcx, T: TypeFoldable<'tcx> + PartialEq + Cop
debug_assert!(!erased.needs_infer(), "{:?}", erased);
erased
}
Err(NoSolution) => bug!("could not fully normalize `{:?}`", value),
Err(NoSolution) => {
infcx
.tcx
.sess
.delay_span_bug(DUMMY_SP, &format!("could not fully normalize `{:?}`", value));
value
}
}
})
}
Expand Down
21 changes: 21 additions & 0 deletions src/test/ui/union/normalization-failure-issue-81199-autofix.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// run-rustfix
#[allow(dead_code)]
#[repr(C)]
union PtrRepr<T: ?Sized + Pointee> {
const_ptr: *const T,
mut_ptr: *mut T,
components: std::mem::ManuallyDrop<PtrComponents<T>>,
//~^ ERROR the trait bound `T: Pointee` is not satisfied
}

#[repr(C)]
struct PtrComponents<T: Pointee + ?Sized> {
data_address: *const (),
metadata: <T as Pointee>::Metadata,
}

pub trait Pointee {
type Metadata;
}

fn main() {}
21 changes: 21 additions & 0 deletions src/test/ui/union/normalization-failure-issue-81199-autofix.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// run-rustfix
#[allow(dead_code)]
#[repr(C)]
union PtrRepr<T: ?Sized> {
const_ptr: *const T,
mut_ptr: *mut T,
components: std::mem::ManuallyDrop<PtrComponents<T>>,
//~^ ERROR the trait bound `T: Pointee` is not satisfied
}

#[repr(C)]
struct PtrComponents<T: Pointee + ?Sized> {
data_address: *const (),
metadata: <T as Pointee>::Metadata,
}

pub trait Pointee {
type Metadata;
}

fn main() {}
19 changes: 19 additions & 0 deletions src/test/ui/union/normalization-failure-issue-81199-autofix.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
error[E0277]: the trait bound `T: Pointee` is not satisfied
--> $DIR/normalization-failure-issue-81199-autofix.rs:7:40
|
LL | components: std::mem::ManuallyDrop<PtrComponents<T>>,
| ^^^^^^^^^^^^^^^^ the trait `Pointee` is not implemented for `T`
|
note: required by a bound in `PtrComponents`
--> $DIR/normalization-failure-issue-81199-autofix.rs:12:25
|
LL | struct PtrComponents<T: Pointee + ?Sized> {
| ^^^^^^^ required by this bound in `PtrComponents`
help: consider further restricting this bound
|
LL | union PtrRepr<T: ?Sized + Pointee> {
| +++++++++

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
12 changes: 12 additions & 0 deletions src/test/ui/union/normalization-failure-issue-81199-min.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
union PtrRepr<T: ?Sized> {
const_ptr: *const T,
mut_ptr: *mut T,
components: <T as Pointee>::Metadata
//~^ ERROR the trait bound `T: Pointee` is not satisfied
}

pub trait Pointee {
type Metadata;
}

fn main() {}
14 changes: 14 additions & 0 deletions src/test/ui/union/normalization-failure-issue-81199-min.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error[E0277]: the trait bound `T: Pointee` is not satisfied
--> $DIR/normalization-failure-issue-81199-min.rs:4:17
|
LL | components: <T as Pointee>::Metadata
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Pointee` is not implemented for `T`
|
help: consider further restricting this bound
|
LL | union PtrRepr<T: ?Sized + Pointee> {
| +++++++++

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
19 changes: 19 additions & 0 deletions src/test/ui/union/normalization-failure-issue-81199.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#[repr(C)]
union PtrRepr<T: ?Sized> {
const_ptr: *const T,
mut_ptr: *mut T,
components: PtrComponents<T>,
//~^ ERROR the trait bound `T: Pointee` is not satisfied in `PtrComponents<T>`
}

#[repr(C)]
struct PtrComponents<T: Pointee + ?Sized> {
data_address: *const (),
metadata: <T as Pointee>::Metadata,
}

pub trait Pointee {
type Metadata;
}

fn main() {}
29 changes: 29 additions & 0 deletions src/test/ui/union/normalization-failure-issue-81199.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
error[E0277]: the trait bound `T: Pointee` is not satisfied in `PtrComponents<T>`
--> $DIR/normalization-failure-issue-81199.rs:5:17
|
LL | components: PtrComponents<T>,
| ^^^^^^^^^^^^^^^^ within `PtrComponents<T>`, the trait `Pointee` is not implemented for `T`
|
note: required because it appears within the type `PtrComponents<T>`
--> $DIR/normalization-failure-issue-81199.rs:10:8
|
LL | struct PtrComponents<T: Pointee + ?Sized> {
| ^^^^^^^^^^^^^
= note: no field of a union may have a dynamically sized type
= help: change the field's type to have a statically known size
help: consider further restricting this bound
|
LL | union PtrRepr<T: ?Sized + Pointee> {
| +++++++++
help: borrowed types always have a statically known size
|
LL | components: &PtrComponents<T>,
| +
help: the `Box` type always has a statically known size and allocates its contents in the heap
|
LL | components: Box<PtrComponents<T>>,
| ++++ +

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.

0 comments on commit 717f97c

Please sign in to comment.