Skip to content

Commit f222b55

Browse files
authored
Rollup merge of #152816 - ShoyuVanilla:issue-151318, r=lcnr
Check for region dependent goals on type_op itself as well Fixes #151318 r? lcnr
2 parents d70f5bd + 5f3bdde commit f222b55

7 files changed

Lines changed: 146 additions & 1 deletion

File tree

compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,40 @@ where
9292
let value = infcx.commit_if_ok(|_| {
9393
let ocx = ObligationCtxt::new(infcx);
9494
let value = op(&ocx).map_err(|_| {
95-
infcx.dcx().span_delayed_bug(span, format!("error performing operation: {name}"))
95+
infcx.tcx.check_potentially_region_dependent_goals(root_def_id).err().unwrap_or_else(
96+
// FIXME: In this region-dependent context, `type_op` should only fail due to
97+
// region-dependent goals. Any other kind of failure indicates a bug and we
98+
// should ICE.
99+
//
100+
// In principle, all non-region errors are expected to be emitted before
101+
// borrowck. Such errors should taint the body and prevent borrowck from
102+
// running at all. However, this invariant does not currently hold.
103+
//
104+
// Consider:
105+
//
106+
// ```ignore (illustrative)
107+
// struct Foo<T>(T)
108+
// where
109+
// T: Iterator,
110+
// <T as Iterator>::Item: Default;
111+
//
112+
// fn foo<T>() -> Foo<T> {
113+
// loop {}
114+
// }
115+
// ```
116+
//
117+
// Here, `fn foo` ought to error and taint the body before MIR build, since
118+
// `Foo<T>` is not well-formed. However, we currently avoid checking this
119+
// during HIR typeck to prevent duplicate diagnostics.
120+
//
121+
// If we ICE here on any non-region-dependent failure, we would trigger ICEs
122+
// too often for such cases. For now, we emit a delayed bug instead.
123+
|| {
124+
infcx
125+
.dcx()
126+
.span_delayed_bug(span, format!("error performing operation: {name}"))
127+
},
128+
)
96129
})?;
97130
let errors = ocx.evaluate_obligations_error_on_ambiguity();
98131
if errors.is_empty() {
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error[E0284]: type annotations needed
2+
--> $DIR/ambiguity-due-to-uniquification-4.rs:17:47
3+
|
4+
LL | pub fn f<'a, 'b, T: Trait<'a> + Trait<'b>>(v: <T as Trait<'a>>::Type) {}
5+
| ^^^^^^^^^^^^^^^^^^^^^^ cannot infer type
6+
|
7+
= note: cannot satisfy `<T as Trait<'a>>::Type == _`
8+
9+
error[E0284]: type annotations needed
10+
--> $DIR/ambiguity-due-to-uniquification-4.rs:17:47
11+
|
12+
LL | pub fn f<'a, 'b, T: Trait<'a> + Trait<'b>>(v: <T as Trait<'a>>::Type) {}
13+
| ^^^^^^^^^^^^^^^^^^^^^^ cannot infer type
14+
|
15+
= note: cannot satisfy `<T as Trait<'a>>::Type == _`
16+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
17+
18+
error: aborting due to 2 previous errors
19+
20+
For more information about this error, try `rustc --explain E0284`.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0284]: type annotations needed: cannot normalize `<T as Trait<'_>>::Type`
2+
--> $DIR/ambiguity-due-to-uniquification-4.rs:17:44
3+
|
4+
LL | pub fn f<'a, 'b, T: Trait<'a> + Trait<'b>>(v: <T as Trait<'a>>::Type) {}
5+
| ^ cannot normalize `<T as Trait<'_>>::Type`
6+
7+
error: aborting due to 1 previous error
8+
9+
For more information about this error, try `rustc --explain E0284`.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//@ revisions: current next
2+
//@[next] compile-flags: -Znext-solver
3+
//@ ignore-compare-mode-next-solver (explicit revisions)
4+
5+
// A regression test for https://github.com/rust-lang/rust/issues/151318.
6+
//
7+
// Unlike in the previous other tests, this fails to compile with the old solver as well.
8+
// Although we were already stashing goals which depend on inference variables and then
9+
// reproving them at the end of HIR typeck to avoid causing an ICE during MIR borrowck,
10+
// it wasn't enough because the type op itself can result in an error due to uniquification,
11+
// e.g. while normalizing a projection type.
12+
13+
pub trait Trait<'a> {
14+
type Type;
15+
}
16+
17+
pub fn f<'a, 'b, T: Trait<'a> + Trait<'b>>(v: <T as Trait<'a>>::Type) {}
18+
//~^ ERROR type annotations needed
19+
//[current]~| ERROR type annotations needed
20+
21+
fn main() {}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error[E0277]: `T` is not an iterator
2+
--> $DIR/return-type-non-wf-no-ice.rs:13:16
3+
|
4+
LL | fn foo<T>() -> Foo<T> {
5+
| ^^^^^^ `T` is not an iterator
6+
|
7+
note: required by a bound in `Foo`
8+
--> $DIR/return-type-non-wf-no-ice.rs:10:8
9+
|
10+
LL | pub struct Foo<T>(T)
11+
| --- required by a bound in this struct
12+
LL | where
13+
LL | T: Iterator,
14+
| ^^^^^^^^ required by this bound in `Foo`
15+
help: consider restricting type parameter `T` with trait `Iterator`
16+
|
17+
LL | fn foo<T: std::iter::Iterator>() -> Foo<T> {
18+
| +++++++++++++++++++++
19+
20+
error: aborting due to 1 previous error
21+
22+
For more information about this error, try `rustc --explain E0277`.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error[E0277]: `T` is not an iterator
2+
--> $DIR/return-type-non-wf-no-ice.rs:13:16
3+
|
4+
LL | fn foo<T>() -> Foo<T> {
5+
| ^^^^^^ `T` is not an iterator
6+
|
7+
note: required by a bound in `Foo`
8+
--> $DIR/return-type-non-wf-no-ice.rs:10:8
9+
|
10+
LL | pub struct Foo<T>(T)
11+
| --- required by a bound in this struct
12+
LL | where
13+
LL | T: Iterator,
14+
| ^^^^^^^^ required by this bound in `Foo`
15+
help: consider restricting type parameter `T` with trait `Iterator`
16+
|
17+
LL | fn foo<T: std::iter::Iterator>() -> Foo<T> {
18+
| +++++++++++++++++++++
19+
20+
error: aborting due to 1 previous error
21+
22+
For more information about this error, try `rustc --explain E0277`.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//@ revisions: current next
2+
//@ ignore-compare-mode-next-solver (explicit revisions)
3+
//@ [next] compile-flags: -Znext-solver
4+
5+
// Ensure we do not ICE if a non-well-formed return type manages to slip past HIR typeck.
6+
// See <https://github.com/rust-lang/rust/pull/152816> for details.
7+
8+
pub struct Foo<T>(T)
9+
where
10+
T: Iterator,
11+
<T as Iterator>::Item: Default;
12+
13+
fn foo<T>() -> Foo<T> {
14+
//~^ ERROR: `T` is not an iterator
15+
loop {}
16+
}
17+
18+
fn main() {}

0 commit comments

Comments
 (0)