about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2023-06-23 15:58:09 +0000
committerMichael Goulet <michael@errs.io>2023-06-23 16:23:27 +0000
commitf12695b53b6b8e5105c3813f402404e12c38ca08 (patch)
treef19ff343ba5a8392ef2bdd22bdc9b3585e32c977
parent04075b32021932e3e8f6ab55d519b3b3494b6ef9 (diff)
downloadrust-f12695b53b6b8e5105c3813f402404e12c38ca08.tar.gz
rust-f12695b53b6b8e5105c3813f402404e12c38ca08.zip
Don't emit same goal as input during wf obligations
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs11
-rw-r--r--tests/ui/traits/new-solver/alias-bound-unsound.rs2
-rw-r--r--tests/ui/traits/new-solver/alias-bound-unsound.stderr14
3 files changed, 24 insertions, 3 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index e80d413d976..e96e89ce73c 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -77,12 +77,19 @@ pub fn unnormalized_obligations<'tcx>(
     param_env: ty::ParamEnv<'tcx>,
     arg: GenericArg<'tcx>,
 ) -> Option<Vec<traits::PredicateObligation<'tcx>>> {
+    debug_assert_eq!(arg, infcx.resolve_vars_if_possible(arg));
+
+    // However, if `arg` IS an unresolved inference variable, returns `None`,
+    // because we are not able to make any progress at all. This is to prevent
+    // "livelock" where we say "$0 is WF if $0 is WF".
+    if arg.is_non_region_infer() {
+        return None;
+    }
+
     if let ty::GenericArgKind::Lifetime(..) = arg.unpack() {
         return Some(vec![]);
     }
 
-    debug_assert_eq!(arg, infcx.resolve_vars_if_possible(arg));
-
     let mut wf = WfPredicates {
         infcx,
         param_env,
diff --git a/tests/ui/traits/new-solver/alias-bound-unsound.rs b/tests/ui/traits/new-solver/alias-bound-unsound.rs
index 00294c708f1..208d4ce966a 100644
--- a/tests/ui/traits/new-solver/alias-bound-unsound.rs
+++ b/tests/ui/traits/new-solver/alias-bound-unsound.rs
@@ -23,5 +23,7 @@ fn main() {
     drop(<() as Foo>::copy_me(&x));
     //~^ ERROR `<() as Foo>::Item: Copy` is not satisfied
     //~| ERROR `<() as Foo>::Item` is not well-formed
+    //~| ERROR `_` is not well-formed
+    //~| ERROR `_` is not well-formed
     println!("{x}");
 }
diff --git a/tests/ui/traits/new-solver/alias-bound-unsound.stderr b/tests/ui/traits/new-solver/alias-bound-unsound.stderr
index 9a43d2a6639..3c2ad8f12bd 100644
--- a/tests/ui/traits/new-solver/alias-bound-unsound.stderr
+++ b/tests/ui/traits/new-solver/alias-bound-unsound.stderr
@@ -19,6 +19,18 @@ error: the type `<() as Foo>::Item` is not well-formed
 LL |     drop(<() as Foo>::copy_me(&x));
    |          ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: the type `_` is not well-formed
+  --> $DIR/alias-bound-unsound.rs:23:5
+   |
+LL |     drop(<() as Foo>::copy_me(&x));
+   |     ^^^^
+
+error: the type `_` is not well-formed
+  --> $DIR/alias-bound-unsound.rs:23:10
+   |
+LL |     drop(<() as Foo>::copy_me(&x));
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0277`.