|
1 | 1 | //! Code shared by trait and projection goals for candidate assembly.
|
2 | 2 |
|
3 | 3 | use super::infcx_ext::InferCtxtExt;
|
4 |
| -use super::{CanonicalResponse, EvalCtxt, Goal, QueryResult}; |
| 4 | +use super::{CanonicalResponse, Certainty, EvalCtxt, Goal, MaybeCause, QueryResult}; |
5 | 5 | use rustc_hir::def_id::DefId;
|
6 | 6 | use rustc_infer::traits::query::NoSolution;
|
7 | 7 | use rustc_infer::traits::util::elaborate_predicates;
|
@@ -79,7 +79,7 @@ pub(super) enum CandidateSource {
|
79 | 79 | AliasBound(usize),
|
80 | 80 | }
|
81 | 81 |
|
82 |
| -pub(super) trait GoalKind<'tcx>: TypeFoldable<'tcx> + Copy { |
| 82 | +pub(super) trait GoalKind<'tcx>: TypeFoldable<'tcx> + Copy + Eq { |
83 | 83 | fn self_ty(self) -> Ty<'tcx>;
|
84 | 84 |
|
85 | 85 | fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self;
|
@@ -117,13 +117,43 @@ pub(super) trait GoalKind<'tcx>: TypeFoldable<'tcx> + Copy {
|
117 | 117 | ecx: &mut EvalCtxt<'_, 'tcx>,
|
118 | 118 | goal: Goal<'tcx, Self>,
|
119 | 119 | ) -> QueryResult<'tcx>;
|
| 120 | + |
| 121 | + fn consider_builtin_pointer_sized_candidate( |
| 122 | + ecx: &mut EvalCtxt<'_, 'tcx>, |
| 123 | + goal: Goal<'tcx, Self>, |
| 124 | + ) -> QueryResult<'tcx>; |
| 125 | + |
| 126 | + fn consider_builtin_fn_trait_candidates( |
| 127 | + ecx: &mut EvalCtxt<'_, 'tcx>, |
| 128 | + goal: Goal<'tcx, Self>, |
| 129 | + kind: ty::ClosureKind, |
| 130 | + ) -> QueryResult<'tcx>; |
| 131 | + |
| 132 | + fn consider_builtin_tuple_candidate( |
| 133 | + ecx: &mut EvalCtxt<'_, 'tcx>, |
| 134 | + goal: Goal<'tcx, Self>, |
| 135 | + ) -> QueryResult<'tcx>; |
120 | 136 | }
|
121 | 137 |
|
122 | 138 | impl<'tcx> EvalCtxt<'_, 'tcx> {
|
123 | 139 | pub(super) fn assemble_and_evaluate_candidates<G: GoalKind<'tcx>>(
|
124 | 140 | &mut self,
|
125 | 141 | goal: Goal<'tcx, G>,
|
126 | 142 | ) -> Vec<Candidate<'tcx>> {
|
| 143 | + debug_assert_eq!(goal, self.infcx.resolve_vars_if_possible(goal)); |
| 144 | + |
| 145 | + // HACK: `_: Trait` is ambiguous, because it may be satisfied via a builtin rule, |
| 146 | + // object bound, alias bound, etc. We are unable to determine this until we can at |
| 147 | + // least structually resolve the type one layer. |
| 148 | + if goal.predicate.self_ty().is_ty_var() { |
| 149 | + return vec![Candidate { |
| 150 | + source: CandidateSource::BuiltinImpl, |
| 151 | + result: self |
| 152 | + .make_canonical_response(Certainty::Maybe(MaybeCause::Ambiguity)) |
| 153 | + .unwrap(), |
| 154 | + }]; |
| 155 | + } |
| 156 | + |
127 | 157 | let mut candidates = Vec::new();
|
128 | 158 |
|
129 | 159 | self.assemble_candidates_after_normalizing_self_ty(goal, &mut candidates);
|
@@ -169,6 +199,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
169 | 199 | Ok((_, certainty)) => certainty,
|
170 | 200 | Err(NoSolution) => return,
|
171 | 201 | };
|
| 202 | + let normalized_ty = self.infcx.resolve_vars_if_possible(normalized_ty); |
172 | 203 |
|
173 | 204 | // NOTE: Alternatively we could call `evaluate_goal` here and only have a `Normalized` candidate.
|
174 | 205 | // This doesn't work as long as we use `CandidateSource` in winnowing.
|
@@ -224,6 +255,12 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
224 | 255 | || lang_items.clone_trait() == Some(trait_def_id)
|
225 | 256 | {
|
226 | 257 | G::consider_builtin_copy_clone_candidate(self, goal)
|
| 258 | + } else if lang_items.pointer_sized() == Some(trait_def_id) { |
| 259 | + G::consider_builtin_pointer_sized_candidate(self, goal) |
| 260 | + } else if let Some(kind) = self.tcx().fn_trait_kind_from_def_id(trait_def_id) { |
| 261 | + G::consider_builtin_fn_trait_candidates(self, goal, kind) |
| 262 | + } else if lang_items.tuple_trait() == Some(trait_def_id) { |
| 263 | + G::consider_builtin_tuple_candidate(self, goal) |
227 | 264 | } else {
|
228 | 265 | Err(NoSolution)
|
229 | 266 | };
|
|
0 commit comments