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
This commit is contained in:
commit
31110152e2
12 changed files with 137 additions and 15 deletions
|
@ -455,7 +455,7 @@ impl<I: Interner> TypeFolder<I> for RegionsToStatic<I> {
|
||||||
I::Binder<T>: TypeSuperFoldable<I>,
|
I::Binder<T>: TypeSuperFoldable<I>,
|
||||||
{
|
{
|
||||||
self.binder.shift_in(1);
|
self.binder.shift_in(1);
|
||||||
let t = t.fold_with(self);
|
let t = t.super_fold_with(self);
|
||||||
self.binder.shift_out(1);
|
self.binder.shift_out(1);
|
||||||
t
|
t
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,6 +58,12 @@ impl<'tcx> inspect::ProofTreeVisitor<'tcx> for Select {
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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`.
|
// We need to winnow. See comments on `candidate_should_be_dropped_in_favor_of`.
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while i < candidates.len() {
|
while i < candidates.len() {
|
||||||
|
@ -86,7 +92,7 @@ fn candidate_should_be_dropped_in_favor_of<'tcx>(
|
||||||
other: &inspect::InspectCandidate<'_, 'tcx>,
|
other: &inspect::InspectCandidate<'_, 'tcx>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
// Don't winnow until `Certainty::Yes` -- we don't need to winnow until
|
// 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(..)) {
|
if matches!(other.result().unwrap(), Certainty::Maybe(..)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -105,12 +111,14 @@ fn candidate_should_be_dropped_in_favor_of<'tcx>(
|
||||||
bug!("should not have assembled a CoherenceUnknowable candidate")
|
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
|
// 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`.
|
// 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::Impl(_) | CandidateSource::ParamEnv(_) | CandidateSource::AliasBound,
|
||||||
CandidateSource::BuiltinImpl(BuiltinImplSource::Object { .. }),
|
CandidateSource::BuiltinImpl(BuiltinImplSource::Object { .. }),
|
||||||
|
|
|
@ -14,7 +14,7 @@ use rustc_middle::ty::{self, TyCtxt};
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
|
|
||||||
use super::eval_ctxt::GenerateProofTree;
|
use super::eval_ctxt::GenerateProofTree;
|
||||||
use super::inspect::{ProofTreeInferCtxtExt, ProofTreeVisitor};
|
use super::inspect::{InspectCandidate, InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor};
|
||||||
use super::{Certainty, InferCtxtEvalExt};
|
use super::{Certainty, InferCtxtEvalExt};
|
||||||
|
|
||||||
/// A trait engine using the new trait solver.
|
/// A trait engine using the new trait solver.
|
||||||
|
@ -304,6 +304,46 @@ impl<'tcx> BestObligation<'tcx> {
|
||||||
self.obligation = old_obligation;
|
self.obligation = old_obligation;
|
||||||
res
|
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> {
|
impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
|
||||||
|
@ -314,11 +354,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_goal(&mut self, goal: &super::inspect::InspectGoal<'_, 'tcx>) -> Self::Result {
|
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.
|
let candidates = self.non_trivial_candidates(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 [candidate] = candidates.as_slice() else {
|
let [candidate] = candidates.as_slice() else {
|
||||||
return ControlFlow::Break(self.obligation.clone());
|
return ControlFlow::Break(self.obligation.clone());
|
||||||
};
|
};
|
||||||
|
|
|
@ -2258,7 +2258,7 @@ pub fn canonicalize<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
|
||||||
/// # Platform-specific behavior
|
/// # Platform-specific behavior
|
||||||
///
|
///
|
||||||
/// This function currently corresponds to the `mkdir` function on Unix
|
/// 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].
|
/// Note that, this [may change in the future][changes].
|
||||||
///
|
///
|
||||||
/// [changes]: io#platform-specific-behavior
|
/// [changes]: io#platform-specific-behavior
|
||||||
|
@ -2298,10 +2298,14 @@ pub fn create_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
|
||||||
/// Recursively create a directory and all of its parent components if they
|
/// Recursively create a directory and all of its parent components if they
|
||||||
/// are missing.
|
/// are missing.
|
||||||
///
|
///
|
||||||
|
/// If this function returns an error, some of the parent components might have
|
||||||
|
/// been created already.
|
||||||
|
///
|
||||||
/// # Platform-specific behavior
|
/// # Platform-specific behavior
|
||||||
///
|
///
|
||||||
/// This function currently corresponds to the `mkdir` function on Unix
|
/// This function currently corresponds to multiple calls to the `mkdir`
|
||||||
/// and the `CreateDirectory` function on Windows.
|
/// function on Unix and the `CreateDirectoryW` function on Windows.
|
||||||
|
///
|
||||||
/// Note that, this [may change in the future][changes].
|
/// Note that, this [may change in the future][changes].
|
||||||
///
|
///
|
||||||
/// [changes]: io#platform-specific-behavior
|
/// [changes]: io#platform-specific-behavior
|
||||||
|
|
|
@ -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() {}
|
|
@ -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
|
||||||
|
|
|
@ -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() {}
|
|
@ -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`.
|
|
@ -4,6 +4,9 @@
|
||||||
// comparing the supertrait `Derived<()>` to the expected trait.
|
// comparing the supertrait `Derived<()>` to the expected trait.
|
||||||
|
|
||||||
//@ build-pass
|
//@ build-pass
|
||||||
|
//@ revisions: current next
|
||||||
|
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||||
|
//@[next] compile-flags: -Znext-solver
|
||||||
|
|
||||||
trait Proj {
|
trait Proj {
|
||||||
type S;
|
type S;
|
||||||
|
|
Loading…
Add table
Reference in a new issue