mod.rs 30.9 KB
Newer Older
L
lcnr 已提交
1 2
//! Code shared by trait and projection goals for candidate assembly.

3
use super::search_graph::OverflowHandler;
L
lcnr 已提交
4
use super::{EvalCtxt, SolverMode};
L
lcnr 已提交
5
use crate::solve::CanonicalResponseExt;
L
lcnr 已提交
6
use crate::traits::coherence;
7
use rustc_data_structures::fx::FxIndexSet;
L
lcnr 已提交
8 9
use rustc_hir::def_id::DefId;
use rustc_infer::traits::query::NoSolution;
M
Michael Goulet 已提交
10
use rustc_infer::traits::util::elaborate;
11
use rustc_infer::traits::Reveal;
12
use rustc_middle::traits::solve::{CanonicalResponse, Certainty, Goal, MaybeCause, QueryResult};
13
use rustc_middle::ty::fast_reject::TreatProjections;
L
lcnr 已提交
14 15 16 17
use rustc_middle::ty::TypeFoldable;
use rustc_middle::ty::{self, Ty, TyCtxt};
use std::fmt::Debug;

L
lcnr 已提交
18 19
pub(super) mod structural_traits;

L
lcnr 已提交
20 21 22 23 24
/// A candidate is a possible way to prove a goal.
///
/// It consists of both the `source`, which describes how that goal would be proven,
/// and the `result` when using the given `source`.
#[derive(Debug, Clone)]
25 26
pub(super) struct Candidate<'tcx> {
    pub(super) source: CandidateSource,
L
lcnr 已提交
27 28 29
    pub(super) result: CanonicalResponse<'tcx>,
}

30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
/// Possible ways the given goal can be proven.
#[derive(Debug, Clone, Copy)]
pub(super) enum CandidateSource {
    /// A user written impl.
    ///
    /// ## Examples
    ///
    /// ```rust
    /// fn main() {
    ///     let x: Vec<u32> = Vec::new();
    ///     // This uses the impl from the standard library to prove `Vec<T>: Clone`.
    ///     let y = x.clone();
    /// }
    /// ```
    Impl(DefId),
    /// A builtin impl generated by the compiler. When adding a new special
    /// trait, try to use actual impls whenever possible. Builtin impls should
    /// only be used in cases where the impl cannot be manually be written.
    ///
    /// Notable examples are auto traits, `Sized`, and `DiscriminantKind`.
    /// For a list of all traits with builtin impls, check out the
    /// [`EvalCtxt::assemble_builtin_impl_candidates`] method. Not
    BuiltinImpl,
    /// An assumption from the environment.
    ///
J
Josh Soref 已提交
55
    /// More precisely we've used the `n-th` assumption in the `param_env`.
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
    ///
    /// ## Examples
    ///
    /// ```rust
    /// fn is_clone<T: Clone>(x: T) -> (T, T) {
    ///     // This uses the assumption `T: Clone` from the `where`-bounds
    ///     // to prove `T: Clone`.
    ///     (x.clone(), x)
    /// }
    /// ```
    ParamEnv(usize),
    /// If the self type is an alias type, e.g. an opaque type or a projection,
    /// we know the bounds on that alias to hold even without knowing its concrete
    /// underlying type.
    ///
    /// More precisely this candidate is using the `n-th` bound in the `item_bounds` of
    /// the self type.
    ///
    /// ## Examples
    ///
    /// ```rust
    /// trait Trait {
    ///     type Assoc: Clone;
    /// }
    ///
    /// fn foo<T: Trait>(x: <T as Trait>::Assoc) {
    ///     // We prove `<T as Trait>::Assoc` by looking at the bounds on `Assoc` in
    ///     // in the trait definition.
    ///     let _y = x.clone();
    /// }
    /// ```
87
    AliasBound,
88
}
L
lcnr 已提交
89

90
/// Methods used to assemble candidates for either trait or projection goals.
91 92 93
pub(super) trait GoalKind<'tcx>:
    TypeFoldable<TyCtxt<'tcx>> + Copy + Eq + std::fmt::Display
{
L
lcnr 已提交
94 95
    fn self_ty(self) -> Ty<'tcx>;

L
lcnr 已提交
96 97
    fn trait_ref(self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx>;

L
lcnr 已提交
98 99 100 101
    fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self;

    fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId;

102 103 104 105 106 107 108 109 110 111 112
    // Try equating an assumption predicate against a goal's predicate. If it
    // holds, then execute the `then` callback, which should do any additional
    // work, then produce a response (typically by executing
    // [`EvalCtxt::evaluate_added_goals_and_make_canonical_response`]).
    fn probe_and_match_goal_against_assumption(
        ecx: &mut EvalCtxt<'_, 'tcx>,
        goal: Goal<'tcx, Self>,
        assumption: ty::Predicate<'tcx>,
        then: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> QueryResult<'tcx>,
    ) -> QueryResult<'tcx>;

M
Michael Goulet 已提交
113 114 115 116
    // Consider a clause, which consists of a "assumption" and some "requirements",
    // to satisfy a goal. If the requirements hold, then attempt to satisfy our
    // goal by equating it with the assumption.
    fn consider_implied_clause(
117 118
        ecx: &mut EvalCtxt<'_, 'tcx>,
        goal: Goal<'tcx, Self>,
M
Michael Goulet 已提交
119
        assumption: ty::Predicate<'tcx>,
M
Michael Goulet 已提交
120
        requirements: impl IntoIterator<Item = Goal<'tcx, ty::Predicate<'tcx>>>,
121 122 123 124 125 126
    ) -> QueryResult<'tcx> {
        Self::probe_and_match_goal_against_assumption(ecx, goal, assumption, |ecx| {
            ecx.add_goals(requirements);
            ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
        })
    }
127

128 129 130 131 132 133 134 135
    /// Consider a bound originating from the item bounds of an alias. For this we
    /// require that the well-formed requirements of the self type of the goal
    /// are "satisfied from the param-env".
    /// See [`EvalCtxt::validate_alias_bound_self_from_param_env`].
    fn consider_alias_bound_candidate(
        ecx: &mut EvalCtxt<'_, 'tcx>,
        goal: Goal<'tcx, Self>,
        assumption: ty::Predicate<'tcx>,
136 137 138 139 140
    ) -> QueryResult<'tcx> {
        Self::probe_and_match_goal_against_assumption(ecx, goal, assumption, |ecx| {
            ecx.validate_alias_bound_self_from_param_env(goal)
        })
    }
141

142 143 144 145 146 147 148
    // Consider a clause specifically for a `dyn Trait` self type. This requires
    // additionally checking all of the supertraits and object bounds to hold,
    // since they're not implied by the well-formedness of the object type.
    fn consider_object_bound_candidate(
        ecx: &mut EvalCtxt<'_, 'tcx>,
        goal: Goal<'tcx, Self>,
        assumption: ty::Predicate<'tcx>,
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
    ) -> QueryResult<'tcx> {
        Self::probe_and_match_goal_against_assumption(ecx, goal, assumption, |ecx| {
            let tcx = ecx.tcx();
            let ty::Dynamic(bounds, _, _) = *goal.predicate.self_ty().kind() else {
                    bug!("expected object type in `consider_object_bound_candidate`");
                };
            ecx.add_goals(
                structural_traits::predicates_for_object_candidate(
                    &ecx,
                    goal.param_env,
                    goal.predicate.trait_ref(tcx),
                    bounds,
                )
                .into_iter()
                .map(|pred| goal.with(tcx, pred)),
            );
            ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
        })
    }
168

M
Michael Goulet 已提交
169
    fn consider_impl_candidate(
170 171
        ecx: &mut EvalCtxt<'_, 'tcx>,
        goal: Goal<'tcx, Self>,
M
Michael Goulet 已提交
172
        impl_def_id: DefId,
173
    ) -> QueryResult<'tcx>;
L
lcnr 已提交
174

M
Michael Goulet 已提交
175 176
    // A type implements an `auto trait` if its components do as well. These components
    // are given by built-in rules from [`instantiate_constituent_tys_for_auto_trait`].
M
Michael Goulet 已提交
177 178 179 180 181
    fn consider_auto_trait_candidate(
        ecx: &mut EvalCtxt<'_, 'tcx>,
        goal: Goal<'tcx, Self>,
    ) -> QueryResult<'tcx>;

M
Michael Goulet 已提交
182
    // A trait alias holds if the RHS traits and `where` clauses hold.
M
Michael Goulet 已提交
183 184 185 186 187
    fn consider_trait_alias_candidate(
        ecx: &mut EvalCtxt<'_, 'tcx>,
        goal: Goal<'tcx, Self>,
    ) -> QueryResult<'tcx>;

M
Michael Goulet 已提交
188 189
    // A type is `Copy` or `Clone` if its components are `Sized`. These components
    // are given by built-in rules from [`instantiate_constituent_tys_for_sized_trait`].
M
Michael Goulet 已提交
190
    fn consider_builtin_sized_candidate(
191 192
        ecx: &mut EvalCtxt<'_, 'tcx>,
        goal: Goal<'tcx, Self>,
193
    ) -> QueryResult<'tcx>;
M
Michael Goulet 已提交
194

M
Michael Goulet 已提交
195 196
    // A type is `Copy` or `Clone` if its components are `Copy` or `Clone`. These
    // components are given by built-in rules from [`instantiate_constituent_tys_for_copy_clone_trait`].
M
Michael Goulet 已提交
197 198 199 200
    fn consider_builtin_copy_clone_candidate(
        ecx: &mut EvalCtxt<'_, 'tcx>,
        goal: Goal<'tcx, Self>,
    ) -> QueryResult<'tcx>;
M
Michael Goulet 已提交
201

202
    // A type is `PointerLike` if we can compute its layout, and that layout
M
Michael Goulet 已提交
203
    // matches the layout of `usize`.
204
    fn consider_builtin_pointer_like_candidate(
M
Michael Goulet 已提交
205 206 207
        ecx: &mut EvalCtxt<'_, 'tcx>,
        goal: Goal<'tcx, Self>,
    ) -> QueryResult<'tcx>;
208

L
lcnr 已提交
209 210 211 212 213 214
    // A type is a `FnPtr` if it is of `FnPtr` type.
    fn consider_builtin_fn_ptr_trait_candidate(
        ecx: &mut EvalCtxt<'_, 'tcx>,
        goal: Goal<'tcx, Self>,
    ) -> QueryResult<'tcx>;

M
Michael Goulet 已提交
215 216
    // A callable type (a closure, fn def, or fn ptr) is known to implement the `Fn<A>`
    // family of traits where `A` is given by the signature of the type.
217 218 219 220 221 222
    fn consider_builtin_fn_trait_candidates(
        ecx: &mut EvalCtxt<'_, 'tcx>,
        goal: Goal<'tcx, Self>,
        kind: ty::ClosureKind,
    ) -> QueryResult<'tcx>;

M
Michael Goulet 已提交
223
    // `Tuple` is implemented if the `Self` type is a tuple.
224 225 226 227
    fn consider_builtin_tuple_candidate(
        ecx: &mut EvalCtxt<'_, 'tcx>,
        goal: Goal<'tcx, Self>,
    ) -> QueryResult<'tcx>;
B
Boxy 已提交
228

M
Michael Goulet 已提交
229 230 231 232 233
    // `Pointee` is always implemented.
    //
    // See the projection implementation for the `Metadata` types for all of
    // the built-in types. For structs, the metadata type is given by the struct
    // tail.
B
Boxy 已提交
234 235 236 237
    fn consider_builtin_pointee_candidate(
        ecx: &mut EvalCtxt<'_, 'tcx>,
        goal: Goal<'tcx, Self>,
    ) -> QueryResult<'tcx>;
M
Michael Goulet 已提交
238

M
Michael Goulet 已提交
239 240 241
    // A generator (that comes from an `async` desugaring) is known to implement
    // `Future<Output = O>`, where `O` is given by the generator's return type
    // that was computed during type-checking.
M
Michael Goulet 已提交
242 243 244 245 246
    fn consider_builtin_future_candidate(
        ecx: &mut EvalCtxt<'_, 'tcx>,
        goal: Goal<'tcx, Self>,
    ) -> QueryResult<'tcx>;

M
Michael Goulet 已提交
247 248 249
    // A generator (that doesn't come from an `async` desugaring) is known to
    // implement `Generator<R, Yield = Y, Return = O>`, given the resume, yield,
    // and return types of the generator computed during type-checking.
M
Michael Goulet 已提交
250 251 252 253
    fn consider_builtin_generator_candidate(
        ecx: &mut EvalCtxt<'_, 'tcx>,
        goal: Goal<'tcx, Self>,
    ) -> QueryResult<'tcx>;
254

255 256 257
    // The most common forms of unsizing are array to slice, and concrete (Sized)
    // type into a `dyn Trait`. ADTs and Tuples can also have their final field
    // unsized if it's generic.
258 259 260 261
    fn consider_builtin_unsize_candidate(
        ecx: &mut EvalCtxt<'_, 'tcx>,
        goal: Goal<'tcx, Self>,
    ) -> QueryResult<'tcx>;
262 263 264

    // `dyn Trait1` can be unsized to `dyn Trait2` if they are the same trait, or
    // if `Trait2` is a (transitive) supertrait of `Trait2`.
M
nits  
Michael Goulet 已提交
265
    fn consider_builtin_dyn_upcast_candidates(
266 267 268
        ecx: &mut EvalCtxt<'_, 'tcx>,
        goal: Goal<'tcx, Self>,
    ) -> Vec<CanonicalResponse<'tcx>>;
269 270 271 272 273

    fn consider_builtin_discriminant_kind_candidate(
        ecx: &mut EvalCtxt<'_, 'tcx>,
        goal: Goal<'tcx, Self>,
    ) -> QueryResult<'tcx>;
274 275 276 277 278

    fn consider_builtin_destruct_candidate(
        ecx: &mut EvalCtxt<'_, 'tcx>,
        goal: Goal<'tcx, Self>,
    ) -> QueryResult<'tcx>;
279 280 281 282 283

    fn consider_builtin_transmute_candidate(
        ecx: &mut EvalCtxt<'_, 'tcx>,
        goal: Goal<'tcx, Self>,
    ) -> QueryResult<'tcx>;
284
}
M
Michael Goulet 已提交
285

286 287 288
impl<'tcx> EvalCtxt<'_, 'tcx> {
    pub(super) fn assemble_and_evaluate_candidates<G: GoalKind<'tcx>>(
        &mut self,
L
lcnr 已提交
289
        goal: Goal<'tcx, G>,
290
    ) -> Vec<Candidate<'tcx>> {
291
        debug_assert_eq!(goal, self.resolve_vars_if_possible(goal));
292

M
Michael Goulet 已提交
293 294
        // HACK: `_: Trait` is ambiguous, because it may be satisfied via a builtin rule,
        // object bound, alias bound, etc. We are unable to determine this until we can at
J
Josh Soref 已提交
295
        // least structurally resolve the type one layer.
M
Michael Goulet 已提交
296 297 298
        if goal.predicate.self_ty().is_ty_var() {
            return vec![Candidate {
                source: CandidateSource::BuiltinImpl,
299 300 301
                result: self
                    .evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
                    .unwrap(),
M
Michael Goulet 已提交
302 303 304
            }];
        }

305
        let mut candidates = Vec::new();
L
lcnr 已提交
306

307
        self.assemble_candidates_after_normalizing_self_ty(goal, &mut candidates);
L
lcnr 已提交
308

309
        self.assemble_impl_candidates(goal, &mut candidates);
L
lcnr 已提交
310

311
        self.assemble_builtin_impl_candidates(goal, &mut candidates);
L
lcnr 已提交
312

313 314 315 316
        self.assemble_param_env_candidates(goal, &mut candidates);

        self.assemble_alias_bound_candidates(goal, &mut candidates);

317 318
        self.assemble_object_bound_candidates(goal, &mut candidates);

L
lcnr 已提交
319 320
        self.assemble_coherence_unknowable_candidates(goal, &mut candidates);

321
        candidates
L
lcnr 已提交
322 323 324 325 326
    }

    /// If the self type of a goal is a projection, computing the relevant candidates is difficult.
    ///
    /// To deal with this, we first try to normalize the self type and add the candidates for the normalized
L
lcnr 已提交
327 328
    /// self type to the list of candidates in case that succeeds. We also have to consider candidates with the
    /// projection as a self type as well
329
    #[instrument(level = "debug", skip_all)]
330 331 332 333 334 335
    fn assemble_candidates_after_normalizing_self_ty<G: GoalKind<'tcx>>(
        &mut self,
        goal: Goal<'tcx, G>,
        candidates: &mut Vec<Candidate<'tcx>>,
    ) {
        let tcx = self.tcx();
336
        let &ty::Alias(_, projection_ty) = goal.predicate.self_ty().kind() else {
L
lcnr 已提交
337 338
            return
        };
339

340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357
        let normalized_self_candidates: Result<_, NoSolution> = self.probe(|ecx| {
            ecx.with_incremented_depth(
                |ecx| {
                    let result = ecx.evaluate_added_goals_and_make_canonical_response(
                        Certainty::Maybe(MaybeCause::Overflow),
                    )?;
                    Ok(vec![Candidate { source: CandidateSource::BuiltinImpl, result }])
                },
                |ecx| {
                    let normalized_ty = ecx.next_ty_infer();
                    let normalizes_to_goal = goal.with(
                        tcx,
                        ty::Binder::dummy(ty::ProjectionPredicate {
                            projection_ty,
                            term: normalized_ty.into(),
                        }),
                    );
                    ecx.add_goal(normalizes_to_goal);
358 359 360
                    let _ = ecx.try_evaluate_added_goals().inspect_err(|_| {
                        debug!("self type normalization failed");
                    })?;
361
                    let normalized_ty = ecx.resolve_vars_if_possible(normalized_ty);
362
                    debug!(?normalized_ty, "self type normalized");
363 364 365 366 367 368 369
                    // NOTE: Alternatively we could call `evaluate_goal` here and only
                    // have a `Normalized` candidate. This doesn't work as long as we
                    // use `CandidateSource` in winnowing.
                    let goal = goal.with(tcx, goal.predicate.with_self_ty(tcx, normalized_ty));
                    Ok(ecx.assemble_and_evaluate_candidates(goal))
                },
            )
370
        });
371 372 373 374

        if let Ok(normalized_self_candidates) = normalized_self_candidates {
            candidates.extend(normalized_self_candidates);
        }
L
lcnr 已提交
375 376
    }

377
    #[instrument(level = "debug", skip_all)]
378 379 380 381 382 383
    fn assemble_impl_candidates<G: GoalKind<'tcx>>(
        &mut self,
        goal: Goal<'tcx, G>,
        candidates: &mut Vec<Candidate<'tcx>>,
    ) {
        let tcx = self.tcx();
384
        tcx.for_each_relevant_impl_treating_projections(
L
lcnr 已提交
385
            goal.predicate.trait_def_id(tcx),
L
lcnr 已提交
386
            goal.predicate.self_ty(),
387
            TreatProjections::NextSolverLookup,
388
            |impl_def_id| match G::consider_impl_candidate(self, goal, impl_def_id) {
389 390 391 392
                Ok(result) => candidates
                    .push(Candidate { source: CandidateSource::Impl(impl_def_id), result }),
                Err(NoSolution) => (),
            },
L
lcnr 已提交
393 394
        );
    }
395

396
    #[instrument(level = "debug", skip_all)]
397 398 399 400 401 402 403
    fn assemble_builtin_impl_candidates<G: GoalKind<'tcx>>(
        &mut self,
        goal: Goal<'tcx, G>,
        candidates: &mut Vec<Candidate<'tcx>>,
    ) {
        let lang_items = self.tcx().lang_items();
        let trait_def_id = goal.predicate.trait_def_id(self.tcx());
404 405 406 407 408 409 410 411

        // N.B. When assembling built-in candidates for lang items that are also
        // `auto` traits, then the auto trait candidate that is assembled in
        // `consider_auto_trait_candidate` MUST be disqualified to remain sound.
        //
        // Instead of adding the logic here, it's a better idea to add it in
        // `EvalCtxt::disqualify_auto_trait_candidate_due_to_possible_impl` in
        // `solve::trait_goals` instead.
M
Michael Goulet 已提交
412 413 414 415 416
        let result = if self.tcx().trait_is_auto(trait_def_id) {
            G::consider_auto_trait_candidate(self, goal)
        } else if self.tcx().trait_is_alias(trait_def_id) {
            G::consider_trait_alias_candidate(self, goal)
        } else if lang_items.sized_trait() == Some(trait_def_id) {
417
            G::consider_builtin_sized_candidate(self, goal)
M
Michael Goulet 已提交
418 419 420 421
        } else if lang_items.copy_trait() == Some(trait_def_id)
            || lang_items.clone_trait() == Some(trait_def_id)
        {
            G::consider_builtin_copy_clone_candidate(self, goal)
422 423
        } else if lang_items.pointer_like() == Some(trait_def_id) {
            G::consider_builtin_pointer_like_candidate(self, goal)
L
lcnr 已提交
424 425
        } else if lang_items.fn_ptr_trait() == Some(trait_def_id) {
            G::consider_builtin_fn_ptr_trait_candidate(self, goal)
426 427 428 429
        } else if let Some(kind) = self.tcx().fn_trait_kind_from_def_id(trait_def_id) {
            G::consider_builtin_fn_trait_candidates(self, goal, kind)
        } else if lang_items.tuple_trait() == Some(trait_def_id) {
            G::consider_builtin_tuple_candidate(self, goal)
B
Boxy 已提交
430 431
        } else if lang_items.pointee_trait() == Some(trait_def_id) {
            G::consider_builtin_pointee_candidate(self, goal)
M
Michael Goulet 已提交
432 433 434 435
        } else if lang_items.future_trait() == Some(trait_def_id) {
            G::consider_builtin_future_candidate(self, goal)
        } else if lang_items.gen_trait() == Some(trait_def_id) {
            G::consider_builtin_generator_candidate(self, goal)
436 437
        } else if lang_items.unsize_trait() == Some(trait_def_id) {
            G::consider_builtin_unsize_candidate(self, goal)
438 439
        } else if lang_items.discriminant_kind_trait() == Some(trait_def_id) {
            G::consider_builtin_discriminant_kind_candidate(self, goal)
440 441
        } else if lang_items.destruct_trait() == Some(trait_def_id) {
            G::consider_builtin_destruct_candidate(self, goal)
442 443
        } else if lang_items.transmute_trait() == Some(trait_def_id) {
            G::consider_builtin_transmute_candidate(self, goal)
444 445 446 447
        } else {
            Err(NoSolution)
        };

448
        match result {
449 450 451 452 453
            Ok(result) => {
                candidates.push(Candidate { source: CandidateSource::BuiltinImpl, result })
            }
            Err(NoSolution) => (),
        }
454 455 456 457

        // There may be multiple unsize candidates for a trait with several supertraits:
        // `trait Foo: Bar<A> + Bar<B>` and `dyn Foo: Unsize<dyn Bar<_>>`
        if lang_items.unsize_trait() == Some(trait_def_id) {
M
nits  
Michael Goulet 已提交
458
            for result in G::consider_builtin_dyn_upcast_candidates(self, goal) {
459 460 461
                candidates.push(Candidate { source: CandidateSource::BuiltinImpl, result });
            }
        }
462 463
    }

464
    #[instrument(level = "debug", skip_all)]
465 466 467 468 469 470
    fn assemble_param_env_candidates<G: GoalKind<'tcx>>(
        &mut self,
        goal: Goal<'tcx, G>,
        candidates: &mut Vec<Candidate<'tcx>>,
    ) {
        for (i, assumption) in goal.param_env.caller_bounds().iter().enumerate() {
M
Michael Goulet 已提交
471
            match G::consider_implied_clause(self, goal, assumption, []) {
472 473 474 475 476 477 478 479
                Ok(result) => {
                    candidates.push(Candidate { source: CandidateSource::ParamEnv(i), result })
                }
                Err(NoSolution) => (),
            }
        }
    }

480
    #[instrument(level = "debug", skip_all)]
481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504
    fn assemble_alias_bound_candidates<G: GoalKind<'tcx>>(
        &mut self,
        goal: Goal<'tcx, G>,
        candidates: &mut Vec<Candidate<'tcx>>,
    ) {
        let alias_ty = match goal.predicate.self_ty().kind() {
            ty::Bool
            | ty::Char
            | ty::Int(_)
            | ty::Uint(_)
            | ty::Float(_)
            | ty::Adt(_, _)
            | ty::Foreign(_)
            | ty::Str
            | ty::Array(_, _)
            | ty::Slice(_)
            | ty::RawPtr(_)
            | ty::Ref(_, _, _)
            | ty::FnDef(_, _)
            | ty::FnPtr(_)
            | ty::Dynamic(..)
            | ty::Closure(..)
            | ty::Generator(..)
            | ty::GeneratorWitness(_)
C
Camille GILLOT 已提交
505
            | ty::GeneratorWitnessMIR(..)
506 507 508 509
            | ty::Never
            | ty::Tuple(_)
            | ty::Param(_)
            | ty::Placeholder(..)
510
            | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
511
            | ty::Alias(ty::Inherent, _)
512
            | ty::Error(_) => return,
513 514
            ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
            | ty::Bound(..) => bug!("unexpected self type for `{goal:?}`"),
515 516
            // Excluding IATs here as they don't have meaningful item bounds.
            ty::Alias(ty::Projection | ty::Opaque, alias_ty) => alias_ty,
517 518
        };

519
        for assumption in self.tcx().item_bounds(alias_ty.def_id).subst(self.tcx(), alias_ty.substs)
520
        {
521
            match G::consider_alias_bound_candidate(self, goal, assumption) {
522
                Ok(result) => {
523
                    candidates.push(Candidate { source: CandidateSource::AliasBound, result })
524 525 526 527 528
                }
                Err(NoSolution) => (),
            }
        }
    }
529

530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628
    /// Check that we are allowed to use an alias bound originating from the self
    /// type of this goal. This means something different depending on the self type's
    /// alias kind.
    ///
    /// * Projection: Given a goal with a self type such as `<Ty as Trait>::Assoc`,
    /// we require that the bound `Ty: Trait` can be proven using either a nested alias
    /// bound candidate, or a param-env candidate.
    ///
    /// * Opaque: The param-env must be in `Reveal::UserFacing` mode. Otherwise,
    /// the goal should be proven by using the hidden type instead.
    #[instrument(level = "debug", skip(self), ret)]
    pub(super) fn validate_alias_bound_self_from_param_env<G: GoalKind<'tcx>>(
        &mut self,
        goal: Goal<'tcx, G>,
    ) -> QueryResult<'tcx> {
        match *goal.predicate.self_ty().kind() {
            ty::Alias(ty::Projection, projection_ty) => {
                let mut param_env_candidates = vec![];
                let self_trait_ref = projection_ty.trait_ref(self.tcx());

                if self_trait_ref.self_ty().is_ty_var() {
                    return self
                        .evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS);
                }

                let trait_goal: Goal<'_, ty::TraitPredicate<'tcx>> = goal.with(
                    self.tcx(),
                    ty::TraitPredicate {
                        trait_ref: self_trait_ref,
                        constness: ty::BoundConstness::NotConst,
                        polarity: ty::ImplPolarity::Positive,
                    },
                );

                self.assemble_param_env_candidates(trait_goal, &mut param_env_candidates);
                // FIXME: We probably need some sort of recursion depth check here.
                // Can't come up with an example yet, though, and the worst case
                // we can have is a compiler stack overflow...
                self.assemble_alias_bound_candidates(trait_goal, &mut param_env_candidates);

                // FIXME: We must also consider alias-bound candidates for a peculiar
                // class of built-in candidates that I'll call "defaulted" built-ins.
                //
                // For example, we always know that `T: Pointee` is implemented, but
                // we do not always know what `<T as Pointee>::Metadata` actually is,
                // similar to if we had a user-defined impl with a `default type ...`.
                // For these traits, since we're not able to always normalize their
                // associated types to a concrete type, we must consider their alias bounds
                // instead, so we can prove bounds such as `<T as Pointee>::Metadata: Copy`.
                self.assemble_alias_bound_candidates_for_builtin_impl_default_items(
                    trait_goal,
                    &mut param_env_candidates,
                );

                self.merge_candidates(param_env_candidates)
            }
            ty::Alias(ty::Opaque, _opaque_ty) => match goal.param_env.reveal() {
                Reveal::UserFacing => {
                    self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
                }
                Reveal::All => return Err(NoSolution),
            },
            _ => bug!("only expected to be called on alias tys"),
        }
    }

    /// Assemble a subset of builtin impl candidates for a class of candidates called
    /// "defaulted" built-in traits.
    ///
    /// For example, we always know that `T: Pointee` is implemented, but we do not
    /// always know what `<T as Pointee>::Metadata` actually is! See the comment in
    /// [`EvalCtxt::validate_alias_bound_self_from_param_env`] for more detail.
    #[instrument(level = "debug", skip_all)]
    fn assemble_alias_bound_candidates_for_builtin_impl_default_items<G: GoalKind<'tcx>>(
        &mut self,
        goal: Goal<'tcx, G>,
        candidates: &mut Vec<Candidate<'tcx>>,
    ) {
        let lang_items = self.tcx().lang_items();
        let trait_def_id = goal.predicate.trait_def_id(self.tcx());

        // You probably shouldn't add anything to this list unless you
        // know what you're doing.
        let result = if lang_items.pointee_trait() == Some(trait_def_id) {
            G::consider_builtin_pointee_candidate(self, goal)
        } else if lang_items.discriminant_kind_trait() == Some(trait_def_id) {
            G::consider_builtin_discriminant_kind_candidate(self, goal)
        } else {
            Err(NoSolution)
        };

        match result {
            Ok(result) => {
                candidates.push(Candidate { source: CandidateSource::BuiltinImpl, result })
            }
            Err(NoSolution) => (),
        }
    }

629
    #[instrument(level = "debug", skip_all)]
630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654
    fn assemble_object_bound_candidates<G: GoalKind<'tcx>>(
        &mut self,
        goal: Goal<'tcx, G>,
        candidates: &mut Vec<Candidate<'tcx>>,
    ) {
        let self_ty = goal.predicate.self_ty();
        let bounds = match *self_ty.kind() {
            ty::Bool
            | ty::Char
            | ty::Int(_)
            | ty::Uint(_)
            | ty::Float(_)
            | ty::Adt(_, _)
            | ty::Foreign(_)
            | ty::Str
            | ty::Array(_, _)
            | ty::Slice(_)
            | ty::RawPtr(_)
            | ty::Ref(_, _, _)
            | ty::FnDef(_, _)
            | ty::FnPtr(_)
            | ty::Alias(..)
            | ty::Closure(..)
            | ty::Generator(..)
            | ty::GeneratorWitness(_)
C
Camille GILLOT 已提交
655
            | ty::GeneratorWitnessMIR(..)
656 657 658 659
            | ty::Never
            | ty::Tuple(_)
            | ty::Param(_)
            | ty::Placeholder(..)
660
            | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
661
            | ty::Error(_) => return,
662 663
            ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
            | ty::Bound(..) => bug!("unexpected self type for `{goal:?}`"),
664 665 666 667
            ty::Dynamic(bounds, ..) => bounds,
        };

        let tcx = self.tcx();
668 669
        let own_bounds: FxIndexSet<_> =
            bounds.iter().map(|bound| bound.with_self_ty(tcx, self_ty)).collect();
670 671 672 673
        for assumption in elaborate(tcx, own_bounds.iter().copied())
            // we only care about bounds that match the `Self` type
            .filter_only_self()
        {
674 675 676 677 678 679 680 681 682 683 684 685
            // FIXME: Predicates are fully elaborated in the object type's existential bounds
            // list. We want to only consider these pre-elaborated projections, and not other
            // projection predicates that we reach by elaborating the principal trait ref,
            // since that'll cause ambiguity.
            //
            // We can remove this when we have implemented intersections in responses.
            if assumption.to_opt_poly_projection_pred().is_some()
                && !own_bounds.contains(&assumption)
            {
                continue;
            }

686
            match G::consider_object_bound_candidate(self, goal, assumption) {
687 688 689 690 691 692 693
                Ok(result) => {
                    candidates.push(Candidate { source: CandidateSource::BuiltinImpl, result })
                }
                Err(NoSolution) => (),
            }
        }
    }
M
Michael Goulet 已提交
694

695
    #[instrument(level = "debug", skip_all)]
L
lcnr 已提交
696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721
    fn assemble_coherence_unknowable_candidates<G: GoalKind<'tcx>>(
        &mut self,
        goal: Goal<'tcx, G>,
        candidates: &mut Vec<Candidate<'tcx>>,
    ) {
        match self.solver_mode() {
            SolverMode::Normal => return,
            SolverMode::Coherence => {
                let trait_ref = goal.predicate.trait_ref(self.tcx());
                match coherence::trait_ref_is_knowable(self.tcx(), trait_ref) {
                    Ok(()) => {}
                    Err(_) => match self
                        .evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
                    {
                        Ok(result) => candidates
                            .push(Candidate { source: CandidateSource::BuiltinImpl, result }),
                        // FIXME: This will be reachable at some point if we're in
                        // `assemble_candidates_after_normalizing_self_ty` and we get a
                        // universe error. We'll deal with it at this point.
                        Err(NoSolution) => bug!("coherence candidate resulted in NoSolution"),
                    },
                }
            }
        }
    }

L
lcnr 已提交
722 723 724
    /// If there are multiple ways to prove a trait or projection goal, we have
    /// to somehow try to merge the candidates into one. If that fails, we return
    /// ambiguity.
M
Michael Goulet 已提交
725
    #[instrument(level = "debug", skip(self), ret)]
L
lcnr 已提交
726
    pub(super) fn merge_candidates(
M
Michael Goulet 已提交
727 728 729
        &mut self,
        mut candidates: Vec<Candidate<'tcx>>,
    ) -> QueryResult<'tcx> {
L
lcnr 已提交
730 731 732 733
        // First try merging all candidates. This is complete and fully sound.
        let responses = candidates.iter().map(|c| c.result).collect::<Vec<_>>();
        if let Some(result) = self.try_merge_responses(&responses) {
            return Ok(result);
M
Michael Goulet 已提交
734 735
        }

L
lcnr 已提交
736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752
        // We then check whether we should prioritize `ParamEnv` candidates.
        //
        // Doing so is incomplete and would therefore be unsound during coherence.
        match self.solver_mode() {
            SolverMode::Coherence => (),
            // Prioritize `ParamEnv` candidates only if they do not guide inference.
            //
            // This is still incomplete as we may add incorrect region bounds.
            SolverMode::Normal => {
                let param_env_responses = candidates
                    .iter()
                    .filter(|c| matches!(c.source, CandidateSource::ParamEnv(_)))
                    .map(|c| c.result)
                    .collect::<Vec<_>>();
                if let Some(result) = self.try_merge_responses(&param_env_responses) {
                    if result.has_only_region_constraints() {
                        return Ok(result);
M
Michael Goulet 已提交
753 754 755 756
                    }
                }
            }
        }
L
lcnr 已提交
757
        self.flounder(&responses)
M
Michael Goulet 已提交
758
    }
L
lcnr 已提交
759
}