Skip to content

Commit

Permalink
add ecx.probe_candidate
Browse files Browse the repository at this point in the history
  • Loading branch information
lcnr committed Jul 4, 2023
1 parent cd68ead commit 795c2ef
Show file tree
Hide file tree
Showing 5 changed files with 280 additions and 298 deletions.
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

0 comments on commit 795c2ef

Please sign in to comment.