use std::mem;
+use rustc_hir::def_id::DefId;
use rustc_infer::infer::canonical::{Canonical, CanonicalVarKind, CanonicalVarValues};
use rustc_infer::infer::canonical::{OriginalQueryValues, QueryRegionConstraints, QueryResponse};
use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
use rustc_middle::infer::canonical::Certainty as OldCertainty;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{
- RegionOutlivesPredicate, SubtypePredicate, ToPredicate, TypeOutlivesPredicate,
+ CoercePredicate, RegionOutlivesPredicate, SubtypePredicate, ToPredicate, TypeOutlivesPredicate,
};
use rustc_span::DUMMY_SP;
}
impl Certainty {
+ pub const AMBIGUOUS: Certainty = Certainty::Maybe(MaybeCause::Ambiguity);
+
/// When proving multiple goals using **AND**, e.g. nested obligations for an impl,
/// use this function to unify the certainty of these goals
pub fn unify_and(self, other: Certainty) -> Certainty {
ty::PredicateKind::Subtype(predicate) => {
self.compute_subtype_goal(Goal { param_env, predicate })
}
- ty::PredicateKind::Coerce(predicate) => self.compute_subtype_goal(Goal {
- param_env,
- predicate: SubtypePredicate {
- a_is_expected: true,
- a: predicate.a,
- b: predicate.b,
- },
- }),
- ty::PredicateKind::ClosureKind(_, substs, kind) => self.compute_closure_kind_goal(
- substs.as_closure().kind_ty().to_opt_closure_kind(),
- kind,
- ),
- ty::PredicateKind::Ambiguous => {
- self.make_canonical_response(Certainty::Maybe(MaybeCause::Ambiguity))
+ ty::PredicateKind::Coerce(predicate) => {
+ self.compute_coerce_goal(Goal { param_env, predicate })
}
+ ty::PredicateKind::ClosureKind(def_id, substs, kind) => self
+ .compute_closure_kind_goal(Goal {
+ param_env,
+ predicate: (def_id, substs, kind),
+ }),
+ ty::PredicateKind::Ambiguous => self.make_canonical_response(Certainty::AMBIGUOUS),
// FIXME: implement these predicates :)
ty::PredicateKind::WellFormed(_)
| ty::PredicateKind::ObjectSafe(_)
self.make_canonical_response(Certainty::Yes)
}
+ fn compute_coerce_goal(
+ &mut self,
+ goal: Goal<'tcx, CoercePredicate<'tcx>>,
+ ) -> QueryResult<'tcx> {
+ self.compute_subtype_goal(Goal {
+ param_env: goal.param_env,
+ predicate: SubtypePredicate {
+ a_is_expected: false,
+ a: goal.predicate.a,
+ b: goal.predicate.b,
+ },
+ })
+ }
+
fn compute_subtype_goal(
&mut self,
goal: Goal<'tcx, SubtypePredicate<'tcx>>,
) -> QueryResult<'tcx> {
- self.infcx.probe(|_| {
- let InferOk { value: (), obligations } = self
- .infcx
- .at(&ObligationCause::dummy(), goal.param_env)
- .sub(goal.predicate.a, goal.predicate.b)?;
- self.evaluate_all_and_make_canonical_response(
- obligations.into_iter().map(|pred| pred.into()).collect(),
- )
- })
+ if goal.predicate.a.is_ty_var() && goal.predicate.b.is_ty_var() {
+ // FIXME: Do we want to register a subtype relation between these vars?
+ // That won't actually reflect in the query response, so it seems moot.
+ self.make_canonical_response(Certainty::AMBIGUOUS)
+ } else {
+ self.infcx.probe(|_| {
+ let InferOk { value: (), obligations } = self
+ .infcx
+ .at(&ObligationCause::dummy(), goal.param_env)
+ .sub(goal.predicate.a, goal.predicate.b)?;
+ self.evaluate_all_and_make_canonical_response(
+ obligations.into_iter().map(|pred| pred.into()).collect(),
+ )
+ })
+ }
}
fn compute_closure_kind_goal(
&mut self,
- found_kind: Option<ty::ClosureKind>,
- expected_kind: ty::ClosureKind,
+ goal: Goal<'tcx, (DefId, ty::SubstsRef<'tcx>, ty::ClosureKind)>,
) -> QueryResult<'tcx> {
+ let (_, substs, expected_kind) = goal.predicate;
+ let found_kind = substs.as_closure().kind_ty().to_opt_closure_kind();
+
let Some(found_kind) = found_kind else {
- return self.make_canonical_response(Certainty::Maybe(MaybeCause::Ambiguity));
+ return self.make_canonical_response(Certainty::AMBIGUOUS);
};
if found_kind.extends(expected_kind) {
self.make_canonical_response(Certainty::Yes)
use super::assembly::{self, Candidate, CandidateSource};
use super::infcx_ext::InferCtxtExt;
use super::trait_goals::structural_traits;
-use super::{Certainty, EvalCtxt, Goal, MaybeCause, QueryResult};
+use super::{Certainty, EvalCtxt, Goal, QueryResult};
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
goal.predicate.def_id(),
impl_def_id
)? else {
- let certainty = Certainty::Maybe(MaybeCause::Ambiguity);
- return ecx.make_canonical_response(trait_ref_certainty.unify_and(certainty));
+ return ecx.make_canonical_response(trait_ref_certainty.unify_and(Certainty::AMBIGUOUS));
};
if !assoc_def.item.defaultness(tcx).has_value() {
.to_predicate(ecx.tcx());
Self::consider_assumption(ecx, goal, pred)
} else {
- ecx.make_canonical_response(Certainty::Maybe(MaybeCause::Ambiguity))
+ ecx.make_canonical_response(Certainty::AMBIGUOUS)
}
}
use super::assembly::{self, Candidate, CandidateSource};
use super::infcx_ext::InferCtxtExt;
-use super::{Certainty, EvalCtxt, Goal, MaybeCause, QueryResult};
+use super::{Certainty, EvalCtxt, Goal, QueryResult};
use rustc_hir::def_id::DefId;
use rustc_infer::infer::InferCtxt;
use rustc_infer::traits::query::NoSolution;
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx> {
if goal.predicate.self_ty().has_non_region_infer() {
- return ecx.make_canonical_response(Certainty::Maybe(MaybeCause::Ambiguity));
+ return ecx.make_canonical_response(Certainty::AMBIGUOUS);
}
let tcx = ecx.tcx();
.to_predicate(ecx.tcx());
Self::consider_assumption(ecx, goal, pred)
} else {
- ecx.make_canonical_response(Certainty::Maybe(MaybeCause::Ambiguity))
+ ecx.make_canonical_response(Certainty::AMBIGUOUS)
}
}