Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/region.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ impl<'tcx> Region<'tcx> {
}
ty::ReError(_) => {
flags = flags | TypeFlags::HAS_FREE_REGIONS;
flags = flags | TypeFlags::HAS_ERROR;
flags = flags | TypeFlags::HAS_RE_ERROR;
}
}

Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_trait_selection/src/traits/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -659,7 +659,9 @@ fn project<'cx, 'tcx>(
)));
}

if let Err(guar) = obligation.predicate.error_reported() {
// We can still compute a projection type when there are only region errors,
// but type/const errors require early return.
if let Err(guar) = obligation.predicate.non_region_error_reported() {
return Ok(Projected::Progress(Progress::error_for_term(
selcx.tcx(),
obligation.predicate,
Expand Down
31 changes: 18 additions & 13 deletions compiler/rustc_type_ir/src/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,27 +91,32 @@ bitflags::bitflags! {
| TypeFlags::HAS_TY_INHERENT.bits()
| TypeFlags::HAS_CT_PROJECTION.bits();

/// Is a type or const error reachable?
const HAS_NON_REGION_ERROR = 1 << 15;
/// Is a region error reachable?
const HAS_RE_ERROR = 1 << 16;
/// Is an error type/lifetime/const reachable?
const HAS_ERROR = 1 << 15;
const HAS_ERROR = TypeFlags::HAS_NON_REGION_ERROR.bits()
| TypeFlags::HAS_RE_ERROR.bits();

/// Does this have any region that "appears free" in the type?
/// Basically anything but `ReBound` and `ReErased`.
const HAS_FREE_REGIONS = 1 << 16;
const HAS_FREE_REGIONS = 1 << 17;

/// Does this have any `ReBound` regions?
const HAS_RE_BOUND = 1 << 17;
const HAS_RE_BOUND = 1 << 18;
/// Does this have any `Bound` types?
const HAS_TY_BOUND = 1 << 18;
const HAS_TY_BOUND = 1 << 19;
/// Does this have any `ConstKind::Bound` consts?
const HAS_CT_BOUND = 1 << 19;
const HAS_CT_BOUND = 1 << 20;
/// Does this have any bound variables?
/// Used to check if a global bound is safe to evaluate.
const HAS_BOUND_VARS = TypeFlags::HAS_RE_BOUND.bits()
| TypeFlags::HAS_TY_BOUND.bits()
| TypeFlags::HAS_CT_BOUND.bits();

/// Does this have any `ReErased` regions?
const HAS_RE_ERASED = 1 << 20;
const HAS_RE_ERASED = 1 << 21;

/// Does this value have parameters/placeholders/inference variables which could be
/// replaced later, in a way that would change the results of `impl` specialization?
Expand All @@ -123,19 +128,19 @@ bitflags::bitflags! {
| TypeFlags::HAS_CT_INFER.bits();

/// Does this value have `InferTy::FreshTy/FreshIntTy/FreshFloatTy`?
const HAS_TY_FRESH = 1 << 21;
const HAS_TY_FRESH = 1 << 22;

/// Does this value have `InferConst::Fresh`?
const HAS_CT_FRESH = 1 << 22;
const HAS_CT_FRESH = 1 << 23;

/// Does this have any binders with bound vars (e.g. that need to be anonymized)?
const HAS_BINDER_VARS = 1 << 23;
const HAS_BINDER_VARS = 1 << 24;

/// Does this type have any coroutines in it?
const HAS_TY_CORO = 1 << 24;
const HAS_TY_CORO = 1 << 25;

/// Does this have have a `Bound(BoundVarIndexKind::Canonical, _)`?
const HAS_CANONICAL_BOUND = 1 << 25;
const HAS_CANONICAL_BOUND = 1 << 26;
}
}

Expand Down Expand Up @@ -240,7 +245,7 @@ impl<I: Interner> FlagComputation<I> {
| ty::Str
| ty::Foreign(..) => {}

ty::Error(_) => self.add_flags(TypeFlags::HAS_ERROR),
ty::Error(_) => self.add_flags(TypeFlags::HAS_NON_REGION_ERROR),

ty::Param(_) => {
self.add_flags(TypeFlags::HAS_TY_PARAM);
Expand Down Expand Up @@ -489,7 +494,7 @@ impl<I: Interner> FlagComputation<I> {
}
}
ty::ConstKind::Expr(e) => self.add_args(e.args().as_slice()),
ty::ConstKind::Error(_) => self.add_flags(TypeFlags::HAS_ERROR),
ty::ConstKind::Error(_) => self.add_flags(TypeFlags::HAS_NON_REGION_ERROR),
}
}

Expand Down
19 changes: 19 additions & 0 deletions compiler/rustc_type_ir/src/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,8 @@ pub trait TypeVisitableExt<I: Interner>: TypeVisitable<I> {

fn error_reported(&self) -> Result<(), I::ErrorGuaranteed>;

fn non_region_error_reported(&self) -> Result<(), I::ErrorGuaranteed>;

fn has_non_region_param(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_PARAM - TypeFlags::HAS_RE_PARAM)
}
Expand Down Expand Up @@ -352,6 +354,11 @@ pub trait TypeVisitableExt<I: Interner>: TypeVisitable<I> {
fn still_further_specializable(&self) -> bool {
self.has_type_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE)
}

/// True if a type or const error is reachable
fn has_non_region_error(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_NON_REGION_ERROR)
}
}

impl<I: Interner, T: TypeVisitable<I>> TypeVisitableExt<I> for T {
Expand All @@ -376,6 +383,18 @@ impl<I: Interner, T: TypeVisitable<I>> TypeVisitableExt<I> for T {
Ok(())
}
}

fn non_region_error_reported(&self) -> Result<(), I::ErrorGuaranteed> {
if self.has_non_region_error() {
if let ControlFlow::Break(guar) = self.visit_with(&mut HasErrorVisitor) {
Err(guar)
} else {
panic!("type flags said there was an non region error, but now there is not")
}
} else {
Ok(())
}
}
}

#[derive(Debug, PartialEq, Eq, Copy, Clone)]
Expand Down
3 changes: 2 additions & 1 deletion tests/ui/dropck/dropck-after-failed-type-lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
trait B {
type C<'a>;
fn d<E>() -> F<E> {
//~^ ERROR: the trait bound `E: B` is not satisfied
todo!()
}
}
struct F<G> {
h: Option<<G as B>::C>,
h: Option<<G as B>::C>, //~ ERROR: the trait bound `G: B` is not satisfied
//~^ ERROR missing generics for associated type `B::C`
}

Expand Down
24 changes: 21 additions & 3 deletions tests/ui/dropck/dropck-after-failed-type-lowering.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0107]: missing generics for associated type `B::C`
--> $DIR/dropck-after-failed-type-lowering.rs:10:25
--> $DIR/dropck-after-failed-type-lowering.rs:11:25
|
LL | h: Option<<G as B>::C>,
| ^ expected 1 lifetime argument
Expand All @@ -14,6 +14,24 @@ help: add missing lifetime argument
LL | h: Option<<G as B>::C<'a>>,
| ++++

error: aborting due to 1 previous error
error[E0277]: the trait bound `G: B` is not satisfied
--> $DIR/dropck-after-failed-type-lowering.rs:11:8
|
LL | h: Option<<G as B>::C>,
| ^^^^^^^^^^^^^^^^^^^ the trait `B` is not implemented for `G`
|
help: consider restricting type parameter `G` with trait `B`
|
LL | struct F<G: B> {
| +++

error[E0277]: the trait bound `E: B` is not satisfied
--> $DIR/dropck-after-failed-type-lowering.rs:5:18
|
LL | fn d<E>() -> F<E> {
| ^^^^ the trait `B` is not implemented for `E`

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0107`.
Some errors have detailed explanations: E0107, E0277.
For more information about an error, try `rustc --explain E0107`.
6 changes: 6 additions & 0 deletions tests/ui/unsized/thin-ptr-to-unsized-projection.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// This is a regression test for <https://github.com/rust-lang/rust/issues/152682>
struct Foo<'a>(<& /*'a*/ [fn()] as core::ops::Deref>::Target); // adding the lifetime solves the ice
//~^ ERROR: missing lifetime specifier [E0106]
const _: *const Foo = 0 as _;
//~^ ERROR: cannot cast `i32` to a pointer that is wide [E0606]
fn main() {}
23 changes: 23 additions & 0 deletions tests/ui/unsized/thin-ptr-to-unsized-projection.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
error[E0106]: missing lifetime specifier
--> $DIR/thin-ptr-to-unsized-projection.rs:2:17
|
LL | struct Foo<'a>(<& /*'a*/ [fn()] as core::ops::Deref>::Target); // adding the lifetime solves the ice
| ^ expected named lifetime parameter
|
help: consider using the `'a` lifetime
|
LL | struct Foo<'a>(<&'a /*'a*/ [fn()] as core::ops::Deref>::Target); // adding the lifetime solves the ice
| ++

error[E0606]: cannot cast `i32` to a pointer that is wide
--> $DIR/thin-ptr-to-unsized-projection.rs:4:28
|
LL | const _: *const Foo = 0 as _;
| - ^ creating a `*const Foo<'_>` requires both an address and a length
| |
| consider casting this expression to `*const ()`, then using `core::ptr::from_raw_parts`

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0106, E0606.
For more information about an error, try `rustc --explain E0106`.
Loading