about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-05-16 02:34:32 +0000
committerbors <bors@rust-lang.org>2025-05-16 02:34:32 +0000
commit7e19eef048ba58c28c70afbf5f95da4829c15796 (patch)
tree73037a0ea9f5cc6608d4e293a5a175bf70b231c9
parent6d1875f99b2d5c1499410505f4233fbf8dbdc23b (diff)
parentdf479588945119d2e356fdfef21a5d2094ce9499 (diff)
downloadrust-7e19eef048ba58c28c70afbf5f95da4829c15796.tar.gz
rust-7e19eef048ba58c28c70afbf5f95da4829c15796.zip
Auto merge of #140557 - compiler-errors:remove-wf-hack, r=lcnr
Remove manual WF hack

We do not need this hack anymore since we fixed the candidate selection problems with `Sized` bounds. We prefer built-in sized bounds now since #138176, which fixes the only regression this hack was intended to fix.

While this theoretically is broken for some code, for example, when there a param-env bound that shadows an impl or built-in trait, we don't see it in practice and IMO it's not worth the burden of having to maintain this wart in `compare_method_predicate_entailment`.

The code that regresses is, for example:

```rust
trait Bar<'a> {}

trait Foo<'a, T> {
    fn method(&self)
    where
        Self: Bar<'a>;
}

struct W<'a, T>(&'a T)
where
    Self: Bar<'a>;

impl<'a, 'b, T> Bar<'a> for W<'b, T> {}

impl<'a, 'b, T> Foo<'a, T> for W<'b, T> {
    fn method(&self) {}
}
```

Specifically, I don't believe this is really going to be encountered in practice. For this to fail, there must be a where clause in the *trait method* that would shadow an impl or built-in (non-`Sized`) candidate in the trait, and this shadowing would need to be encountered when solving a nested WF goal from the impl self type.

See #108544 for the original regression. Crater run is clean!

r? lcnr
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs65
-rw-r--r--tests/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-88022.rs6
-rw-r--r--tests/ui/dropck/explicit-drop-bounds.bad1.stderr18
-rw-r--r--tests/ui/dropck/explicit-drop-bounds.bad2.stderr22
-rw-r--r--tests/ui/dropck/explicit-drop-bounds.rs2
-rw-r--r--tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.rs4
-rw-r--r--tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr44
7 files changed, 89 insertions, 72 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index fb67f2fd223..2ee41e2efbd 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -3,7 +3,7 @@ use std::borrow::Cow;
 use std::iter;
 
 use hir::def_id::{DefId, DefIdMap, LocalDefId};
-use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
+use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
 use rustc_errors::codes::*;
 use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, pluralize, struct_span_code_err};
 use rustc_hir::def::{DefKind, Res};
@@ -356,61 +356,14 @@ fn compare_method_predicate_entailment<'tcx>(
     }
 
     if !(impl_sig, trait_sig).references_error() {
-        // Select obligations to make progress on inference before processing
-        // the wf obligation below.
-        // FIXME(-Znext-solver): Not needed when the hack below is removed.
-        let errors = ocx.select_where_possible();
-        if !errors.is_empty() {
-            let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
-            return Err(reported);
-        }
-
-        // See #108544. Annoying, we can end up in cases where, because of winnowing,
-        // we pick param env candidates over a more general impl, leading to more
-        // stricter lifetime requirements than we would otherwise need. This can
-        // trigger the lint. Instead, let's only consider type outlives and
-        // region outlives obligations.
-        //
-        // FIXME(-Znext-solver): Try removing this hack again once the new
-        // solver is stable. We should just be able to register a WF pred for
-        // the fn sig.
-        let mut wf_args: smallvec::SmallVec<[_; 4]> =
-            unnormalized_impl_sig.inputs_and_output.iter().map(|ty| ty.into()).collect();
-        // Annoyingly, asking for the WF predicates of an array (with an unevaluated const (only?))
-        // will give back the well-formed predicate of the same array.
-        let mut wf_args_seen: FxHashSet<_> = wf_args.iter().copied().collect();
-        while let Some(term) = wf_args.pop() {
-            let Some(obligations) = rustc_trait_selection::traits::wf::obligations(
-                infcx,
-                param_env,
-                impl_m_def_id,
-                0,
-                term,
-                impl_m_span,
-            ) else {
-                continue;
-            };
-            for obligation in obligations {
-                debug!(?obligation);
-                match obligation.predicate.kind().skip_binder() {
-                    // We need to register Projection oblgiations too, because we may end up with
-                    // an implied `X::Item: 'a`, which gets desugared into `X::Item = ?0`, `?0: 'a`.
-                    // If we only register the region outlives obligation, this leads to an unconstrained var.
-                    // See `implied_bounds_entailment_alias_var.rs` test.
-                    ty::PredicateKind::Clause(
-                        ty::ClauseKind::RegionOutlives(..)
-                        | ty::ClauseKind::TypeOutlives(..)
-                        | ty::ClauseKind::Projection(..),
-                    ) => ocx.register_obligation(obligation),
-                    ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
-                        if wf_args_seen.insert(term) {
-                            wf_args.push(term)
-                        }
-                    }
-                    _ => {}
-                }
-            }
-        }
+        ocx.register_obligation(traits::Obligation::new(
+            infcx.tcx,
+            cause,
+            param_env,
+            ty::ClauseKind::WellFormed(
+                Ty::new_fn_ptr(tcx, ty::Binder::dummy(unnormalized_impl_sig)).into(),
+            ),
+        ));
     }
 
     // Check that all obligations are satisfied by the implementation's
diff --git a/tests/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-88022.rs b/tests/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-88022.rs
index 99eb92f432c..76f6aaee6dc 100644
--- a/tests/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-88022.rs
+++ b/tests/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-88022.rs
@@ -15,12 +15,14 @@ where
 
 impl<'a, T, const S: usize> Iterator for BufferIter<'a, T, S> {
     //~^ error: the trait bound
-    //~^^ error: unconstrained generic constant
+    //~| error: unconstrained generic constant
     type Item = &'a T;
 
     fn next(&mut self) -> Option<Self::Item> {
         //~^ error: the trait bound
-        //~^^ error: unconstrained generic constant
+        //~| error: unconstrained generic constant
+        //~| error: the trait bound
+        //~| error: unconstrained generic constant
         None
     }
 }
diff --git a/tests/ui/dropck/explicit-drop-bounds.bad1.stderr b/tests/ui/dropck/explicit-drop-bounds.bad1.stderr
index 12d7f5b6cd3..28d7546d0c9 100644
--- a/tests/ui/dropck/explicit-drop-bounds.bad1.stderr
+++ b/tests/ui/dropck/explicit-drop-bounds.bad1.stderr
@@ -15,6 +15,22 @@ LL |     [T; 1]: Copy, T: std::marker::Copy // But `[T; 1]: Copy` does not imply
    |                   ++++++++++++++++++++
 
 error[E0277]: the trait bound `T: Copy` is not satisfied
+  --> $DIR/explicit-drop-bounds.rs:32:5
+   |
+LL |     fn drop(&mut self) {}
+   |     ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
+   |
+note: required by a bound in `DropMe`
+  --> $DIR/explicit-drop-bounds.rs:7:18
+   |
+LL | struct DropMe<T: Copy>(T);
+   |                  ^^^^ required by this bound in `DropMe`
+help: consider further restricting type parameter `T` with trait `Copy`
+   |
+LL |     [T; 1]: Copy, T: std::marker::Copy // But `[T; 1]: Copy` does not imply `T: Copy`
+   |                   ++++++++++++++++++++
+
+error[E0277]: the trait bound `T: Copy` is not satisfied
   --> $DIR/explicit-drop-bounds.rs:32:18
    |
 LL |     fn drop(&mut self) {}
@@ -30,6 +46,6 @@ help: consider further restricting type parameter `T` with trait `Copy`
 LL |     [T; 1]: Copy, T: std::marker::Copy // But `[T; 1]: Copy` does not imply `T: Copy`
    |                   ++++++++++++++++++++
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/dropck/explicit-drop-bounds.bad2.stderr b/tests/ui/dropck/explicit-drop-bounds.bad2.stderr
index 5851731e834..c363676edea 100644
--- a/tests/ui/dropck/explicit-drop-bounds.bad2.stderr
+++ b/tests/ui/dropck/explicit-drop-bounds.bad2.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `T: Copy` is not satisfied
-  --> $DIR/explicit-drop-bounds.rs:37:18
+  --> $DIR/explicit-drop-bounds.rs:38:18
    |
 LL | impl<T> Drop for DropMe<T>
    |                  ^^^^^^^^^ the trait `Copy` is not implemented for `T`
@@ -15,7 +15,23 @@ LL | impl<T: std::marker::Copy> Drop for DropMe<T>
    |       +++++++++++++++++++
 
 error[E0277]: the trait bound `T: Copy` is not satisfied
-  --> $DIR/explicit-drop-bounds.rs:40:18
+  --> $DIR/explicit-drop-bounds.rs:41:5
+   |
+LL |     fn drop(&mut self) {}
+   |     ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
+   |
+note: required by a bound in `DropMe`
+  --> $DIR/explicit-drop-bounds.rs:7:18
+   |
+LL | struct DropMe<T: Copy>(T);
+   |                  ^^^^ required by this bound in `DropMe`
+help: consider restricting type parameter `T` with trait `Copy`
+   |
+LL | impl<T: std::marker::Copy> Drop for DropMe<T>
+   |       +++++++++++++++++++
+
+error[E0277]: the trait bound `T: Copy` is not satisfied
+  --> $DIR/explicit-drop-bounds.rs:41:18
    |
 LL |     fn drop(&mut self) {}
    |                  ^^^^ the trait `Copy` is not implemented for `T`
@@ -30,6 +46,6 @@ help: consider restricting type parameter `T` with trait `Copy`
 LL | impl<T: std::marker::Copy> Drop for DropMe<T>
    |       +++++++++++++++++++
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/dropck/explicit-drop-bounds.rs b/tests/ui/dropck/explicit-drop-bounds.rs
index 6ddac4d314f..cd1d89ed9db 100644
--- a/tests/ui/dropck/explicit-drop-bounds.rs
+++ b/tests/ui/dropck/explicit-drop-bounds.rs
@@ -31,6 +31,7 @@ where
 {
     fn drop(&mut self) {}
     //[bad1]~^ ERROR the trait bound `T: Copy` is not satisfied
+    //[bad1]~| ERROR the trait bound `T: Copy` is not satisfied
 }
 
 #[cfg(bad2)]
@@ -39,6 +40,7 @@ impl<T> Drop for DropMe<T>
 {
     fn drop(&mut self) {}
     //[bad2]~^ ERROR the trait bound `T: Copy` is not satisfied
+    //[bad2]~| ERROR the trait bound `T: Copy` is not satisfied
 }
 
 fn main() {}
diff --git a/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.rs b/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.rs
index 6380449124f..3b297a9a662 100644
--- a/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.rs
+++ b/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.rs
@@ -30,7 +30,8 @@ where
     type Output = B;
     extern "rust-call" fn call_once(mut self, a: A) -> Self::Output {
     //~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument
-        self.call_mut(a)
+    //~| ERROR type parameter to bare `FnOnce` trait must be a tuple
+    self.call_mut(a)
         //~^ ERROR `A` is not a tuple
     }
 }
@@ -43,6 +44,7 @@ where
 {
     extern "rust-call" fn call_mut(&mut self, a: A) -> Self::Output {
     //~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument
+    //~| ERROR type parameter to bare `FnOnce` trait must be a tuple
         self.cache.get(&a).map(|a| a.clone()).unwrap_or_else(|| {
             let b = (self.fun)(self, a.clone());
             self.cache.insert(a, b.clone());
diff --git a/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr b/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr
index 3b051ef9a88..32a564e466b 100644
--- a/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr
+++ b/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr
@@ -11,8 +11,21 @@ help: consider further restricting type parameter `A` with unstable trait `Tuple
 LL |     A: Eq + Hash + Clone + std::marker::Tuple,
    |                          ++++++++++++++++++++
 
+error[E0059]: type parameter to bare `FnOnce` trait must be a tuple
+  --> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:31:5
+   |
+LL |     extern "rust-call" fn call_once(mut self, a: A) -> Self::Output {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `A`
+   |
+note: required by a bound in `FnOnce`
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
+help: consider further restricting type parameter `A` with unstable trait `Tuple`
+   |
+LL |     A: Eq + Hash + Clone + std::marker::Tuple,
+   |                          ++++++++++++++++++++
+
 error[E0059]: type parameter to bare `FnMut` trait must be a tuple
-  --> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:38:12
+  --> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:39:12
    |
 LL | impl<A, B> FnMut<A> for CachedFun<A, B>
    |            ^^^^^^^^ the trait `Tuple` is not implemented for `A`
@@ -24,6 +37,19 @@ help: consider further restricting type parameter `A` with unstable trait `Tuple
 LL |     A: Eq + Hash + Clone + std::marker::Tuple,
    |                          ++++++++++++++++++++
 
+error[E0059]: type parameter to bare `FnOnce` trait must be a tuple
+  --> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:45:5
+   |
+LL |     extern "rust-call" fn call_mut(&mut self, a: A) -> Self::Output {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `A`
+   |
+note: required by a bound in `FnOnce`
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
+help: consider further restricting type parameter `A` with unstable trait `Tuple`
+   |
+LL |     A: Eq + Hash + Clone + std::marker::Tuple,
+   |                          ++++++++++++++++++++
+
 error[E0277]: functions with the "rust-call" ABI must take a single non-self tuple argument
   --> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:31:5
    |
@@ -36,7 +62,7 @@ LL |     A: Eq + Hash + Clone + std::marker::Tuple,
    |                          ++++++++++++++++++++
 
 error[E0277]: functions with the "rust-call" ABI must take a single non-self tuple argument
-  --> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:44:5
+  --> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:45:5
    |
 LL |     extern "rust-call" fn call_mut(&mut self, a: A) -> Self::Output {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `A`
@@ -47,12 +73,12 @@ LL |     A: Eq + Hash + Clone + std::marker::Tuple,
    |                          ++++++++++++++++++++
 
 error[E0277]: `A` is not a tuple
-  --> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:33:23
+  --> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:34:19
    |
-LL |         self.call_mut(a)
-   |              -------- ^ the trait `Tuple` is not implemented for `A`
-   |              |
-   |              required by a bound introduced by this call
+LL |     self.call_mut(a)
+   |          -------- ^ the trait `Tuple` is not implemented for `A`
+   |          |
+   |          required by a bound introduced by this call
    |
 note: required by a bound in `call_mut`
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
@@ -62,7 +88,7 @@ LL |     A: Eq + Hash + Clone + std::marker::Tuple,
    |                          ++++++++++++++++++++
 
 error[E0277]: `i32` is not a tuple
-  --> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:57:26
+  --> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:59:26
    |
 LL |     cachedcoso.call_once(1);
    |                --------- ^ the trait `Tuple` is not implemented for `i32`
@@ -76,7 +102,7 @@ help: use a unary tuple instead
 LL |     cachedcoso.call_once((1,));
    |                          + ++
 
-error: aborting due to 6 previous errors
+error: aborting due to 8 previous errors
 
 Some errors have detailed explanations: E0059, E0277.
 For more information about an error, try `rustc --explain E0059`.