Make inductive cycles always ambiguous#122791
Conversation
|
|
Apologies. I misread the crater report. The regressions are a combination of For the record, the regression was removed when a bunch of impls were reworked in: LNP-BP/client_side_validation#152. |
|
Regarding /// Used only internally for blank implementation on reference types.
#[doc(hidden)]
pub enum AsRef {}
impl<'a, T> CommitEncode for Holder<&'a T, AsRef>
where
T: CommitEncode,
{
fn commit_encode(&self, e: &mut impl io::Write) {
self.as_type().commit_encode(e);
}
}
impl<T> CommitStrategy for &T
where
T: CommitEncode,
{
type Strategy = AsRef;
}
impl<T> CommitEncode for T
where
T: CommitStrategy,
for<'a> Holder<&'a T, T::Strategy>: CommitEncode,
{
fn commit_encode(&self, e: &mut impl io::Write)
Holder::new(self).commit_encode(e)
}
}... which I guess because we don't treat ambiguity as error, we end up actually evaluating to overflow. Removing |
lcnr
left a comment
There was a problem hiding this comment.
which is a hack to make sure we're not eagerly normalizing bounds that have nothing to do with the predicate we're trying to solve, and which result in.
"fatal overflow" i guess?
What is a test which is affected here. How does this handle <AssocTy as Id>::Assoc: Bound? writing a test rn
| /// This can't be trivially cached for the same reason as `EvaluatedToErrStackDependent`. | ||
| /// This can't be trivially cached because the result depends on the | ||
| /// stack results. | ||
| EvaluatedToAmbigStackDependent, |
There was a problem hiding this comment.
unrelated: isn't this just utterly broken if you have stack dependent ambiguity resulting in difference inference constraints, causing a later goal to error without stack dependence?
anyways, the old solver cannot be salvaged. This is an existing issue 😁
|
This already fails on nightly, so this PR seems good to me. I am a bit confused why though, we somehow keep the trait Id {
type This: ?Sized;
}
impl<T: ?Sized> Id for T {
type This = T;
}
trait Trait
where
<Self::Assoc as Id>::This: Copy,
{
type Assoc;
}
fn foo<T: Trait>(x: T::Assoc) -> (T::Assoc, T::Assoc) {
(x, x)
}edit: it's because that hasn't landed yet '^^ that is from a separate PR #120752 The following also already fails, which makes sense, but seems like a shortcoming of our approach to normalization #![feature(associated_type_bounds)]
trait Id {
type This: ?Sized;
}
impl<T: ?Sized> Id for T {
type This = T;
}
trait Trait {
type Assoc: Id<This: Copy>;
}
fn foo<T: Trait>(x: T::Assoc) -> (T::Assoc, T::Assoc) {
(x, x)
}however, why does the following compile? #![feature(associated_type_bounds)]
trait Id {
type This: ?Sized;
}
trait Trait {
type Assoc: Id<This: Copy>;
}
fn foo<T: Trait>(x: T::Assoc) -> (T::Assoc, T::Assoc)
where
T::Assoc: Id<This = T::Assoc>,
{
(x, x)
}please add these all as tests 😁 |
|
Ignoring the question about nested For more details, see the PR description by @compiler-errors. @rfcbot fcp merge |
|
Team member @lcnr has proposed to merge this. The next step is review by the rest of the tagged team members: No concerns currently listed. Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See this document for info about what commands tagged team members can give me. |
|
☔ The latest upstream changes (presumably #121123) made this pull request unmergeable. Please resolve the merge conflicts. |
This comment was marked as outdated.
This comment was marked as outdated.
|
Actually, yeah, it's due to candidate shadowing, just for associated item bounds shadowing the global impl. |
7e0b48c to
c594682
Compare
|
🔔 This is now entering its final comment period, as per the review above. 🔔 |
|
The job Click to see the possible cause of the failure (guessed by this bot) |
|
💔 Test failed - checks-actions |
|
@bors retry |
|
☀️ Test successful - checks-actions |
|
Finished benchmarking commit (40f743d): comparison URL. Overall result: no relevant changes - no action needed@rustbot label: -perf-regression Instruction countThis benchmark run did not return any relevant results for this metric. Max RSS (memory usage)ResultsThis is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
CyclesResultsThis is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
Binary sizeResultsThis is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
Bootstrap: 668.585s -> 668.957s (0.06%) |
This makes inductive cycles always result in ambiguity rather than be treated like a stack-dependent error.
This has some interactions with specialization, and so breaks a few UI tests that I don't agree should've ever worked in the first place, and also breaks a handful of crates in a way that I don't believe is a problem.
On the bright side, it puts us in a better spot when it comes to eventually enabling coinduction everywhere.
Results
This was cratered in #116494 (comment), which boils down to two regressions:
lu_packets- This code should have never compiled in the first place. More below.commit_verify@0.11.0-beta.1(edit: andcommit_verify@0.10.x) - This actually seems to be fixed in version0.11.0-beta.5, which is the most up to date version, but it's still prerelease on crates.io so I don't think cargo ends up pickingbeta.5when building dependent crates.lu_packetsFirstly, this crate uses specialization, so I think it's automatically worth breaking. However, I've minimized the regression to:
Specifically this fails when computing the specialization graph for the
downstreamcrate.The code ends up cycling on
&[?0]: Serializewhen we equate&?0 = &[?1]during impl matching, which ends up needing to prove&[?1]: Serialize, which since cycles are treated like ambiguity, ends up in a fatal overflow. For some reason this requires two crates, squashing them into one crate doesn't work.Side-note: This code is subtly order dependent. When minimizing, I ended up having the code start failing on
nightlyvery easily after removing and reordering impls. This seems to me all the more reason to remove this behavior altogether.Side-note: Item Bounds (edit: this was fixed independently in #121123)
Due to the changes in #120584 where we now consider an alias's item bounds and all the item bounds of the alias's nested self type aliases, I've had to add e6b64c6 which is a hack to make sure we're not eagerly normalizing bounds that have nothing to do with the predicate we're trying to solve, and which result in.
This is fixed in a more principled way in #121123.
r? lcnr for an initial review