Skip to content

Commit

Permalink
Don't create impl candidates when obligation contains errors
Browse files Browse the repository at this point in the history
Fixes rust-lang#72839

In PR rust-lang#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.
  • Loading branch information
Aaron1011 committed Jun 4, 2020
1 parent 3d5d0f8 commit 7f7729d
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 0 deletions.
10 changes: 10 additions & 0 deletions src/librustc_trait_selection/traits/select/candidate_assembly.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
) -> Result<(), SelectionError<'tcx>> {
debug!("assemble_candidates_from_impls(obligation={:?})", obligation);

// Essentially any user-written impl will match with an error type,
// so creating `ImplCandidates` isn't useful. However, we might
// end up finding a candidate elsewhere (e.g. a `BuiltinCandidate` for `Sized)
// This helps us avoid overflow: see issue #72839
// Since compilation is already guarnateed to fail, this is just
// to try to show the 'nicest' possible errors to the user.
if obligation.references_error() {
return Ok(());
}

self.tcx().for_each_relevant_impl(
obligation.predicate.def_id(),
obligation.predicate.skip_binder().trait_ref.self_ty(),
Expand Down
19 changes: 19 additions & 0 deletions src/test/ui/issues/issue-72839-error-overflow.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Regression test for issue #72839
// Tests that we do not overflow during trait selection after
// a type error occurs
use std::ops::Rem;
trait Foo {}
struct MyStruct<T>(T);

impl<T, U> Rem<MyStruct<T>> for MyStruct<U> where MyStruct<U>: Rem<MyStruct<T>> {
type Output = u8;
fn rem(self, _: MyStruct<T>) -> Self::Output {
panic!()
}
}

fn main() {}

fn foo() {
if missing_var % 8 == 0 {} //~ ERROR cannot find
}
9 changes: 9 additions & 0 deletions src/test/ui/issues/issue-72839-error-overflow.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error[E0425]: cannot find value `missing_var` in this scope
--> $DIR/issue-72839-error-overflow.rs:18:8
|
LL | if missing_var % 8 == 0 {}
| ^^^^^^^^^^^ not found in this scope

error: aborting due to previous error

For more information about this error, try `rustc --explain E0425`.

0 comments on commit 7f7729d

Please sign in to comment.