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
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,40 @@ where
let value = infcx.commit_if_ok(|_| {
let ocx = ObligationCtxt::new(infcx);
let value = op(&ocx).map_err(|_| {
infcx.dcx().span_delayed_bug(span, format!("error performing operation: {name}"))
infcx.tcx.check_potentially_region_dependent_goals(root_def_id).err().unwrap_or_else(
// FIXME: In this region-dependent context, `type_op` should only fail due to
// region-dependent goals. Any other kind of failure indicates a bug and we
// should ICE.
//
// In principle, all non-region errors are expected to be emitted before
// borrowck. Such errors should taint the body and prevent borrowck from
// running at all. However, this invariant does not currently hold.
//
// Consider:
//
// ```ignore (illustrative)
// struct Foo<T>(T)
// where
// T: Iterator,
// <T as Iterator>::Item: Default;
//
// fn foo<T>() -> Foo<T> {
// loop {}
// }
// ```
//
// Here, `fn foo` ought to error and taint the body before MIR build, since
// `Foo<T>` is not well-formed. However, we currently avoid checking this
// during HIR typeck to prevent duplicate diagnostics.
//
// If we ICE here on any non-region-dependent failure, we would trigger ICEs
// too often for such cases. For now, we emit a delayed bug instead.
|| {
infcx
.dcx()
.span_delayed_bug(span, format!("error performing operation: {name}"))
},
)
})?;
let errors = ocx.evaluate_obligations_error_on_ambiguity();
if errors.is_empty() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
error[E0284]: type annotations needed
--> $DIR/ambiguity-due-to-uniquification-4.rs:17:47
|
LL | pub fn f<'a, 'b, T: Trait<'a> + Trait<'b>>(v: <T as Trait<'a>>::Type) {}
| ^^^^^^^^^^^^^^^^^^^^^^ cannot infer type
|
= note: cannot satisfy `<T as Trait<'a>>::Type == _`

error[E0284]: type annotations needed
--> $DIR/ambiguity-due-to-uniquification-4.rs:17:47
|
LL | pub fn f<'a, 'b, T: Trait<'a> + Trait<'b>>(v: <T as Trait<'a>>::Type) {}
| ^^^^^^^^^^^^^^^^^^^^^^ cannot infer type
|
= note: cannot satisfy `<T as Trait<'a>>::Type == _`
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0284`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error[E0284]: type annotations needed: cannot normalize `<T as Trait<'_>>::Type`
--> $DIR/ambiguity-due-to-uniquification-4.rs:17:44
|
LL | pub fn f<'a, 'b, T: Trait<'a> + Trait<'b>>(v: <T as Trait<'a>>::Type) {}
| ^ cannot normalize `<T as Trait<'_>>::Type`

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0284`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//@ revisions: current next
//@[next] compile-flags: -Znext-solver
//@ ignore-compare-mode-next-solver (explicit revisions)

// A regression test for https://github.com/rust-lang/rust/issues/151318.
//
// Unlike in the previous other tests, this fails to compile with the old solver as well.
// Although we were already stashing goals which depend on inference variables and then
// reproving them at the end of HIR typeck to avoid causing an ICE during MIR borrowck,
// it wasn't enough because the type op itself can result in an error due to uniquification,
// e.g. while normalizing a projection type.

pub trait Trait<'a> {
type Type;
}

pub fn f<'a, 'b, T: Trait<'a> + Trait<'b>>(v: <T as Trait<'a>>::Type) {}
//~^ ERROR type annotations needed
//[current]~| ERROR type annotations needed

fn main() {}
22 changes: 22 additions & 0 deletions tests/ui/wf/return-type-non-wf-no-ice.current.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
error[E0277]: `T` is not an iterator
--> $DIR/return-type-non-wf-no-ice.rs:13:16
|
LL | fn foo<T>() -> Foo<T> {
| ^^^^^^ `T` is not an iterator
|
note: required by a bound in `Foo`
--> $DIR/return-type-non-wf-no-ice.rs:10:8
|
LL | pub struct Foo<T>(T)
| --- required by a bound in this struct
LL | where
LL | T: Iterator,
| ^^^^^^^^ required by this bound in `Foo`
help: consider restricting type parameter `T` with trait `Iterator`
|
LL | fn foo<T: std::iter::Iterator>() -> Foo<T> {
| +++++++++++++++++++++

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0277`.
22 changes: 22 additions & 0 deletions tests/ui/wf/return-type-non-wf-no-ice.next.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
error[E0277]: `T` is not an iterator
--> $DIR/return-type-non-wf-no-ice.rs:13:16
|
LL | fn foo<T>() -> Foo<T> {
| ^^^^^^ `T` is not an iterator
|
note: required by a bound in `Foo`
--> $DIR/return-type-non-wf-no-ice.rs:10:8
|
LL | pub struct Foo<T>(T)
| --- required by a bound in this struct
LL | where
LL | T: Iterator,
| ^^^^^^^^ required by this bound in `Foo`
help: consider restricting type parameter `T` with trait `Iterator`
|
LL | fn foo<T: std::iter::Iterator>() -> Foo<T> {
| +++++++++++++++++++++

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0277`.
18 changes: 18 additions & 0 deletions tests/ui/wf/return-type-non-wf-no-ice.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@ [next] compile-flags: -Znext-solver

// Ensure we do not ICE if a non-well-formed return type manages to slip past HIR typeck.
// See <https://github.com/rust-lang/rust/pull/152816> for details.

pub struct Foo<T>(T)
where
T: Iterator,
<T as Iterator>::Item: Default;

fn foo<T>() -> Foo<T> {
//~^ ERROR: `T` is not an iterator
loop {}
}

fn main() {}
Loading