Skip to content

proven_via into query response #142953

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

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,13 @@ use std::ops::ControlFlow;
use derive_where::derive_where;
use rustc_type_ir::inherent::*;
use rustc_type_ir::lang_items::TraitSolverLangItem;
use rustc_type_ir::solve::SizedTraitKind;
use rustc_type_ir::solve::{SizedTraitKind, TraitGoalProvenVia};
use rustc_type_ir::{
self as ty, Interner, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt as _,
TypeVisitor, TypingMode, Upcast as _, elaborate,
};
use tracing::{debug, instrument};

use super::trait_goals::TraitGoalProvenVia;
use super::{has_only_region_constraints, inspect};
use crate::delegate::SolverDelegate;
use crate::solve::inspect::ProbeKind;
Expand Down
8 changes: 2 additions & 6 deletions compiler/rustc_next_trait_solver/src/solve/effect_goals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use rustc_type_ir::fast_reject::DeepRejectCtxt;
use rustc_type_ir::inherent::*;
use rustc_type_ir::lang_items::TraitSolverLangItem;
use rustc_type_ir::solve::SizedTraitKind;
use rustc_type_ir::solve::inspect::ProbeKind;
use rustc_type_ir::{self as ty, Interner, elaborate};
use tracing::instrument;

Expand Down Expand Up @@ -394,11 +393,8 @@ where
&mut self,
goal: Goal<I, ty::HostEffectPredicate<I>>,
) -> QueryResult<I> {
let (_, proven_via) = self.probe(|_| ProbeKind::ShadowedEnvProbing).enter(|ecx| {
let trait_goal: Goal<I, ty::TraitPredicate<I>> =
goal.with(ecx.cx(), goal.predicate.trait_ref);
ecx.compute_trait_goal(trait_goal)
})?;
let trait_goal = goal.with(self.cx(), goal.predicate.trait_ref);
let proven_via = self.trait_goal_proven_via(trait_goal)?;
self.assemble_and_merge_candidates(proven_via, goal, |_ecx| Err(NoSolution))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use rustc_index::IndexVec;
use rustc_type_ir::data_structures::HashSet;
use rustc_type_ir::inherent::*;
use rustc_type_ir::relate::solver_relating::RelateExt;
use rustc_type_ir::solve::TraitGoalProvenVia;
use rustc_type_ir::{
self as ty, Canonical, CanonicalVarValues, InferCtxtLike, Interner, TypeFoldable,
};
Expand Down Expand Up @@ -178,6 +179,7 @@ where
var_values,
certainty,
external_constraints: self.cx().mk_external_constraints(external_constraints),
trait_goal_proven_via: None,
},
);

Expand Down Expand Up @@ -278,15 +280,15 @@ where
param_env: I::ParamEnv,
original_values: &[I::GenericArg],
response: CanonicalResponse<I>,
) -> (NestedNormalizationGoals<I>, Certainty) {
) -> (NestedNormalizationGoals<I>, Option<TraitGoalProvenVia>, Certainty) {
let instantiation = Self::compute_query_response_instantiation_values(
self.delegate,
&original_values,
&response,
self.origin_span,
);

let Response { var_values, external_constraints, certainty } =
let Response { var_values, external_constraints, certainty, trait_goal_proven_via } =
self.delegate.instantiate_canonical(response, instantiation);

Self::unify_query_var_values(
Expand All @@ -306,7 +308,7 @@ where
self.register_region_constraints(region_constraints);
self.register_new_opaque_types(opaque_types);

(normalization_nested_goals.clone(), certainty)
(normalization_nested_goals.clone(), trait_goal_proven_via, certainty)
}

/// This returns the canonical variable values to instantiate the bound variables of
Expand Down
36 changes: 31 additions & 5 deletions compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use rustc_type_ir::inherent::*;
use rustc_type_ir::relate::Relate;
use rustc_type_ir::relate::solver_relating::RelateExt;
use rustc_type_ir::search_graph::PathKind;
use rustc_type_ir::solve::TraitGoalProvenVia;
use rustc_type_ir::{
self as ty, CanonicalVarValues, InferCtxtLike, Interner, TypeFoldable, TypeFolder,
TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
Expand Down Expand Up @@ -233,6 +234,7 @@ where
I::Span::dummy(),
|ecx| {
ecx.evaluate_goal_raw(GoalEvaluationKind::Root, GoalSource::Misc, goal, stalled_on)
.map(|(n, _, r)| (n, r))
},
)
}
Expand Down Expand Up @@ -460,12 +462,27 @@ where
goal: Goal<I, I::Predicate>,
stalled_on: Option<GoalStalledOn<I>>,
) -> Result<GoalEvaluation<I>, NoSolution> {
let (normalization_nested_goals, goal_evaluation) =
let (normalization_nested_goals, _, goal_evaluation) =
self.evaluate_goal_raw(goal_evaluation_kind, source, goal, stalled_on)?;
assert!(normalization_nested_goals.is_empty());
Ok(goal_evaluation)
}

pub(super) fn trait_goal_proven_via(
&mut self,
goal: Goal<I, I::Predicate>,
) -> Result<Option<TraitGoalProvenVia>, NoSolution> {
let (_, canonical_goal) = self.canonicalize_goal(goal);
let canonical_response = EvalCtxt::evaluate_canonical_goal(
self.cx(),
self.search_graph,
canonical_goal,
self.step_kind_for_source(GoalSource::Misc),
&mut ProofTreeBuilder::new_noop(),
);
canonical_response.map(|r| r.value.trait_goal_proven_via)
}

/// Recursively evaluates `goal`, returning the nested goals in case
/// the nested goal is a `NormalizesTo` goal.
///
Expand All @@ -479,7 +496,10 @@ where
source: GoalSource,
goal: Goal<I, I::Predicate>,
stalled_on: Option<GoalStalledOn<I>>,
) -> Result<(NestedNormalizationGoals<I>, GoalEvaluation<I>), NoSolution> {
) -> Result<
(NestedNormalizationGoals<I>, Option<TraitGoalProvenVia>, GoalEvaluation<I>),
NoSolution,
> {
// If we have run this goal before, and it was stalled, check that any of the goal's
// args have changed. Otherwise, we don't need to re-run the goal because it'll remain
// stalled, since it'll canonicalize the same way and evaluation is pure.
Expand All @@ -492,6 +512,7 @@ where
{
return Ok((
NestedNormalizationGoals::empty(),
None,
GoalEvaluation {
certainty: Certainty::Maybe(stalled_on.stalled_cause),
has_changed: HasChanged::No,
Expand Down Expand Up @@ -522,7 +543,7 @@ where
let has_changed =
if !has_only_region_constraints(response) { HasChanged::Yes } else { HasChanged::No };

let (normalization_nested_goals, certainty) =
let (normalization_nested_goals, trait_goal_proven_via, certainty) =
self.instantiate_and_apply_query_response(goal.param_env, &orig_values, response);
self.inspect.goal_evaluation(goal_evaluation);

Expand Down Expand Up @@ -582,7 +603,11 @@ where
},
};

Ok((normalization_nested_goals, GoalEvaluation { certainty, has_changed, stalled_on }))
Ok((
normalization_nested_goals,
trait_goal_proven_via,
GoalEvaluation { certainty, has_changed, stalled_on },
))
}

fn compute_goal(&mut self, goal: Goal<I, I::Predicate>) -> QueryResult<I> {
Expand All @@ -591,7 +616,7 @@ where
if let Some(kind) = kind.no_bound_vars() {
match kind {
ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate)) => {
self.compute_trait_goal(Goal { param_env, predicate }).map(|(r, _via)| r)
self.compute_trait_goal(Goal { param_env, predicate })
}
ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(predicate)) => {
self.compute_host_effect_goal(Goal { param_env, predicate })
Expand Down Expand Up @@ -715,6 +740,7 @@ where

let (
NestedNormalizationGoals(nested_goals),
_proven_via,
GoalEvaluation { certainty, stalled_on, has_changed: _ },
) = self.evaluate_goal_raw(
GoalEvaluationKind::Nested,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> {
ProofTreeBuilder::new(DebugSolver::Root)
}

fn new_noop() -> ProofTreeBuilder<D> {
pub(crate) fn new_noop() -> ProofTreeBuilder<D> {
ProofTreeBuilder { state: None, _infcx: PhantomData }
}

Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_next_trait_solver/src/solve/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,8 @@ fn response_no_constraints_raw<I: Interner>(
variables,
value: Response {
var_values: ty::CanonicalVarValues::make_identity(cx, variables),
// Cycles start out without knowing how the trait goal was proven.
trait_goal_proven_via: None,
// FIXME: maybe we should store the "no response" version in cx, like
// we do for cx.types and stuff.
external_constraints: cx.mk_external_constraints(ExternalConstraintsData::default()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,8 @@ where
match goal.predicate.alias.kind(cx) {
ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst => {
let trait_ref = goal.predicate.alias.trait_ref(cx);
let (_, proven_via) =
self.probe(|_| ProbeKind::ShadowedEnvProbing).enter(|ecx| {
let trait_goal: Goal<I, ty::TraitPredicate<I>> = goal.with(cx, trait_ref);
ecx.compute_trait_goal(trait_goal)
})?;
let trait_goal = goal.with(cx, trait_ref);
let proven_via = self.trait_goal_proven_via(trait_goal)?;
self.assemble_and_merge_candidates(proven_via, goal, |ecx| {
ecx.probe(|&result| ProbeKind::RigidAlias { result }).enter(|this| {
this.structurally_instantiate_normalizes_to_term(
Expand Down
31 changes: 6 additions & 25 deletions compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use rustc_type_ir::data_structures::IndexSet;
use rustc_type_ir::fast_reject::DeepRejectCtxt;
use rustc_type_ir::inherent::*;
use rustc_type_ir::lang_items::TraitSolverLangItem;
use rustc_type_ir::solve::{CanonicalResponse, SizedTraitKind};
use rustc_type_ir::solve::{CanonicalResponse, SizedTraitKind, TraitGoalProvenVia};
use rustc_type_ir::{
self as ty, Interner, Movability, TraitPredicate, TraitRef, TypeVisitableExt as _, TypingMode,
Upcast as _, elaborate,
Expand Down Expand Up @@ -1278,28 +1278,6 @@ where
}
}

/// How we've proven this trait goal.
///
/// This is used by `NormalizesTo` goals to only normalize
/// by using the same 'kind of candidate' we've used to prove
/// its corresponding trait goal. Most notably, we do not
/// normalize by using an impl if the trait goal has been
/// proven via a `ParamEnv` candidate.
///
/// This is necessary to avoid unnecessary region constraints,
/// see trait-system-refactor-initiative#125 for more details.
#[derive(Debug, Clone, Copy)]
pub(super) enum TraitGoalProvenVia {
/// We've proven the trait goal by something which is
/// is not a non-global where-bound or an alias-bound.
///
/// This means we don't disable any candidates during
/// normalization.
Misc,
ParamEnv,
AliasBound,
}

impl<D, I> EvalCtxt<'_, D>
where
D: SolverDelegate<Interner = I>,
Expand Down Expand Up @@ -1433,9 +1411,12 @@ where
pub(super) fn compute_trait_goal(
&mut self,
goal: Goal<I, TraitPredicate<I>>,
) -> Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>), NoSolution> {
) -> Result<CanonicalResponse<I>, NoSolution> {
let candidates = self.assemble_and_evaluate_candidates(goal, AssembleCandidatesFrom::All);
self.merge_trait_candidates(candidates)
self.merge_trait_candidates(candidates).map(|(mut r, proven_via)| {
r.value.trait_goal_proven_via = proven_via;
r
})
}

fn try_stall_coroutine_witness(
Expand Down
26 changes: 26 additions & 0 deletions compiler/rustc_type_ir/src/solve/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,32 @@ pub struct Response<I: Interner> {
pub var_values: CanonicalVarValues<I>,
/// Additional constraints returned by this query.
pub external_constraints: I::ExternalConstraints,
#[type_foldable(identity)]
#[type_visitable(ignore)]
pub trait_goal_proven_via: Option<TraitGoalProvenVia>,
}

/// How we've proven this trait goal.
///
/// This is used by `NormalizesTo` goals to only normalize
/// by using the same 'kind of candidate' we've used to prove
/// its corresponding trait goal. Most notably, we do not
/// normalize by using an impl if the trait goal has been
/// proven via a `ParamEnv` candidate.
///
/// This is necessary to avoid unnecessary region constraints,
/// see trait-system-refactor-initiative#125 for more details.
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
pub enum TraitGoalProvenVia {
/// We've proven the trait goal by something which is
/// is not a non-global where-bound or an alias-bound.
///
/// This means we don't disable any candidates during
/// normalization.
Misc,
ParamEnv,
AliasBound,
}

/// Additional constraints returned on success.
Expand Down
Loading