Skip to content

Commit e461d2e

Browse files
committed
Beta backport of PR rust-lang#73005 (obligation error impl candidate)
1 parent 1dc0f6d commit e461d2e

File tree

5 files changed

+55
-181
lines changed

5 files changed

+55
-181
lines changed

src/librustc_trait_selection/traits/select.rs

+18
Original file line numberDiff line numberDiff line change
@@ -1173,6 +1173,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
11731173
// who might care about this case, like coherence, should use
11741174
// that function).
11751175
if candidates.is_empty() {
1176+
// If there's an error type, 'downgrade' our result from
1177+
// `Err(Unimplemented)` to `Ok(None)`. This helps us avoid
1178+
// emitting additional spurious errors, since we're guaranteed
1179+
// to have emitted at least one.
1180+
if stack.obligation.references_error() {
1181+
debug!("no results for error type, treating as ambiguous");
1182+
return Ok(None);
1183+
}
11761184
return Err(Unimplemented);
11771185
}
11781186

@@ -1697,6 +1705,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
16971705
) -> Result<(), SelectionError<'tcx>> {
16981706
debug!("assemble_candidates_from_impls(obligation={:?})", obligation);
16991707

1708+
// Essentially any user-written impl will match with an error type,
1709+
// so creating `ImplCandidates` isn't useful. However, we might
1710+
// end up finding a candidate elsewhere (e.g. a `BuiltinCandidate` for `Sized)
1711+
// This helps us avoid overflow: see issue #72839
1712+
// Since compilation is already guaranteed to fail, this is just
1713+
// to try to show the 'nicest' possible errors to the user.
1714+
if obligation.references_error() {
1715+
return Ok(());
1716+
}
1717+
17001718
self.tcx().for_each_relevant_impl(
17011719
obligation.predicate.def_id(),
17021720
obligation.predicate.skip_binder().trait_ref.self_ty(),

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)