Skip to content
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

implement intercrate_ambiguity_causes in the new solver #115996

Merged
merged 6 commits into from
Sep 21, 2023

Conversation

lcnr
Copy link
Contributor

@lcnr lcnr commented Sep 20, 2023

I added some comments but this is still somewhat of a mess. I think we should for the most part be able to treat all of this as a black box, so I can accept that this code isn't too great.

I also believe that some of the weirdness here is unavoidable, as proof trees - and their visitor - hide semantically relevant information, so they cannot perfectly represent the actual solver behavior.

There are some known bugs here when testing with ./x.py test tests/ui --bless -- --target-rustcflags -Ztrait-solver=next-coherence. While I haven't diagnosed them all in detail I believe we are able to handle them all separately

  • structurally_normalize currently does not normalize opaque types, resulting in divergence between the solver internal trait_ref_is_knowable and the one when computing intercrate ambiguity causes.
  • we don't add an intercrate_ambiguity_cause for reserved impls
  • we should deeply_normalize the trait ref before printing it, that requires a "best effort" version of deeply_normalize

r? @compiler-errors

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver) labels Sep 20, 2023
@rustbot
Copy link
Collaborator

rustbot commented Sep 20, 2023

Some changes occurred to the core trait solver

cc @rust-lang/initiative-trait-system-refactor

@rust-log-analyzer

This comment has been minimized.

@lcnr lcnr force-pushed the intercrate_ambiguity_causes-uwu branch from 052b3bc to 609a6fb Compare September 20, 2023 08:59
@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@lcnr lcnr force-pushed the intercrate_ambiguity_causes-uwu branch from a6b3582 to 30f314b Compare September 20, 2023 18:50
@@ -568,7 +569,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
GoalEvaluationKind::Nested { is_normalizes_to_hack: IsNormalizesToHack::Yes },
unconstrained_goal,
)?;
self.add_goals(instantiate_goals);
self.nested_goals.goals.extend(instantiate_goals);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I stopped using add_goals here because the added goals aren't really nested goals and it ended up breaking the proof tree builder

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you be more specific how it breaks things? Like I understand how we probably don't want to include these goals, and I especially understand not wanting to add ambiguous goal repeatedly over and over below, but does this affect tests detrimentally?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the issue was that we add goals while the state is DebugBuilder::AddedGoalsEvaluation.

For us to sensibly handle these nested goals we'd have to either add AddGoal as an action to AddedGoalsEvaluation or somehow take the added goals during the evaluation and "move them back" into the WipProbe once the added goals evaluation is done. Both of these feel somewhat ugly and slightly annoying to implement

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@lcnr lcnr force-pushed the intercrate_ambiguity_causes-uwu branch 2 times, most recently from 9e7cc9e to f0bffce Compare September 20, 2023 19:27
@rust-log-analyzer

This comment has been minimized.

@lcnr lcnr force-pushed the intercrate_ambiguity_causes-uwu branch from 5fee5f7 to ceb890a Compare September 20, 2023 19:41
@rust-log-analyzer

This comment has been minimized.

@lcnr lcnr force-pushed the intercrate_ambiguity_causes-uwu branch from ceb890a to ed7f5ce Compare September 20, 2023 19:47
WARN rustc_trait_selection::traits::coherence expected an unknowable trait ref: <<LocalTy as Overflow>::Assoc as std::marker::Sized>
WARN rustc_trait_selection::traits::coherence expected an unknowable trait ref: <<LocalTy as Overflow>::Assoc as std::marker::Sized>
WARN rustc_trait_selection::traits::coherence expected an unknowable trait ref: <<LocalTy as Overflow>::Assoc as std::marker::Sized>
WARN rustc_trait_selection::traits::coherence expected an unknowable trait ref: <<LocalTy as Overflow>::Assoc as std::marker::Sized>
Copy link
Contributor Author

@lcnr lcnr Sep 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this happens because I only changed structurally_normalize to silently fail on overflow, added a fixme there to correctly handle it.

@lcnr lcnr force-pushed the intercrate_ambiguity_causes-uwu branch 2 times, most recently from 2c1ea63 to 4bc1228 Compare September 20, 2023 19:59
@@ -568,7 +569,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
GoalEvaluationKind::Nested { is_normalizes_to_hack: IsNormalizesToHack::Yes },
unconstrained_goal,
)?;
self.add_goals(instantiate_goals);
self.nested_goals.goals.extend(instantiate_goals);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you be more specific how it breaks things? Like I understand how we probably don't want to include these goals, and I especially understand not wanting to add ambiguous goal repeatedly over and over below, but does this affect tests detrimentally?

@@ -29,6 +33,22 @@ use rustc_span::DUMMY_SP;
use std::iter;
use std::ops::Deref;

trait ResponseT<'tcx> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This name is kinda bad, but I can change it in a follow-up.

@@ -206,21 +228,21 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
/// This returns the substitutions to instantiate the bound variables of
/// the canonical response. This depends on the `original_values` for the
/// bound variables.
fn compute_query_response_substitution(
&self,
fn compute_query_response_substitution<T: ResponseT<'tcx>>(
Copy link
Member

@compiler-errors compiler-errors Sep 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know why this is a method on EvalCtxt anymore in this case. Should probably just be free and live in some public submodule, or even just in solve. You don't have to change this though.

@@ -287,9 +309,9 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
CanonicalVarValues { var_values }
}

#[instrument(level = "debug", skip(self, param_env), ret)]
#[instrument(level = "debug", skip(infcx, param_env), ret)]
fn unify_query_var_values(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above.

/// need it.
pub fn visit_nested<V: ProofTreeVisitor<'tcx>>(
&self,
visitor: &mut V,
Copy link
Member

@compiler-errors compiler-errors Sep 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like type folders, I feel like it makes more sense for the visitor to provide a fn infcx(&self) -> &InferCtxt<'tcx> rather than carrying it in the candidate itself. You don't have to change this though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, I had the InferCtxt as part of the context instead of the visitor as the context is responsible for calling infcx.probe which in some sense requires "ownership" of the infcx to me 🤷

self.candidates_recur(&mut candidates, &mut nested_goals, &last_eval_step.evaluation);

if candidates.is_empty() {
candidates.push(InspectCandidate {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, does this matter? If we fail to assemble any candidates, do the nested obligations that we accumulate in probes actually matter?

Copy link
Contributor Author

@lcnr lcnr Sep 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added a comment and slightly restructured the code. It is slightly broken rn and I am still a bit unsure how to best handle this 🤷

},
);
}
if !overlap_mode.use_implicit_negative() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's up with the control flow changes here? Doesn't this mean we're no longer doing leak check below?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, wanted to avoid computing intercrate ambiguity causes in case we didn't actually prove the obligations as we now don't collect them while proving them. Changed this back.

infcx: &InferCtxt<'tcx>,
obligations: &[PredicateObligation<'tcx>],
) -> FxIndexSet<IntercrateAmbiguityCause> {
let mut causes: FxIndexSet<IntercrateAmbiguityCause> = Default::default();
Copy link
Member

@compiler-errors compiler-errors Sep 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: inference should guide this? You don't need to fix this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure what you mean with that

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you need to ascribe the type here lol


let Goal { param_env, predicate } = goal.goal();

let trait_ref = match predicate.kind().no_bound_vars() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we ever have bound preds? I'm not exactly sure how we track that extra step of instantiation with placeholders in the proof tree. Is it just a goal with 1 nested goal?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, for these goals we instantiate the bound vars with placeholders in the ProbeKind::Root and then prove it as a nested goal. Added commenmt

// FIXME: this isn't quite right. Changing a goal from YES with
// inference contraints to AMBIGUOUS can also cause a goal to not
// fail.
Ok(Certainty::Yes) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing a goal from YES with inference contraints to AMBIGUOUS can also cause a goal to not fail.

Not certain what this means.

Copy link
Member

@compiler-errors compiler-errors Sep 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be checking that the goal is YES + no inference constraints, right? We essentially don't want to report ambiguity if we would've just disregarded that branch of the tree because of a better one?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it really only cares about "if the coherence ambiguity candidate did not exist, would this goal be an error", changed it and improved the FIXME

This should be checking that the goal is YES + no inference constraints, right?

this is already handled in line 929

@compiler-errors
Copy link
Member

compiler-errors commented Sep 21, 2023

r=me after addressing this one comment: #115996 (comment)

The rest can be clarified asynchronously I guess, since they're just miscellaneous thoughts.

@lcnr lcnr force-pushed the intercrate_ambiguity_causes-uwu branch from 4bc1228 to 8024c69 Compare September 21, 2023 06:18
@rust-log-analyzer

This comment has been minimized.

@lcnr lcnr force-pushed the intercrate_ambiguity_causes-uwu branch from c1ff61a to 614760f Compare September 21, 2023 06:57
@lcnr
Copy link
Contributor Author

lcnr commented Sep 21, 2023

@bors r=compiler-errors rollup (new solver)

@bors
Copy link
Contributor

bors commented Sep 21, 2023

📌 Commit 614760f has been approved by compiler-errors

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Sep 21, 2023
@bors
Copy link
Contributor

bors commented Sep 21, 2023

⌛ Testing commit 614760f with merge e4a361a...

@bors
Copy link
Contributor

bors commented Sep 21, 2023

☀️ Test successful - checks-actions
Approved by: compiler-errors
Pushing e4a361a to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Sep 21, 2023
@bors bors merged commit e4a361a into rust-lang:master Sep 21, 2023
@rustbot rustbot added this to the 1.74.0 milestone Sep 21, 2023
@lcnr lcnr deleted the intercrate_ambiguity_causes-uwu branch September 21, 2023 11:00
@rust-timer
Copy link
Collaborator

Finished benchmarking commit (e4a361a): comparison URL.

Overall result: no relevant changes - no action needed

@rustbot label: -perf-regression

Instruction count

This benchmark run did not return any relevant results for this metric.

Max RSS (memory usage)

This benchmark run did not return any relevant results for this metric.

Cycles

This benchmark run did not return any relevant results for this metric.

Binary size

This benchmark run did not return any relevant results for this metric.

Bootstrap: 630.991s -> 633.931s (0.47%)
Artifact size: 317.95 MiB -> 317.95 MiB (0.00%)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants