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

L
lcnr 已提交
3 4
use super::{EvalCtxt, SolverMode};
use crate::traits::coherence;
L
lcnr 已提交
5 6
use rustc_hir::def_id::DefId;
use rustc_infer::traits::query::NoSolution;
7
use rustc_infer::traits::Reveal;
8
use rustc_middle::traits::solve::inspect::CandidateKind;
9
use rustc_middle::traits::solve::{CanonicalResponse, Certainty, Goal, QueryResult};
M
Michael Goulet 已提交
10
use rustc_middle::traits::BuiltinImplSource;
11
use rustc_middle::ty::fast_reject::{SimplifiedType, TreatParams};
L
lcnr 已提交
12
use rustc_middle::ty::{self, Ty, TyCtxt};
13
use rustc_middle::ty::{fast_reject, TypeFoldable};
M
Michael Goulet 已提交
14
use rustc_middle::ty::{ToPredicate, TypeVisitableExt};
15
use rustc_span::ErrorGuaranteed;
L
lcnr 已提交
16 17
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
/// 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
52
    BuiltinImpl(BuiltinImplSource),
53 54
    /// 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
    /// 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`]).
106 107 108
    fn probe_and_match_goal_against_assumption(
        ecx: &mut EvalCtxt<'_, 'tcx>,
        goal: Goal<'tcx, Self>,
M
Michael Goulet 已提交
109
        assumption: ty::Clause<'tcx>,
110 111 112
        then: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> QueryResult<'tcx>,
    ) -> QueryResult<'tcx>;

113 114 115
    /// 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.
M
Michael Goulet 已提交
116
    fn consider_implied_clause(
117 118
        ecx: &mut EvalCtxt<'_, 'tcx>,
        goal: Goal<'tcx, Self>,
M
Michael Goulet 已提交
119
        assumption: ty::Clause<'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
    /// 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>,
M
Michael Goulet 已提交
135
        assumption: ty::Clause<'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
    /// 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.
145 146 147
    fn consider_object_bound_candidate(
        ecx: &mut EvalCtxt<'_, 'tcx>,
        goal: Goal<'tcx, Self>,
M
Michael Goulet 已提交
148
        assumption: ty::Clause<'tcx>,
149 150 151 152
    ) -> 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 {
153 154
                bug!("expected object type in `consider_object_bound_candidate`");
            };
155 156 157 158 159 160
            ecx.add_goals(structural_traits::predicates_for_object_candidate(
                &ecx,
                goal.param_env,
                goal.predicate.trait_ref(tcx),
                bounds,
            ));
161 162 163
            ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
        })
    }
164

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

L
lcnr 已提交
171 172 173
    /// If the predicate contained an error, we want to avoid emitting unnecessary trait
    /// errors but still want to emit errors for other trait goals. We have some special
    /// handling for this case.
174
    ///
L
lcnr 已提交
175 176
    /// Trait goals always hold while projection goals never do. This is a bit arbitrary
    /// but prevents incorrect normalization while hiding any trait errors.
177 178 179 180 181
    fn consider_error_guaranteed_candidate(
        ecx: &mut EvalCtxt<'_, 'tcx>,
        guar: ErrorGuaranteed,
    ) -> QueryResult<'tcx>;

L
lcnr 已提交
182 183 184 185
    /// A type implements an `auto trait` if its components do as well.
    ///
    /// These components are given by built-in rules from
    /// [`structural_traits::instantiate_constituent_tys_for_auto_trait`].
M
Michael Goulet 已提交
186 187 188 189 190
    fn consider_auto_trait_candidate(
        ecx: &mut EvalCtxt<'_, 'tcx>,
        goal: Goal<'tcx, Self>,
    ) -> QueryResult<'tcx>;

191
    /// A trait alias holds if the RHS traits and `where` clauses hold.
M
Michael Goulet 已提交
192 193 194 195 196
    fn consider_trait_alias_candidate(
        ecx: &mut EvalCtxt<'_, 'tcx>,
        goal: Goal<'tcx, Self>,
    ) -> QueryResult<'tcx>;

L
lcnr 已提交
197 198 199 200
    /// A type is `Copy` or `Clone` if its components are `Sized`.
    ///
    /// These components are given by built-in rules from
    /// [`structural_traits::instantiate_constituent_tys_for_sized_trait`].
M
Michael Goulet 已提交
201
    fn consider_builtin_sized_candidate(
202 203
        ecx: &mut EvalCtxt<'_, 'tcx>,
        goal: Goal<'tcx, Self>,
204
    ) -> QueryResult<'tcx>;
M
Michael Goulet 已提交
205

L
lcnr 已提交
206 207 208 209
    /// A type is `Copy` or `Clone` if its components are `Copy` or `Clone`.
    ///
    /// These components are given by built-in rules from
    /// [`structural_traits::instantiate_constituent_tys_for_copy_clone_trait`].
M
Michael Goulet 已提交
210 211 212 213
    fn consider_builtin_copy_clone_candidate(
        ecx: &mut EvalCtxt<'_, 'tcx>,
        goal: Goal<'tcx, Self>,
    ) -> QueryResult<'tcx>;
M
Michael Goulet 已提交
214

215 216
    /// A type is `PointerLike` if we can compute its layout, and that layout
    /// matches the layout of `usize`.
217
    fn consider_builtin_pointer_like_candidate(
M
Michael Goulet 已提交
218 219 220
        ecx: &mut EvalCtxt<'_, 'tcx>,
        goal: Goal<'tcx, Self>,
    ) -> QueryResult<'tcx>;
221

222
    /// A type is a `FnPtr` if it is of `FnPtr` type.
L
lcnr 已提交
223 224 225 226 227
    fn consider_builtin_fn_ptr_trait_candidate(
        ecx: &mut EvalCtxt<'_, 'tcx>,
        goal: Goal<'tcx, Self>,
    ) -> QueryResult<'tcx>;

228 229
    /// 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.
230 231 232 233 234 235
    fn consider_builtin_fn_trait_candidates(
        ecx: &mut EvalCtxt<'_, 'tcx>,
        goal: Goal<'tcx, Self>,
        kind: ty::ClosureKind,
    ) -> QueryResult<'tcx>;

236
    /// `Tuple` is implemented if the `Self` type is a tuple.
237 238 239 240
    fn consider_builtin_tuple_candidate(
        ecx: &mut EvalCtxt<'_, 'tcx>,
        goal: Goal<'tcx, Self>,
    ) -> QueryResult<'tcx>;
B
Boxy 已提交
241

242 243 244 245 246
    /// `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 已提交
247 248 249 250
    fn consider_builtin_pointee_candidate(
        ecx: &mut EvalCtxt<'_, 'tcx>,
        goal: Goal<'tcx, Self>,
    ) -> QueryResult<'tcx>;
M
Michael Goulet 已提交
251

252 253 254
    /// 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 已提交
255 256 257 258 259
    fn consider_builtin_future_candidate(
        ecx: &mut EvalCtxt<'_, 'tcx>,
        goal: Goal<'tcx, Self>,
    ) -> QueryResult<'tcx>;

260 261 262
    /// 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 已提交
263 264 265 266
    fn consider_builtin_generator_candidate(
        ecx: &mut EvalCtxt<'_, 'tcx>,
        goal: Goal<'tcx, Self>,
    ) -> QueryResult<'tcx>;
267

268 269 270 271
    fn consider_builtin_discriminant_kind_candidate(
        ecx: &mut EvalCtxt<'_, 'tcx>,
        goal: Goal<'tcx, Self>,
    ) -> QueryResult<'tcx>;
272 273 274 275 276

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

    fn consider_builtin_transmute_candidate(
        ecx: &mut EvalCtxt<'_, 'tcx>,
        goal: Goal<'tcx, Self>,
    ) -> QueryResult<'tcx>;
M
Michael Goulet 已提交
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296

    /// Consider (possibly several) candidates to upcast or unsize a type to another
    /// type.
    ///
    /// 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.
    ///
    /// `dyn Trait1` can be unsized to `dyn Trait2` if they are the same trait, or
    /// if `Trait2` is a (transitive) supertrait of `Trait2`.
    ///
    /// We return the `BuiltinImplSource` for each candidate as it is needed
    /// for unsize coercion in hir typeck and because it is difficult to
    /// otherwise recompute this for codegen. This is a bit of a mess but the
    /// easiest way to maintain the existing behavior for now.
297
    fn consider_builtin_unsize_candidates(
M
Michael Goulet 已提交
298 299 300
        ecx: &mut EvalCtxt<'_, 'tcx>,
        goal: Goal<'tcx, Self>,
    ) -> Vec<(CanonicalResponse<'tcx>, BuiltinImplSource)>;
301
}
M
Michael Goulet 已提交
302

303 304 305
impl<'tcx> EvalCtxt<'_, 'tcx> {
    pub(super) fn assemble_and_evaluate_candidates<G: GoalKind<'tcx>>(
        &mut self,
L
lcnr 已提交
306
        goal: Goal<'tcx, G>,
307
    ) -> Vec<Candidate<'tcx>> {
308
        debug_assert_eq!(goal, self.resolve_vars_if_possible(goal));
L
review  
lcnr 已提交
309
        if let Some(ambig) = self.assemble_self_ty_infer_ambiguity_response(goal) {
310 311 312
            return ambig;
        }

313
        let mut candidates = self.assemble_candidates_via_self_ty(goal, 0);
314 315 316 317

        self.assemble_blanket_impl_candidates(goal, &mut candidates);

        self.assemble_param_env_candidates(goal, &mut candidates);
318

319 320
        self.assemble_coherence_unknowable_candidates(goal, &mut candidates);

321 322 323
        candidates
    }

L
review  
lcnr 已提交
324
    /// `?0: Trait` is ambiguous, because it may be satisfied via a builtin rule,
L
lcnr 已提交
325 326 327 328 329
    /// object bound, alias bound, etc. We are unable to determine this until we can at
    /// least structurally resolve the type one layer.
    ///
    /// It would also require us to consider all impls of the trait, which is both pretty
    /// bad for perf and would also constrain the self type if there is just a single impl.
L
review  
lcnr 已提交
330
    fn assemble_self_ty_infer_ambiguity_response<G: GoalKind<'tcx>>(
331 332 333 334 335
        &mut self,
        goal: Goal<'tcx, G>,
    ) -> Option<Vec<Candidate<'tcx>>> {
        goal.predicate.self_ty().is_ty_var().then(|| {
            vec![Candidate {
M
Michael Goulet 已提交
336
                source: CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
337 338 339
                result: self
                    .evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
                    .unwrap(),
340 341 342 343 344 345 346 347 348 349 350
            }]
        })
    }

    /// Assemble candidates which apply to the self type. This only looks at candidate which
    /// apply to the specific self type and ignores all others.
    ///
    /// Returns `None` if the self type is still ambiguous.
    fn assemble_candidates_via_self_ty<G: GoalKind<'tcx>>(
        &mut self,
        goal: Goal<'tcx, G>,
351
        num_steps: usize,
352 353
    ) -> Vec<Candidate<'tcx>> {
        debug_assert_eq!(goal, self.resolve_vars_if_possible(goal));
L
review  
lcnr 已提交
354
        if let Some(ambig) = self.assemble_self_ty_infer_ambiguity_response(goal) {
355
            return ambig;
M
Michael Goulet 已提交
356 357
        }

358
        let mut candidates = Vec::new();
L
lcnr 已提交
359

360
        self.assemble_non_blanket_impl_candidates(goal, &mut candidates);
L
lcnr 已提交
361

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

364 365
        self.assemble_alias_bound_candidates(goal, &mut candidates);

366 367
        self.assemble_object_bound_candidates(goal, &mut candidates);

368
        self.assemble_candidates_after_normalizing_self_ty(goal, &mut candidates, num_steps);
369
        candidates
L
lcnr 已提交
370 371
    }

372 373
    /// If the self type of a goal is an alias we first try to normalize the self type
    /// and compute the candidates for the normalized self type in case that succeeds.
L
lcnr 已提交
374
    ///
375 376 377 378 379 380 381 382 383 384 385
    /// These candidates are used in addition to the ones with the alias as a self type.
    /// We do this to simplify both builtin candidates and for better performance.
    ///
    /// We generate the builtin candidates on the fly by looking at the self type, e.g.
    /// add `FnPtr` candidates if the self type is a function pointer. Handling builtin
    /// candidates while the self type is still an alias seems difficult. This is similar
    /// to `try_structurally_resolve_type` during hir typeck (FIXME once implemented).
    ///
    /// Looking at all impls for some trait goal is prohibitively expensive. We therefore
    /// only look at implementations with a matching self type. Because of this function,
    /// we can avoid looking at all existing impls if the self type is an alias.
386
    #[instrument(level = "debug", skip_all)]
387 388 389 390
    fn assemble_candidates_after_normalizing_self_ty<G: GoalKind<'tcx>>(
        &mut self,
        goal: Goal<'tcx, G>,
        candidates: &mut Vec<Candidate<'tcx>>,
391
        num_steps: usize,
392 393
    ) {
        let tcx = self.tcx();
394
        let &ty::Alias(_, projection_ty) = goal.predicate.self_ty().kind() else { return };
395

396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
        candidates.extend(self.probe(|_| CandidateKind::NormalizedSelfTyAssembly).enter(|ecx| {
            if num_steps < ecx.local_overflow_limit() {
                let normalized_ty = ecx.next_ty_infer();
                let normalizes_to_goal = goal.with(
                    tcx,
                    ty::ProjectionPredicate { projection_ty, term: normalized_ty.into() },
                );
                ecx.add_goal(normalizes_to_goal);
                if let Err(NoSolution) = ecx.try_evaluate_added_goals() {
                    debug!("self type normalization failed");
                    return vec![];
                }
                let normalized_ty = ecx.resolve_vars_if_possible(normalized_ty);
                debug!(?normalized_ty, "self type normalized");
                // 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));
                ecx.assemble_candidates_via_self_ty(goal, num_steps + 1)
            } else {
                match ecx.evaluate_added_goals_and_make_canonical_response(Certainty::OVERFLOW) {
                    Ok(result) => vec![Candidate {
                        source: CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
                        result,
                    }],
                    Err(NoSolution) => vec![],
                }
            }
        }));
L
lcnr 已提交
425 426
    }

427
    #[instrument(level = "debug", skip_all)]
428
    fn assemble_non_blanket_impl_candidates<G: GoalKind<'tcx>>(
429 430 431 432 433
        &mut self,
        goal: Goal<'tcx, G>,
        candidates: &mut Vec<Candidate<'tcx>>,
    ) {
        let tcx = self.tcx();
434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521
        let self_ty = goal.predicate.self_ty();
        let trait_impls = tcx.trait_impls_of(goal.predicate.trait_def_id(tcx));
        let mut consider_impls_for_simplified_type = |simp| {
            if let Some(impls_for_type) = trait_impls.non_blanket_impls().get(&simp) {
                for &impl_def_id in impls_for_type {
                    match G::consider_impl_candidate(self, goal, impl_def_id) {
                        Ok(result) => candidates
                            .push(Candidate { source: CandidateSource::Impl(impl_def_id), result }),
                        Err(NoSolution) => (),
                    }
                }
            }
        };

        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::Dynamic(_, _, _)
            | ty::Closure(_, _)
            | ty::Generator(_, _, _)
            | ty::Never
            | ty::Tuple(_) => {
                let simp =
                    fast_reject::simplify_type(tcx, self_ty, TreatParams::ForLookup).unwrap();
                consider_impls_for_simplified_type(simp);
            }

            // HACK: For integer and float variables we have to manually look at all impls
            // which have some integer or float as a self type.
            ty::Infer(ty::IntVar(_)) => {
                use ty::IntTy::*;
                use ty::UintTy::*;
                // This causes a compiler error if any new integer kinds are added.
                let (I8 | I16 | I32 | I64 | I128 | Isize): ty::IntTy;
                let (U8 | U16 | U32 | U64 | U128 | Usize): ty::UintTy;
                let possible_integers = [
                    // signed integers
                    SimplifiedType::Int(I8),
                    SimplifiedType::Int(I16),
                    SimplifiedType::Int(I32),
                    SimplifiedType::Int(I64),
                    SimplifiedType::Int(I128),
                    SimplifiedType::Int(Isize),
                    // unsigned integers
                    SimplifiedType::Uint(U8),
                    SimplifiedType::Uint(U16),
                    SimplifiedType::Uint(U32),
                    SimplifiedType::Uint(U64),
                    SimplifiedType::Uint(U128),
                    SimplifiedType::Uint(Usize),
                ];
                for simp in possible_integers {
                    consider_impls_for_simplified_type(simp);
                }
            }

            ty::Infer(ty::FloatVar(_)) => {
                // This causes a compiler error if any new float kinds are added.
                let (ty::FloatTy::F32 | ty::FloatTy::F64);
                let possible_floats = [
                    SimplifiedType::Float(ty::FloatTy::F32),
                    SimplifiedType::Float(ty::FloatTy::F64),
                ];

                for simp in possible_floats {
                    consider_impls_for_simplified_type(simp);
                }
            }

            // The only traits applying to aliases and placeholders are blanket impls.
            //
            // Impls which apply to an alias after normalization are handled by
            // `assemble_candidates_after_normalizing_self_ty`.
            ty::Alias(_, _) | ty::Placeholder(..) | ty::Error(_) => (),

            // FIXME: These should ideally not exist as a self type. It would be nice for
522
            // the builtin auto trait impls of generators to instead directly recurse
523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541
            // into the witness.
            ty::GeneratorWitness(_) | ty::GeneratorWitnessMIR(_, _) => (),

            // These variants should not exist as a self type.
            ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
            | ty::Param(_)
            | ty::Bound(_, _) => bug!("unexpected self type: {self_ty}"),
        }
    }

    fn assemble_blanket_impl_candidates<G: GoalKind<'tcx>>(
        &mut self,
        goal: Goal<'tcx, G>,
        candidates: &mut Vec<Candidate<'tcx>>,
    ) {
        let tcx = self.tcx();
        let trait_impls = tcx.trait_impls_of(goal.predicate.trait_def_id(tcx));
        for &impl_def_id in trait_impls.blanket_impls() {
            match G::consider_impl_candidate(self, goal, impl_def_id) {
542 543 544
                Ok(result) => candidates
                    .push(Candidate { source: CandidateSource::Impl(impl_def_id), result }),
                Err(NoSolution) => (),
545 546
            }
        }
L
lcnr 已提交
547
    }
548

549
    #[instrument(level = "debug", skip_all)]
550 551 552 553 554
    fn assemble_builtin_impl_candidates<G: GoalKind<'tcx>>(
        &mut self,
        goal: Goal<'tcx, G>,
        candidates: &mut Vec<Candidate<'tcx>>,
    ) {
555 556 557
        let tcx = self.tcx();
        let lang_items = tcx.lang_items();
        let trait_def_id = goal.predicate.trait_def_id(tcx);
558 559 560 561 562 563 564 565

        // 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.
566 567 568
        let result = if let Err(guar) = goal.predicate.error_reported() {
            G::consider_error_guaranteed_candidate(self, guar)
        } else if tcx.trait_is_auto(trait_def_id) {
M
Michael Goulet 已提交
569
            G::consider_auto_trait_candidate(self, goal)
570
        } else if tcx.trait_is_alias(trait_def_id) {
M
Michael Goulet 已提交
571 572
            G::consider_trait_alias_candidate(self, goal)
        } else if lang_items.sized_trait() == Some(trait_def_id) {
573
            G::consider_builtin_sized_candidate(self, goal)
M
Michael Goulet 已提交
574 575 576 577
        } 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)
578 579
        } else if lang_items.pointer_like() == Some(trait_def_id) {
            G::consider_builtin_pointer_like_candidate(self, goal)
L
lcnr 已提交
580 581
        } else if lang_items.fn_ptr_trait() == Some(trait_def_id) {
            G::consider_builtin_fn_ptr_trait_candidate(self, goal)
582 583 584 585
        } 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 已提交
586 587
        } else if lang_items.pointee_trait() == Some(trait_def_id) {
            G::consider_builtin_pointee_candidate(self, goal)
M
Michael Goulet 已提交
588 589 590 591
        } 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)
592 593
        } else if lang_items.discriminant_kind_trait() == Some(trait_def_id) {
            G::consider_builtin_discriminant_kind_candidate(self, goal)
594 595
        } else if lang_items.destruct_trait() == Some(trait_def_id) {
            G::consider_builtin_destruct_candidate(self, goal)
596 597
        } else if lang_items.transmute_trait() == Some(trait_def_id) {
            G::consider_builtin_transmute_candidate(self, goal)
598 599 600 601
        } else {
            Err(NoSolution)
        };

602
        match result {
603 604 605 606
            Ok(result) => candidates.push(Candidate {
                source: CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
                result,
            }),
607 608
            Err(NoSolution) => (),
        }
609 610 611 612

        // 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) {
613
            for (result, source) in G::consider_builtin_unsize_candidates(self, goal) {
614
                candidates.push(Candidate { source: CandidateSource::BuiltinImpl(source), result });
615 616
            }
        }
617 618
    }

619
    #[instrument(level = "debug", skip_all)]
620 621 622 623 624 625
    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() {
626 627 628
            match G::consider_implied_clause(self, goal, assumption, []) {
                Ok(result) => {
                    candidates.push(Candidate { source: CandidateSource::ParamEnv(i), result })
629
                }
630
                Err(NoSolution) => (),
631 632 633 634
            }
        }
    }

635
    #[instrument(level = "debug", skip_all)]
636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659
    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 已提交
660
            | ty::GeneratorWitnessMIR(..)
661 662 663 664
            | ty::Never
            | ty::Tuple(_)
            | ty::Param(_)
            | ty::Placeholder(..)
665
            | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
666
            | ty::Alias(ty::Inherent, _)
667
            | ty::Alias(ty::Weak, _)
668
            | ty::Error(_) => return,
669 670
            ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
            | ty::Bound(..) => bug!("unexpected self type for `{goal:?}`"),
671
            // Excluding IATs and type aliases here as they don't have meaningful item bounds.
672
            ty::Alias(ty::Projection | ty::Opaque, alias_ty) => alias_ty,
673 674
        };

675 676
        for assumption in
            self.tcx().item_bounds(alias_ty.def_id).instantiate(self.tcx(), alias_ty.args)
677
        {
678 679 680
            match G::consider_alias_bound_candidate(self, goal, assumption) {
                Ok(result) => {
                    candidates.push(Candidate { source: CandidateSource::AliasBound, result })
681
                }
682
                Err(NoSolution) => (),
683 684 685
            }
        }
    }
686

687 688 689 690 691 692 693 694 695 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 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777
    /// 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,
                        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 {
778 779 780 781
            Ok(result) => candidates.push(Candidate {
                source: CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
                result,
            }),
782 783 784 785
            Err(NoSolution) => (),
        }
    }

786
    #[instrument(level = "debug", skip_all)]
787 788 789 790 791
    fn assemble_object_bound_candidates<G: GoalKind<'tcx>>(
        &mut self,
        goal: Goal<'tcx, G>,
        candidates: &mut Vec<Candidate<'tcx>>,
    ) {
792 793 794 795 796
        let tcx = self.tcx();
        if !tcx.trait_def(goal.predicate.trait_def_id(tcx)).implement_via_object {
            return;
        }

797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816
        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 已提交
817
            | ty::GeneratorWitnessMIR(..)
818 819 820 821
            | ty::Never
            | ty::Tuple(_)
            | ty::Param(_)
            | ty::Placeholder(..)
822
            | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
823
            | ty::Error(_) => return,
824 825
            ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
            | ty::Bound(..) => bug!("unexpected self type for `{goal:?}`"),
826 827 828
            ty::Dynamic(bounds, ..) => bounds,
        };

829 830 831 832 833
        // Do not consider built-in object impls for non-object-safe types.
        if bounds.principal_def_id().is_some_and(|def_id| !tcx.check_is_object_safe(def_id)) {
            return;
        }

M
Michael Goulet 已提交
834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855
        // Consider all of the auto-trait and projection bounds, which don't
        // need to be recorded as a `BuiltinImplSource::Object` since they don't
        // really have a vtable base...
        for bound in bounds {
            match bound.skip_binder() {
                ty::ExistentialPredicate::Trait(_) => {
                    // Skip principal
                }
                ty::ExistentialPredicate::Projection(_)
                | ty::ExistentialPredicate::AutoTrait(_) => {
                    match G::consider_object_bound_candidate(
                        self,
                        goal,
                        bound.with_self_ty(tcx, self_ty),
                    ) {
                        Ok(result) => candidates.push(Candidate {
                            source: CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
                            result,
                        }),
                        Err(NoSolution) => (),
                    }
                }
856
            }
M
Michael Goulet 已提交
857
        }
858

M
Michael Goulet 已提交
859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874
        // FIXME: We only need to do *any* of this if we're considering a trait goal,
        // since we don't need to look at any supertrait or anything if we are doing
        // a projection goal.
        if let Some(principal) = bounds.principal() {
            let principal_trait_ref = principal.with_self_ty(tcx, self_ty);
            self.walk_vtable(principal_trait_ref, |ecx, assumption, vtable_base, _| {
                match G::consider_object_bound_candidate(ecx, goal, assumption.to_predicate(tcx)) {
                    Ok(result) => candidates.push(Candidate {
                        source: CandidateSource::BuiltinImpl(BuiltinImplSource::Object {
                            vtable_base,
                        }),
                        result,
                    }),
                    Err(NoSolution) => (),
                }
            });
875 876
        }
    }
M
Michael Goulet 已提交
877

878
    #[instrument(level = "debug", skip_all)]
L
lcnr 已提交
879 880 881 882 883
    fn assemble_coherence_unknowable_candidates<G: GoalKind<'tcx>>(
        &mut self,
        goal: Goal<'tcx, G>,
        candidates: &mut Vec<Candidate<'tcx>>,
    ) {
884
        let tcx = self.tcx();
L
lcnr 已提交
885 886
        match self.solver_mode() {
            SolverMode::Normal => return,
887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910
            SolverMode::Coherence => {}
        };

        let result = self.probe_candidate("coherence unknowable").enter(|ecx| {
            let trait_ref = goal.predicate.trait_ref(tcx);

            #[derive(Debug)]
            enum FailureKind {
                Overflow,
                NoSolution(NoSolution),
            }
            let lazily_normalize_ty = |ty| match ecx.try_normalize_ty(goal.param_env, ty) {
                Ok(Some(ty)) => Ok(ty),
                Ok(None) => Err(FailureKind::Overflow),
                Err(e) => Err(FailureKind::NoSolution(e)),
            };

            match coherence::trait_ref_is_knowable(tcx, trait_ref, lazily_normalize_ty) {
                Err(FailureKind::Overflow) => {
                    ecx.evaluate_added_goals_and_make_canonical_response(Certainty::OVERFLOW)
                }
                Err(FailureKind::NoSolution(NoSolution)) | Ok(Ok(())) => Err(NoSolution),
                Ok(Err(_)) => {
                    ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
L
lcnr 已提交
911 912
                }
            }
913 914 915 916 917 918 919 920
        });

        match result {
            Ok(result) => candidates.push(Candidate {
                source: CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
                result,
            }),
            Err(NoSolution) => {}
L
lcnr 已提交
921 922 923
        }
    }

L
lcnr 已提交
924 925 926
    /// 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 已提交
927
    #[instrument(level = "debug", skip(self), ret)]
L
lcnr 已提交
928
    pub(super) fn merge_candidates(
M
Michael Goulet 已提交
929 930 931
        &mut self,
        mut candidates: Vec<Candidate<'tcx>>,
    ) -> QueryResult<'tcx> {
L
lcnr 已提交
932 933 934 935
        // 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 已提交
936 937
        }

L
lcnr 已提交
938 939 940 941 942 943 944 945 946 947 948
        // 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()
949 950 951 952 953 954
                    .filter(|c| {
                        matches!(
                            c.source,
                            CandidateSource::ParamEnv(_) | CandidateSource::AliasBound
                        )
                    })
L
lcnr 已提交
955 956 957
                    .map(|c| c.result)
                    .collect::<Vec<_>>();
                if let Some(result) = self.try_merge_responses(&param_env_responses) {
958 959 960
                    // We strongly prefer alias and param-env bounds here, even if they affect inference.
                    // See https://github.com/rust-lang/trait-system-refactor-initiative/issues/11.
                    return Ok(result);
M
Michael Goulet 已提交
961 962 963
                }
            }
        }
L
lcnr 已提交
964
        self.flounder(&responses)
M
Michael Goulet 已提交
965
    }
L
lcnr 已提交
966
}