Skip to content

Commit 024f025

Browse files
authored
Rollup merge of #73005 - Aaron1011:fix/error-overflow, r=estebank
Don't create impl candidates when obligation contains errors Fixes #72839 In PR #72621, trait selection was modified to no longer bail out early when an error type was encountered. This allowed us treat `ty::Error` as `Sized`, causing us to avoid emitting a spurious "not sized" error after a type error had already occured. However, this means that we may now try to match an impl candidate against the error type. Since the error type will unify with almost anything, this can cause us to infinitely recurse (eventually triggering an overflow) when trying to verify certain `where` clauses. This commit causes us to skip generating any impl candidates when an error type is involved.
2 parents 8addb2e + ae42c91 commit 024f025

File tree

6 files changed

+55
-181
lines changed

6 files changed

+55
-181
lines changed

src/librustc_trait_selection/traits/select/candidate_assembly.rs

+10
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
331331
) -> Result<(), SelectionError<'tcx>> {
332332
debug!("assemble_candidates_from_impls(obligation={:?})", obligation);
333333

334+
// Essentially any user-written impl will match with an error type,
335+
// so creating `ImplCandidates` isn't useful. However, we might
336+
// end up finding a candidate elsewhere (e.g. a `BuiltinCandidate` for `Sized)
337+
// This helps us avoid overflow: see issue #72839
338+
// Since compilation is already guaranteed to fail, this is just
339+
// to try to show the 'nicest' possible errors to the user.
340+
if obligation.references_error() {
341+
return Ok(());
342+
}
343+
334344
self.tcx().for_each_relevant_impl(
335345
obligation.predicate.def_id(),
336346
obligation.predicate.skip_binder().trait_ref.self_ty(),

src/librustc_trait_selection/traits/select/mod.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1104,6 +1104,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
11041104
// who might care about this case, like coherence, should use
11051105
// that function).
11061106
if candidates.is_empty() {
1107+
// If there's an error type, 'downgrade' our result from
1108+
// `Err(Unimplemented)` to `Ok(None)`. This helps us avoid
1109+
// emitting additional spurious errors, since we're guaranteed
1110+
// to have emitted at least one.
1111+
if stack.obligation.references_error() {
1112+
debug!("no results for error type, treating as ambiguous");
1113+
return Ok(None);
1114+
}
11071115
return Err(Unimplemented);
11081116
}
11091117

src/test/ui/impl-trait/auto-trait-leak.rs

-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ fn main() {
1111
// return type, which can't depend on the obligation.
1212
fn cycle1() -> impl Clone {
1313
//~^ ERROR cycle detected
14-
//~| ERROR cycle detected
15-
//~| ERROR cycle detected
1614
send(cycle2().clone());
1715
//~^ ERROR cannot be sent between threads safely
1816

src/test/ui/impl-trait/auto-trait-leak.stderr

+9-179
Original file line numberDiff line numberDiff line change
@@ -36,37 +36,37 @@ LL | fn cycle1() -> impl Clone {
3636
| ^^^^^^^^^^^^^^^^^^^^^^^^^
3737
= note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
3838
note: ...which requires computing type of `cycle2::{{opaque}}#0`...
39-
--> $DIR/auto-trait-leak.rs:22:16
39+
--> $DIR/auto-trait-leak.rs:20:16
4040
|
4141
LL | fn cycle2() -> impl Clone {
4242
| ^^^^^^^^^^
4343
note: ...which requires borrow-checking `cycle2`...
44-
--> $DIR/auto-trait-leak.rs:22:1
44+
--> $DIR/auto-trait-leak.rs:20:1
4545
|
4646
LL | fn cycle2() -> impl Clone {
4747
| ^^^^^^^^^^^^^^^^^^^^^^^^^
4848
note: ...which requires processing `cycle2`...
49-
--> $DIR/auto-trait-leak.rs:22:1
49+
--> $DIR/auto-trait-leak.rs:20:1
5050
|
5151
LL | fn cycle2() -> impl Clone {
5252
| ^^^^^^^^^^^^^^^^^^^^^^^^^
5353
note: ...which requires processing MIR for `cycle2`...
54-
--> $DIR/auto-trait-leak.rs:22:1
54+
--> $DIR/auto-trait-leak.rs:20:1
5555
|
5656
LL | fn cycle2() -> impl Clone {
5757
| ^^^^^^^^^^^^^^^^^^^^^^^^^
5858
note: ...which requires unsafety-checking `cycle2`...
59-
--> $DIR/auto-trait-leak.rs:22:1
59+
--> $DIR/auto-trait-leak.rs:20:1
6060
|
6161
LL | fn cycle2() -> impl Clone {
6262
| ^^^^^^^^^^^^^^^^^^^^^^^^^
6363
note: ...which requires building MIR for `cycle2`...
64-
--> $DIR/auto-trait-leak.rs:22:1
64+
--> $DIR/auto-trait-leak.rs:20:1
6565
|
6666
LL | fn cycle2() -> impl Clone {
6767
| ^^^^^^^^^^^^^^^^^^^^^^^^^
6868
note: ...which requires type-checking `cycle2`...
69-
--> $DIR/auto-trait-leak.rs:22:1
69+
--> $DIR/auto-trait-leak.rs:20:1
7070
|
7171
LL | fn cycle2() -> impl Clone {
7272
| ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -84,178 +84,8 @@ LL | | Rc::new(String::from("foo"))
8484
LL | | }
8585
| |_^
8686

87-
error[E0391]: cycle detected when computing type of `cycle1::{{opaque}}#0`
88-
--> $DIR/auto-trait-leak.rs:12:16
89-
|
90-
LL | fn cycle1() -> impl Clone {
91-
| ^^^^^^^^^^
92-
|
93-
note: ...which requires borrow-checking `cycle1`...
94-
--> $DIR/auto-trait-leak.rs:12:1
95-
|
96-
LL | fn cycle1() -> impl Clone {
97-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
98-
note: ...which requires processing `cycle1`...
99-
--> $DIR/auto-trait-leak.rs:12:1
100-
|
101-
LL | fn cycle1() -> impl Clone {
102-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
103-
note: ...which requires processing MIR for `cycle1`...
104-
--> $DIR/auto-trait-leak.rs:12:1
105-
|
106-
LL | fn cycle1() -> impl Clone {
107-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
108-
note: ...which requires unsafety-checking `cycle1`...
109-
--> $DIR/auto-trait-leak.rs:12:1
110-
|
111-
LL | fn cycle1() -> impl Clone {
112-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
113-
note: ...which requires building MIR for `cycle1`...
114-
--> $DIR/auto-trait-leak.rs:12:1
115-
|
116-
LL | fn cycle1() -> impl Clone {
117-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
118-
note: ...which requires type-checking `cycle1`...
119-
--> $DIR/auto-trait-leak.rs:12:1
120-
|
121-
LL | fn cycle1() -> impl Clone {
122-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
123-
= note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
124-
note: ...which requires computing type of `cycle2::{{opaque}}#0`...
125-
--> $DIR/auto-trait-leak.rs:22:16
126-
|
127-
LL | fn cycle2() -> impl Clone {
128-
| ^^^^^^^^^^
129-
note: ...which requires borrow-checking `cycle2`...
130-
--> $DIR/auto-trait-leak.rs:22:1
131-
|
132-
LL | fn cycle2() -> impl Clone {
133-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
134-
note: ...which requires processing `cycle2`...
135-
--> $DIR/auto-trait-leak.rs:22:1
136-
|
137-
LL | fn cycle2() -> impl Clone {
138-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
139-
note: ...which requires processing MIR for `cycle2`...
140-
--> $DIR/auto-trait-leak.rs:22:1
141-
|
142-
LL | fn cycle2() -> impl Clone {
143-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
144-
note: ...which requires unsafety-checking `cycle2`...
145-
--> $DIR/auto-trait-leak.rs:22:1
146-
|
147-
LL | fn cycle2() -> impl Clone {
148-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
149-
note: ...which requires building MIR for `cycle2`...
150-
--> $DIR/auto-trait-leak.rs:22:1
151-
|
152-
LL | fn cycle2() -> impl Clone {
153-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
154-
note: ...which requires type-checking `cycle2`...
155-
--> $DIR/auto-trait-leak.rs:22:1
156-
|
157-
LL | fn cycle2() -> impl Clone {
158-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
159-
= note: ...which again requires computing type of `cycle1::{{opaque}}#0`, completing the cycle
160-
note: cycle used when checking item types in top-level module
161-
--> $DIR/auto-trait-leak.rs:1:1
162-
|
163-
LL | / use std::cell::Cell;
164-
LL | | use std::rc::Rc;
165-
LL | |
166-
LL | | fn send<T: Send>(_: T) {}
167-
... |
168-
LL | | Rc::new(String::from("foo"))
169-
LL | | }
170-
| |_^
171-
172-
error[E0391]: cycle detected when computing type of `cycle1::{{opaque}}#0`
173-
--> $DIR/auto-trait-leak.rs:12:16
174-
|
175-
LL | fn cycle1() -> impl Clone {
176-
| ^^^^^^^^^^
177-
|
178-
note: ...which requires borrow-checking `cycle1`...
179-
--> $DIR/auto-trait-leak.rs:12:1
180-
|
181-
LL | fn cycle1() -> impl Clone {
182-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
183-
note: ...which requires processing `cycle1`...
184-
--> $DIR/auto-trait-leak.rs:12:1
185-
|
186-
LL | fn cycle1() -> impl Clone {
187-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
188-
note: ...which requires processing MIR for `cycle1`...
189-
--> $DIR/auto-trait-leak.rs:12:1
190-
|
191-
LL | fn cycle1() -> impl Clone {
192-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
193-
note: ...which requires unsafety-checking `cycle1`...
194-
--> $DIR/auto-trait-leak.rs:12:1
195-
|
196-
LL | fn cycle1() -> impl Clone {
197-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
198-
note: ...which requires building MIR for `cycle1`...
199-
--> $DIR/auto-trait-leak.rs:12:1
200-
|
201-
LL | fn cycle1() -> impl Clone {
202-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
203-
note: ...which requires type-checking `cycle1`...
204-
--> $DIR/auto-trait-leak.rs:12:1
205-
|
206-
LL | fn cycle1() -> impl Clone {
207-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
208-
= note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
209-
note: ...which requires computing type of `cycle2::{{opaque}}#0`...
210-
--> $DIR/auto-trait-leak.rs:22:16
211-
|
212-
LL | fn cycle2() -> impl Clone {
213-
| ^^^^^^^^^^
214-
note: ...which requires borrow-checking `cycle2`...
215-
--> $DIR/auto-trait-leak.rs:22:1
216-
|
217-
LL | fn cycle2() -> impl Clone {
218-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
219-
note: ...which requires processing `cycle2`...
220-
--> $DIR/auto-trait-leak.rs:22:1
221-
|
222-
LL | fn cycle2() -> impl Clone {
223-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
224-
note: ...which requires processing MIR for `cycle2`...
225-
--> $DIR/auto-trait-leak.rs:22:1
226-
|
227-
LL | fn cycle2() -> impl Clone {
228-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
229-
note: ...which requires unsafety-checking `cycle2`...
230-
--> $DIR/auto-trait-leak.rs:22:1
231-
|
232-
LL | fn cycle2() -> impl Clone {
233-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
234-
note: ...which requires building MIR for `cycle2`...
235-
--> $DIR/auto-trait-leak.rs:22:1
236-
|
237-
LL | fn cycle2() -> impl Clone {
238-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
239-
note: ...which requires type-checking `cycle2`...
240-
--> $DIR/auto-trait-leak.rs:22:1
241-
|
242-
LL | fn cycle2() -> impl Clone {
243-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
244-
= note: ...which again requires computing type of `cycle1::{{opaque}}#0`, completing the cycle
245-
note: cycle used when checking item types in top-level module
246-
--> $DIR/auto-trait-leak.rs:1:1
247-
|
248-
LL | / use std::cell::Cell;
249-
LL | | use std::rc::Rc;
250-
LL | |
251-
LL | | fn send<T: Send>(_: T) {}
252-
... |
253-
LL | | Rc::new(String::from("foo"))
254-
LL | | }
255-
| |_^
256-
25787
error[E0277]: `std::rc::Rc<std::string::String>` cannot be sent between threads safely
258-
--> $DIR/auto-trait-leak.rs:16:5
88+
--> $DIR/auto-trait-leak.rs:14:5
25989
|
26090
LL | fn send<T: Send>(_: T) {}
26191
| ---- required by this bound in `send`
@@ -269,7 +99,7 @@ LL | fn cycle2() -> impl Clone {
26999
= help: within `impl std::clone::Clone`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<std::string::String>`
270100
= note: required because it appears within the type `impl std::clone::Clone`
271101

272-
error: aborting due to 4 previous errors
102+
error: aborting due to 2 previous errors
273103

274104
Some errors have detailed explanations: E0277, E0391.
275105
For more information about an error, try `rustc --explain E0277`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Regression test for issue #72839
2+
// Tests that we do not overflow during trait selection after
3+
// a type error occurs
4+
use std::ops::Rem;
5+
trait Foo {}
6+
struct MyStruct<T>(T);
7+
8+
impl<T, U> Rem<MyStruct<T>> for MyStruct<U> where MyStruct<U>: Rem<MyStruct<T>> {
9+
type Output = u8;
10+
fn rem(self, _: MyStruct<T>) -> Self::Output {
11+
panic!()
12+
}
13+
}
14+
15+
fn main() {}
16+
17+
fn foo() {
18+
if missing_var % 8 == 0 {} //~ ERROR cannot find
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0425]: cannot find value `missing_var` in this scope
2+
--> $DIR/issue-72839-error-overflow.rs:18:8
3+
|
4+
LL | if missing_var % 8 == 0 {}
5+
| ^^^^^^^^^^^ not found in this scope
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0425`.

0 commit comments

Comments
 (0)