Address goal nits

This commit is contained in:
Michael Goulet 2023-01-20 18:38:33 +00:00
parent d6a411c086
commit 444cbcd729
4 changed files with 54 additions and 38 deletions

View File

@ -1,7 +1,7 @@
//! Code shared by trait and projection goals for candidate assembly. //! Code shared by trait and projection goals for candidate assembly.
use super::infcx_ext::InferCtxtExt; use super::infcx_ext::InferCtxtExt;
use super::{CanonicalResponse, Certainty, EvalCtxt, Goal, MaybeCause, QueryResult}; use super::{CanonicalResponse, Certainty, EvalCtxt, Goal, QueryResult};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::query::NoSolution;
use rustc_infer::traits::util::elaborate_predicates; use rustc_infer::traits::util::elaborate_predicates;
@ -148,9 +148,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
if goal.predicate.self_ty().is_ty_var() { if goal.predicate.self_ty().is_ty_var() {
return vec![Candidate { return vec![Candidate {
source: CandidateSource::BuiltinImpl, source: CandidateSource::BuiltinImpl,
result: self result: self.make_canonical_response(Certainty::AMBIGUOUS).unwrap(),
.make_canonical_response(Certainty::Maybe(MaybeCause::Ambiguity))
.unwrap(),
}]; }];
} }

View File

@ -19,6 +19,7 @@
use std::mem; use std::mem;
use rustc_hir::def_id::DefId;
use rustc_infer::infer::canonical::{Canonical, CanonicalVarKind, CanonicalVarValues}; use rustc_infer::infer::canonical::{Canonical, CanonicalVarKind, CanonicalVarValues};
use rustc_infer::infer::canonical::{OriginalQueryValues, QueryRegionConstraints, QueryResponse}; use rustc_infer::infer::canonical::{OriginalQueryValues, QueryRegionConstraints, QueryResponse};
use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt}; use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
@ -27,7 +28,7 @@ use rustc_infer::traits::Obligation;
use rustc_middle::infer::canonical::Certainty as OldCertainty; use rustc_middle::infer::canonical::Certainty as OldCertainty;
use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{ use rustc_middle::ty::{
RegionOutlivesPredicate, SubtypePredicate, ToPredicate, TypeOutlivesPredicate, CoercePredicate, RegionOutlivesPredicate, SubtypePredicate, ToPredicate, TypeOutlivesPredicate,
}; };
use rustc_span::DUMMY_SP; use rustc_span::DUMMY_SP;
@ -89,6 +90,8 @@ pub enum Certainty {
} }
impl Certainty { impl Certainty {
pub const AMBIGUOUS: Certainty = Certainty::Maybe(MaybeCause::Ambiguity);
/// When proving multiple goals using **AND**, e.g. nested obligations for an impl, /// When proving multiple goals using **AND**, e.g. nested obligations for an impl,
/// use this function to unify the certainty of these goals /// use this function to unify the certainty of these goals
pub fn unify_and(self, other: Certainty) -> Certainty { pub fn unify_and(self, other: Certainty) -> Certainty {
@ -248,21 +251,15 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
ty::PredicateKind::Subtype(predicate) => { ty::PredicateKind::Subtype(predicate) => {
self.compute_subtype_goal(Goal { param_env, predicate }) self.compute_subtype_goal(Goal { param_env, predicate })
} }
ty::PredicateKind::Coerce(predicate) => self.compute_subtype_goal(Goal { ty::PredicateKind::Coerce(predicate) => {
param_env, self.compute_coerce_goal(Goal { param_env, predicate })
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::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 :) // FIXME: implement these predicates :)
ty::PredicateKind::WellFormed(_) ty::PredicateKind::WellFormed(_)
| ty::PredicateKind::ObjectSafe(_) | ty::PredicateKind::ObjectSafe(_)
@ -296,28 +293,50 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
self.make_canonical_response(Certainty::Yes) 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( fn compute_subtype_goal(
&mut self, &mut self,
goal: Goal<'tcx, SubtypePredicate<'tcx>>, goal: Goal<'tcx, SubtypePredicate<'tcx>>,
) -> QueryResult<'tcx> { ) -> QueryResult<'tcx> {
self.infcx.probe(|_| { if goal.predicate.a.is_ty_var() && goal.predicate.b.is_ty_var() {
let InferOk { value: (), obligations } = self // FIXME: Do we want to register a subtype relation between these vars?
.infcx // That won't actually reflect in the query response, so it seems moot.
.at(&ObligationCause::dummy(), goal.param_env) self.make_canonical_response(Certainty::AMBIGUOUS)
.sub(goal.predicate.a, goal.predicate.b)?; } else {
self.evaluate_all_and_make_canonical_response( self.infcx.probe(|_| {
obligations.into_iter().map(|pred| pred.into()).collect(), 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( fn compute_closure_kind_goal(
&mut self, &mut self,
found_kind: Option<ty::ClosureKind>, goal: Goal<'tcx, (DefId, ty::SubstsRef<'tcx>, ty::ClosureKind)>,
expected_kind: ty::ClosureKind,
) -> QueryResult<'tcx> { ) -> 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 { 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) { if found_kind.extends(expected_kind) {
self.make_canonical_response(Certainty::Yes) self.make_canonical_response(Certainty::Yes)

View File

@ -3,7 +3,7 @@ use crate::traits::{specialization_graph, translate_substs};
use super::assembly::{self, Candidate, CandidateSource}; use super::assembly::{self, Candidate, CandidateSource};
use super::infcx_ext::InferCtxtExt; use super::infcx_ext::InferCtxtExt;
use super::trait_goals::structural_traits; 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_errors::ErrorGuaranteed;
use rustc_hir::def::DefKind; use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
@ -229,8 +229,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
goal.predicate.def_id(), goal.predicate.def_id(),
impl_def_id impl_def_id
)? else { )? else {
let certainty = Certainty::Maybe(MaybeCause::Ambiguity); return ecx.make_canonical_response(trait_ref_certainty.unify_and(Certainty::AMBIGUOUS));
return ecx.make_canonical_response(trait_ref_certainty.unify_and(certainty));
}; };
if !assoc_def.item.defaultness(tcx).has_value() { if !assoc_def.item.defaultness(tcx).has_value() {
@ -382,7 +381,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
.to_predicate(ecx.tcx()); .to_predicate(ecx.tcx());
Self::consider_assumption(ecx, goal, pred) Self::consider_assumption(ecx, goal, pred)
} else { } else {
ecx.make_canonical_response(Certainty::Maybe(MaybeCause::Ambiguity)) ecx.make_canonical_response(Certainty::AMBIGUOUS)
} }
} }

View File

@ -4,7 +4,7 @@ use std::iter;
use super::assembly::{self, Candidate, CandidateSource}; use super::assembly::{self, Candidate, CandidateSource};
use super::infcx_ext::InferCtxtExt; 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_hir::def_id::DefId;
use rustc_infer::infer::InferCtxt; use rustc_infer::infer::InferCtxt;
use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::query::NoSolution;
@ -133,7 +133,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
goal: Goal<'tcx, Self>, goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx> { ) -> QueryResult<'tcx> {
if goal.predicate.self_ty().has_non_region_infer() { 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(); let tcx = ecx.tcx();
@ -171,7 +171,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
.to_predicate(ecx.tcx()); .to_predicate(ecx.tcx());
Self::consider_assumption(ecx, goal, pred) Self::consider_assumption(ecx, goal, pred)
} else { } else {
ecx.make_canonical_response(Certainty::Maybe(MaybeCause::Ambiguity)) ecx.make_canonical_response(Certainty::AMBIGUOUS)
} }
} }