Skip to content

add ecx.probe_candidate #113329

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

Merged
merged 1 commit into from
Jul 5, 2023
Merged
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
68 changes: 31 additions & 37 deletions compiler/rustc_trait_selection/src/solve/alias_relate.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use super::{EvalCtxt, SolverMode};
use rustc_infer::traits::query::NoSolution;
use rustc_middle::traits::solve::inspect::CandidateKind;
use rustc_middle::traits::solve::{Certainty, Goal, QueryResult};
use rustc_middle::ty;

Expand Down Expand Up @@ -110,12 +109,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
direction: ty::AliasRelationDirection,
invert: Invert,
) -> QueryResult<'tcx> {
self.probe(|r| CandidateKind::Candidate { name: "normalizes-to".into(), result: *r }).enter(
|ecx| {
ecx.normalizes_to_inner(param_env, alias, other, direction, invert)?;
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
},
)
self.probe_candidate("normalizes-to").enter(|ecx| {
ecx.normalizes_to_inner(param_env, alias, other, direction, invert)?;
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
})
}

fn normalizes_to_inner(
Expand Down Expand Up @@ -156,20 +153,18 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
alias_rhs: ty::AliasTy<'tcx>,
direction: ty::AliasRelationDirection,
) -> QueryResult<'tcx> {
self.probe(|r| CandidateKind::Candidate { name: "substs relate".into(), result: *r }).enter(
|ecx| {
match direction {
ty::AliasRelationDirection::Equate => {
ecx.eq(param_env, alias_lhs, alias_rhs)?;
}
ty::AliasRelationDirection::Subtype => {
ecx.sub(param_env, alias_lhs, alias_rhs)?;
}
self.probe_candidate("substs relate").enter(|ecx| {
match direction {
ty::AliasRelationDirection::Equate => {
ecx.eq(param_env, alias_lhs, alias_rhs)?;
}
ty::AliasRelationDirection::Subtype => {
ecx.sub(param_env, alias_lhs, alias_rhs)?;
}
}

ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
},
)
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
})
}

fn assemble_bidirectional_normalizes_to_candidate(
Expand All @@ -179,23 +174,22 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
rhs: ty::Term<'tcx>,
direction: ty::AliasRelationDirection,
) -> QueryResult<'tcx> {
self.probe(|r| CandidateKind::Candidate { name: "bidir normalizes-to".into(), result: *r })
.enter(|ecx| {
ecx.normalizes_to_inner(
param_env,
lhs.to_alias_ty(ecx.tcx()).unwrap(),
rhs,
direction,
Invert::No,
)?;
ecx.normalizes_to_inner(
param_env,
rhs.to_alias_ty(ecx.tcx()).unwrap(),
lhs,
direction,
Invert::Yes,
)?;
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
})
self.probe_candidate("bidir normalizes-to").enter(|ecx| {
ecx.normalizes_to_inner(
param_env,
lhs.to_alias_ty(ecx.tcx()).unwrap(),
rhs,
direction,
Invert::No,
)?;
ecx.normalizes_to_inner(
param_env,
rhs.to_alias_ty(ecx.tcx()).unwrap(),
lhs,
direction,
Invert::Yes,
)?;
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
})
}
}
34 changes: 14 additions & 20 deletions compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use rustc_infer::infer::{
use rustc_infer::traits::query::NoSolution;
use rustc_infer::traits::ObligationCause;
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
use rustc_middle::traits::solve::inspect::{self, CandidateKind};
use rustc_middle::traits::solve::inspect;
use rustc_middle::traits::solve::{
CanonicalInput, CanonicalResponse, Certainty, IsNormalizesToHack, MaybeCause,
PredefinedOpaques, PredefinedOpaquesData, QueryResult,
Expand Down Expand Up @@ -880,25 +880,19 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
if candidate_key.def_id != key.def_id {
continue;
}
values.extend(
self.probe(|r| CandidateKind::Candidate {
name: "opaque type storage".into(),
result: *r,
})
.enter(|ecx| {
for (a, b) in std::iter::zip(candidate_key.substs, key.substs) {
ecx.eq(param_env, a, b)?;
}
ecx.eq(param_env, candidate_ty, ty)?;
ecx.add_item_bounds_for_hidden_type(
candidate_key.def_id.to_def_id(),
candidate_key.substs,
param_env,
candidate_ty,
);
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}),
);
values.extend(self.probe_candidate("opaque type storage").enter(|ecx| {
for (a, b) in std::iter::zip(candidate_key.substs, key.substs) {
ecx.eq(param_env, a, b)?;
}
ecx.eq(param_env, candidate_ty, ty)?;
ecx.add_item_bounds_for_hidden_type(
candidate_key.def_id.to_def_id(),
candidate_key.substs,
param_env,
candidate_ty,
);
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}));
}
values
}
Expand Down
22 changes: 21 additions & 1 deletion compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::EvalCtxt;
use rustc_middle::traits::solve::inspect;
use rustc_middle::traits::solve::{inspect, QueryResult};
use std::marker::PhantomData;

pub(in crate::solve) struct ProbeCtxt<'me, 'a, 'tcx, F, T> {
Expand Down Expand Up @@ -44,4 +44,24 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
{
ProbeCtxt { ecx: self, probe_kind, _result: PhantomData }
}

pub(in crate::solve) fn probe_candidate(
&mut self,
name: &'static str,
) -> ProbeCtxt<
'_,
'a,
'tcx,
impl FnOnce(&QueryResult<'tcx>) -> inspect::CandidateKind<'tcx>,
QueryResult<'tcx>,
> {
ProbeCtxt {
ecx: self,
probe_kind: move |result: &QueryResult<'tcx>| inspect::CandidateKind::Candidate {
name: name.to_string(),
result: *result,
},
_result: PhantomData,
}
}
}
179 changes: 84 additions & 95 deletions compiler/rustc_trait_selection/src/solve/project_goals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,23 +112,18 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
) -> QueryResult<'tcx> {
if let Some(projection_pred) = assumption.as_projection_clause() {
if projection_pred.projection_def_id() == goal.predicate.def_id() {
ecx.probe(|r| CandidateKind::Candidate { name: "assumption".into(), result: *r })
.enter(|ecx| {
let assumption_projection_pred =
ecx.instantiate_binder_with_infer(projection_pred);
ecx.eq(
goal.param_env,
goal.predicate.projection_ty,
assumption_projection_pred.projection_ty,
)?;
ecx.eq(
goal.param_env,
goal.predicate.term,
assumption_projection_pred.term,
)
ecx.probe_candidate("assumption").enter(|ecx| {
let assumption_projection_pred =
ecx.instantiate_binder_with_infer(projection_pred);
ecx.eq(
goal.param_env,
goal.predicate.projection_ty,
assumption_projection_pred.projection_ty,
)?;
ecx.eq(goal.param_env, goal.predicate.term, assumption_projection_pred.term)
.expect("expected goal term to be fully unconstrained");
then(ecx)
})
then(ecx)
})
} else {
Err(NoSolution)
}
Expand Down Expand Up @@ -329,91 +324,89 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx> {
let tcx = ecx.tcx();
ecx.probe(|r| CandidateKind::Candidate { name: "builtin pointee".into(), result: *r })
.enter(|ecx| {
let metadata_ty = match goal.predicate.self_ty().kind() {
ty::Bool
| ty::Char
| ty::Int(..)
| ty::Uint(..)
| ty::Float(..)
| ty::Array(..)
| ty::RawPtr(..)
| ty::Ref(..)
| ty::FnDef(..)
| ty::FnPtr(..)
| ty::Closure(..)
| ty::Infer(ty::IntVar(..) | ty::FloatVar(..))
| ty::Generator(..)
| ty::GeneratorWitness(..)
| ty::GeneratorWitnessMIR(..)
| ty::Never
| ty::Foreign(..) => tcx.types.unit,

ty::Error(e) => tcx.ty_error(*e),

ty::Str | ty::Slice(_) => tcx.types.usize,

ty::Dynamic(_, _, _) => {
let dyn_metadata = tcx.require_lang_item(LangItem::DynMetadata, None);
tcx.type_of(dyn_metadata)
.subst(tcx, &[ty::GenericArg::from(goal.predicate.self_ty())])
}

ty::Alias(_, _) | ty::Param(_) | ty::Placeholder(..) => {
// FIXME(ptr_metadata): It would also be possible to return a `Ok(Ambig)` with no constraints.
let sized_predicate = ty::TraitRef::from_lang_item(
tcx,
LangItem::Sized,
DUMMY_SP,
[ty::GenericArg::from(goal.predicate.self_ty())],
);
ecx.add_goal(goal.with(tcx, sized_predicate));
tcx.types.unit
}
ecx.probe_candidate("builtin pointee").enter(|ecx| {
let metadata_ty = match goal.predicate.self_ty().kind() {
ty::Bool
| ty::Char
| ty::Int(..)
| ty::Uint(..)
| ty::Float(..)
| ty::Array(..)
| ty::RawPtr(..)
| ty::Ref(..)
| ty::FnDef(..)
| ty::FnPtr(..)
| ty::Closure(..)
| ty::Infer(ty::IntVar(..) | ty::FloatVar(..))
| ty::Generator(..)
| ty::GeneratorWitness(..)
| ty::GeneratorWitnessMIR(..)
| ty::Never
| ty::Foreign(..) => tcx.types.unit,

ty::Error(e) => tcx.ty_error(*e),

ty::Str | ty::Slice(_) => tcx.types.usize,

ty::Dynamic(_, _, _) => {
let dyn_metadata = tcx.require_lang_item(LangItem::DynMetadata, None);
tcx.type_of(dyn_metadata)
.subst(tcx, &[ty::GenericArg::from(goal.predicate.self_ty())])
}

ty::Adt(def, substs) if def.is_struct() => {
match def.non_enum_variant().fields.raw.last() {
None => tcx.types.unit,
Some(field_def) => {
let self_ty = field_def.ty(tcx, substs);
ecx.add_goal(goal.with(
tcx,
ty::Binder::dummy(goal.predicate.with_self_ty(tcx, self_ty)),
));
return ecx.evaluate_added_goals_and_make_canonical_response(
Certainty::Yes,
);
}
}
}
ty::Adt(_, _) => tcx.types.unit,
ty::Alias(_, _) | ty::Param(_) | ty::Placeholder(..) => {
// FIXME(ptr_metadata): It would also be possible to return a `Ok(Ambig)` with no constraints.
let sized_predicate = ty::TraitRef::from_lang_item(
tcx,
LangItem::Sized,
DUMMY_SP,
[ty::GenericArg::from(goal.predicate.self_ty())],
);
ecx.add_goal(goal.with(tcx, sized_predicate));
tcx.types.unit
}

ty::Tuple(elements) => match elements.last() {
ty::Adt(def, substs) if def.is_struct() => {
match def.non_enum_variant().fields.raw.last() {
None => tcx.types.unit,
Some(&self_ty) => {
Some(field_def) => {
let self_ty = field_def.ty(tcx, substs);
ecx.add_goal(goal.with(
tcx,
ty::Binder::dummy(goal.predicate.with_self_ty(tcx, self_ty)),
));
return ecx
.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
}
},

ty::Infer(
ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_),
)
| ty::Bound(..) => bug!(
"unexpected self ty `{:?}` when normalizing `<T as Pointee>::Metadata`",
goal.predicate.self_ty()
),
};
}
}
ty::Adt(_, _) => tcx.types.unit,

ecx.eq(goal.param_env, goal.predicate.term, metadata_ty.into())
.expect("expected goal term to be fully unconstrained");
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
})
ty::Tuple(elements) => match elements.last() {
None => tcx.types.unit,
Some(&self_ty) => {
ecx.add_goal(goal.with(
tcx,
ty::Binder::dummy(goal.predicate.with_self_ty(tcx, self_ty)),
));
return ecx
.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
}
},

ty::Infer(
ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_),
)
| ty::Bound(..) => bug!(
"unexpected self ty `{:?}` when normalizing `<T as Pointee>::Metadata`",
goal.predicate.self_ty()
),
};

ecx.eq(goal.param_env, goal.predicate.term, metadata_ty.into())
.expect("expected goal term to be fully unconstrained");
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
})
}

fn consider_builtin_future_candidate(
Expand Down Expand Up @@ -548,11 +541,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
),
};

ecx.probe(|r| CandidateKind::Candidate {
name: "builtin discriminant kind".into(),
result: *r,
})
.enter(|ecx| {
ecx.probe_candidate("builtin discriminant kind").enter(|ecx| {
ecx.eq(goal.param_env, goal.predicate.term, discriminant_ty.into())
.expect("expected goal term to be fully unconstrained");
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
Expand Down
Loading