-
-
Notifications
You must be signed in to change notification settings - Fork 15.6k
next solver: prefer to select impl candidates over global where-clause candidates #162655
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,7 +2,7 @@ use std::ops::ControlFlow; | |
|
|
||
| use rustc_infer::infer::InferCtxt; | ||
| use rustc_infer::traits::solve::inspect::ProbeKind; | ||
| use rustc_infer::traits::solve::{CandidateSource, Certainty, Goal}; | ||
| use rustc_infer::traits::solve::{CandidateSource, Certainty, Goal, ParamEnvSource}; | ||
| use rustc_infer::traits::{ | ||
| BuiltinImplSource, ImplSource, ImplSourceUserDefinedData, Obligation, ObligationCause, | ||
| PolyTraitObligation, Selection, SelectionError, SelectionResult, | ||
|
|
@@ -93,8 +93,8 @@ fn candidate_should_be_dropped_in_favor_of<'tcx>( | |
| victim: &inspect::InspectCandidate<'_, 'tcx>, | ||
| other: &inspect::InspectCandidate<'_, 'tcx>, | ||
| ) -> bool { | ||
| // Don't winnow until `Certainty::Yes` -- we don't need to winnow until | ||
| // codegen, and only on the good path. | ||
| // Don't winnow until `Certainty::Yes` -- we don't need to winnow until constant evaluation or | ||
| // codegen. | ||
| if matches!(other.result().unwrap(), Certainty::Maybe(_)) { | ||
| return false; | ||
| } | ||
|
|
@@ -137,6 +137,15 @@ fn candidate_should_be_dropped_in_favor_of<'tcx>( | |
| victim.goal().infcx().tcx.specializes((other_def_id, victim_def_id)) | ||
| } | ||
|
|
||
| // Prefer impl candidates over global where clause candidates. Unless `generic_const_args` | ||
| // is enabled, we currently don't use an empty environment when resolving and evaluating | ||
| // constants to lower them to patterns. If we don't drop where clause candidates here, we | ||
| // can fail to select impl candidates (#162331). | ||
| ( | ||
| CandidateSource::ParamEnv(ParamEnvSource::Global), | ||
| CandidateSource::Impl(_) | CandidateSource::BuiltinImpl(_), | ||
| ) => true, | ||
|
Comment on lines
+144
to
+147
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe this could be more aggressive? I'm not sure what else would be needed, so I'm treating this as a targeted fix. so far, I haven't been able to find any examples that would still fail without this if const-to-pat resolved and evaluated consts in a clean environment (e.g. as it does when full gca is enabled) |
||
|
|
||
| _ => false, | ||
| } | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| //! Regression test for <https://github.com/rust-lang/rust/issues/162331> | ||
| //@ revisions: current next | ||
| //@ ignore-compare-mode-next-solver (explicit revisions) | ||
| //@[next] compile-flags: -Znext-solver | ||
|
Comment on lines
+2
to
+4
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. could maybe get rid of the current-solver revision but I figured I'd include it as a sanity check |
||
| //@ check-pass | ||
|
|
||
| #![feature(const_trait_impl)] | ||
| #![feature(const_clone)] | ||
|
Comment on lines
+7
to
+8
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is for testing the preference for builtin impls over global where-clause candidates. I haven't found a way to do that without unstable features |
||
|
|
||
| // At the time of writing, when resolving an instance for `<u8 as Trait>::N`, the environment | ||
| // contains `f`'s `u8: Trait` clause. The old solver dropped the where clause candidate in favor of | ||
| // the `impl Trait for u8` candidate, but the new solver didn't, which resulted in ambiguity. | ||
|
|
||
| pub trait Trait { | ||
| const N: usize; | ||
| } | ||
|
|
||
| impl Trait for u8 { | ||
| const N: usize = 0; | ||
| } | ||
|
|
||
| pub fn f() | ||
| where | ||
| u8: Trait, | ||
| { | ||
| match 0 { | ||
| <u8 as Trait>::N => {} | ||
| _ => {} | ||
| } | ||
| } | ||
|
|
||
| // At the time of writing, `ZERO` is evaluated in an environment containing `g`'s `(u8,): Clone` | ||
| // clause. This wasn't dropped in favor of the built-in `(u8,): Clone` impl when resolving an | ||
| // instance for `<(u8,) as Clone>::clone`, which resulted in ambiguity. | ||
|
|
||
| const ZERO: (u8,) = (0,).clone(); | ||
|
|
||
| fn g() | ||
| where | ||
| (u8,): Clone | ||
| { | ||
| match (0,) { | ||
| ZERO => {} | ||
| _ => {} | ||
| } | ||
| } | ||
|
|
||
| fn main() {} | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not totally sure what to do with this comment, but seeing as it was wrong before, I'd like to update it in some way
View changes since the review