Auto merge of #124811 - matthiaskrgr:rollup-4zpov13, r=matthiaskrgr

Rollup of 4 pull requests

Successful merges:

 - #124520 (Document that `create_dir_all` calls `mkdir`/`CreateDirW` multiple times)
 - #124724 (Prefer lower vtable candidates in select in new solver)
 - #124771 (Don't consider candidates with no failing where clauses when refining obligation causes in new solver)
 - #124808 (Use `super_fold` in `RegionsToStatic` visitor)

r? `@ghost`
`@rustbot` modify labels: rollup
diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
index 6600b92..c437ded 100644
--- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs
+++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
@@ -455,7 +455,7 @@
         I::Binder<T>: TypeSuperFoldable<I>,
     {
         self.binder.shift_in(1);
-        let t = t.fold_with(self);
+        let t = t.super_fold_with(self);
         self.binder.shift_out(1);
         t
     }
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs
index 16fe045..4d474b8 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs
@@ -58,6 +58,12 @@
             )));
         }
 
+        // Don't winnow until `Certainty::Yes` -- we don't need to winnow until
+        // codegen, and only on the good path.
+        if matches!(goal.result().unwrap(), Certainty::Maybe(..)) {
+            return ControlFlow::Break(Ok(None));
+        }
+
         // We need to winnow. See comments on `candidate_should_be_dropped_in_favor_of`.
         let mut i = 0;
         while i < candidates.len() {
@@ -86,7 +92,7 @@
     other: &inspect::InspectCandidate<'_, 'tcx>,
 ) -> bool {
     // Don't winnow until `Certainty::Yes` -- we don't need to winnow until
-    // codegen, technically.
+    // codegen, and only on the good path.
     if matches!(other.result().unwrap(), Certainty::Maybe(..)) {
         return false;
     }
@@ -105,13 +111,15 @@
             bug!("should not have assembled a CoherenceUnknowable candidate")
         }
 
+        // In the old trait solver, we arbitrarily choose lower vtable candidates
+        // over higher ones.
+        (
+            CandidateSource::BuiltinImpl(BuiltinImplSource::Object { vtable_base: a }),
+            CandidateSource::BuiltinImpl(BuiltinImplSource::Object { vtable_base: b }),
+        ) => a >= b,
         // Prefer dyn candidates over non-dyn candidates. This is necessary to
         // handle the unsoundness between `impl<T: ?Sized> Any for T` and `dyn Any: Any`.
         (
-            CandidateSource::BuiltinImpl(BuiltinImplSource::Object { .. }),
-            CandidateSource::BuiltinImpl(BuiltinImplSource::Object { .. }),
-        ) => false,
-        (
             CandidateSource::Impl(_) | CandidateSource::ParamEnv(_) | CandidateSource::AliasBound,
             CandidateSource::BuiltinImpl(BuiltinImplSource::Object { .. }),
         ) => true,
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs
index fd4b580..39d2ec4 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs
@@ -14,7 +14,7 @@
 use rustc_span::symbol::sym;
 
 use super::eval_ctxt::GenerateProofTree;
-use super::inspect::{ProofTreeInferCtxtExt, ProofTreeVisitor};
+use super::inspect::{InspectCandidate, InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor};
 use super::{Certainty, InferCtxtEvalExt};
 
 /// A trait engine using the new trait solver.
@@ -304,6 +304,46 @@
         self.obligation = old_obligation;
         res
     }
+
+    /// Filter out the candidates that aren't either error or ambiguous (depending
+    /// on what we are looking for), and also throw out candidates that have no
+    /// failing WC (or higher-ranked obligations, for which there should only be
+    /// one candidate anyways -- but I digress). This most likely means that the
+    /// goal just didn't unify at all, e.g. a param candidate with an alias in it.
+    fn non_trivial_candidates<'a>(
+        &self,
+        goal: &'a InspectGoal<'a, 'tcx>,
+    ) -> Vec<InspectCandidate<'a, 'tcx>> {
+        let mut candidates = goal
+            .candidates()
+            .into_iter()
+            .filter(|candidate| match self.consider_ambiguities {
+                true => matches!(candidate.result(), Ok(Certainty::Maybe(_))),
+                false => matches!(candidate.result(), Err(_)),
+            })
+            .collect::<Vec<_>>();
+
+        // If we have >1 candidate, one may still be due to "boring" reasons, like
+        // an alias-relate that failed to hold when deeply evaluated. We really
+        // don't care about reasons like this.
+        if candidates.len() > 1 {
+            candidates.retain(|candidate| {
+                goal.infcx().probe(|_| {
+                    candidate.instantiate_nested_goals(self.span()).iter().any(|nested_goal| {
+                        matches!(
+                            nested_goal.source(),
+                            GoalSource::ImplWhereBound | GoalSource::InstantiateHigherRanked
+                        ) && match self.consider_ambiguities {
+                            true => matches!(nested_goal.result(), Ok(Certainty::Maybe(_))),
+                            false => matches!(nested_goal.result(), Err(_)),
+                        }
+                    })
+                })
+            });
+        }
+
+        candidates
+    }
 }
 
 impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
@@ -314,11 +354,7 @@
     }
 
     fn visit_goal(&mut self, goal: &super::inspect::InspectGoal<'_, 'tcx>) -> Self::Result {
-        // FIXME: Throw out candidates that have no failing WC and >0 failing misc goal.
-        // This most likely means that the goal just didn't unify at all, e.g. a param
-        // candidate with an alias in it.
-        let candidates = goal.candidates();
-
+        let candidates = self.non_trivial_candidates(goal);
         let [candidate] = candidates.as_slice() else {
             return ControlFlow::Break(self.obligation.clone());
         };
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index 409ead0..a59faf5 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -2258,7 +2258,7 @@
 /// # Platform-specific behavior
 ///
 /// This function currently corresponds to the `mkdir` function on Unix
-/// and the `CreateDirectory` function on Windows.
+/// and the `CreateDirectoryW` function on Windows.
 /// Note that, this [may change in the future][changes].
 ///
 /// [changes]: io#platform-specific-behavior
@@ -2298,10 +2298,14 @@
 /// Recursively create a directory and all of its parent components if they
 /// are missing.
 ///
+/// If this function returns an error, some of the parent components might have
+/// been created already.
+///
 /// # Platform-specific behavior
 ///
-/// This function currently corresponds to the `mkdir` function on Unix
-/// and the `CreateDirectory` function on Windows.
+/// This function currently corresponds to multiple calls to the `mkdir`
+/// function on Unix and the `CreateDirectoryW` function on Windows.
+///
 /// Note that, this [may change in the future][changes].
 ///
 /// [changes]: io#platform-specific-behavior
diff --git a/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.rs b/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.rs
new file mode 100644
index 0000000..33a6d7a
--- /dev/null
+++ b/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.rs
@@ -0,0 +1,8 @@
+//@ compile-flags: -Znext-solver=coherence
+
+#[derive(Debug)]
+struct X<const FN: fn() = { || {} }>;
+//~^ ERROR using function pointers as const generic parameters is forbidden
+//~| ERROR using function pointers as const generic parameters is forbidden
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr b/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr
new file mode 100644
index 0000000..4eef8c0
--- /dev/null
+++ b/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr
@@ -0,0 +1,19 @@
+error: using function pointers as const generic parameters is forbidden
+  --> $DIR/const-region-infer-to-static-in-binder.rs:4:20
+   |
+LL | struct X<const FN: fn() = { || {} }>;
+   |                    ^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+
+error: using function pointers as const generic parameters is forbidden
+  --> $DIR/const-region-infer-to-static-in-binder.rs:4:20
+   |
+LL | struct X<const FN: fn() = { || {} }>;
+   |                    ^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/traits/next-solver/canonicalize-effect-var.rs b/tests/ui/traits/next-solver/canonical/effect-var.rs
similarity index 100%
rename from tests/ui/traits/next-solver/canonicalize-effect-var.rs
rename to tests/ui/traits/next-solver/canonical/effect-var.rs
diff --git a/tests/ui/traits/next-solver/canonical-int-var-eq-in-response.rs b/tests/ui/traits/next-solver/canonical/int-var-eq-in-response.rs
similarity index 100%
rename from tests/ui/traits/next-solver/canonical-int-var-eq-in-response.rs
rename to tests/ui/traits/next-solver/canonical/int-var-eq-in-response.rs
diff --git a/tests/ui/traits/next-solver/canonical-ty-var-eq-in-response.rs b/tests/ui/traits/next-solver/canonical/ty-var-eq-in-response.rs
similarity index 100%
rename from tests/ui/traits/next-solver/canonical-ty-var-eq-in-response.rs
rename to tests/ui/traits/next-solver/canonical/ty-var-eq-in-response.rs
diff --git a/tests/ui/traits/next-solver/diagnostics/where-clause-doesnt-apply.rs b/tests/ui/traits/next-solver/diagnostics/where-clause-doesnt-apply.rs
new file mode 100644
index 0000000..4737546
--- /dev/null
+++ b/tests/ui/traits/next-solver/diagnostics/where-clause-doesnt-apply.rs
@@ -0,0 +1,22 @@
+trait Foo {}
+trait Bar {}
+
+impl<T> Foo for T where T: Bar {}
+fn needs_foo(_: impl Foo) {}
+
+trait Mirror {
+    type Mirror;
+}
+impl<T> Mirror for T {
+    type Mirror = T;
+}
+
+// Make sure the `Alias: Foo` bound doesn't "shadow" the impl, since the
+// impl is really the only candidate we care about here for the purpose
+// of error reporting.
+fn hello<T>() where <T as Mirror>::Mirror: Foo {
+    needs_foo(());
+    //~^ ERROR the trait bound `(): Foo` is not satisfied
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/diagnostics/where-clause-doesnt-apply.stderr b/tests/ui/traits/next-solver/diagnostics/where-clause-doesnt-apply.stderr
new file mode 100644
index 0000000..77a0cc4
--- /dev/null
+++ b/tests/ui/traits/next-solver/diagnostics/where-clause-doesnt-apply.stderr
@@ -0,0 +1,22 @@
+error[E0277]: the trait bound `(): Foo` is not satisfied
+  --> $DIR/where-clause-doesnt-apply.rs:18:15
+   |
+LL |     needs_foo(());
+   |     --------- ^^ the trait `Bar` is not implemented for `()`, which is required by `(): Foo`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required for `()` to implement `Foo`
+  --> $DIR/where-clause-doesnt-apply.rs:4:9
+   |
+LL | impl<T> Foo for T where T: Bar {}
+   |         ^^^     ^          --- unsatisfied trait bound introduced here
+note: required by a bound in `needs_foo`
+  --> $DIR/where-clause-doesnt-apply.rs:5:22
+   |
+LL | fn needs_foo(_: impl Foo) {}
+   |                      ^^^ required by this bound in `needs_foo`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/normalize-supertrait.rs b/tests/ui/traits/normalize-supertrait.rs
index 1ab2b8e..3ba4a8b 100644
--- a/tests/ui/traits/normalize-supertrait.rs
+++ b/tests/ui/traits/normalize-supertrait.rs
@@ -4,6 +4,9 @@
 // comparing the supertrait `Derived<()>` to the expected trait.
 
 //@ build-pass
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
 
 trait Proj {
     type S;