auto_trait.rs 41.7 KB
Newer Older
1 2
//! Support code for rustdoc and external tools.
//! You really don't want to be using this unless you need to.
3

4 5
use super::*;

M
Mark Mansi 已提交
6 7
use crate::infer::region_constraints::{Constraint, RegionConstraintData};
use crate::infer::InferCtxt;
8
use crate::traits::project::ProjectAndUnifyResult;
9
use rustc_middle::mir::interpret::ErrorHandled;
N
Nicholas Nethercote 已提交
10
use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
K
kadmin 已提交
11
use rustc_middle::ty::{Region, RegionVid, Term};
12

13 14 15 16
use rustc_data_structures::fx::{FxHashMap, FxHashSet};

use std::collections::hash_map::Entry;
use std::collections::VecDeque;
J
Josh Stone 已提交
17
use std::iter;
18

19
// FIXME(twk): this is obviously not nice to duplicate like that
20
#[derive(Eq, PartialEq, Hash, Copy, Clone, Debug)]
21
pub enum RegionTarget<'tcx> {
22
    Region(Region<'tcx>),
23
    RegionVid(RegionVid),
24 25 26
}

#[derive(Default, Debug, Clone)]
27
pub struct RegionDeps<'tcx> {
28
    larger: FxHashSet<RegionTarget<'tcx>>,
29
    smaller: FxHashSet<RegionTarget<'tcx>>,
30 31
}

32
pub enum AutoTraitResult<A> {
33
    ExplicitImpl,
34
    PositiveImpl(A),
35 36 37
    NegativeImpl,
}

38
#[allow(dead_code)]
39
impl<A> AutoTraitResult<A> {
40
    fn is_auto(&self) -> bool {
41
        matches!(self, AutoTraitResult::PositiveImpl(_) | AutoTraitResult::NegativeImpl)
42 43 44
    }
}

45 46 47 48 49 50
pub struct AutoTraitInfo<'cx> {
    pub full_user_env: ty::ParamEnv<'cx>,
    pub region_data: RegionConstraintData<'cx>,
    pub vid_to_region: FxHashMap<ty::RegionVid, ty::Region<'cx>>,
}

51
pub struct AutoTraitFinder<'tcx> {
52
    tcx: TyCtxt<'tcx>,
53 54
}

55
impl<'tcx> AutoTraitFinder<'tcx> {
56
    pub fn new(tcx: TyCtxt<'tcx>) -> Self {
57 58 59
        AutoTraitFinder { tcx }
    }

A
Alexander Regueiro 已提交
60
    /// Makes a best effort to determine whether and under which conditions an auto trait is
61 62 63 64 65
    /// implemented for a type. For example, if you have
    ///
    /// ```
    /// struct Foo<T> { data: Box<T> }
    /// ```
D
Diogo Sousa 已提交
66
    ///
67 68 69
    /// then this might return that Foo<T>: Send if T: Send (encoded in the AutoTraitResult type).
    /// The analysis attempts to account for custom impls as well as other complex cases. This
    /// result is intended for use by rustdoc and other such consumers.
D
Diogo Sousa 已提交
70
    ///
71 72 73 74
    /// (Note that due to the coinductive nature of Send, the full and correct result is actually
    /// quite simple to generate. That is, when a type has no custom impl, it is Send iff its field
    /// types are all Send. So, in our example, we might have that Foo<T>: Send if Box<T>: Send.
    /// But this is often not the best way to present to the user.)
D
Diogo Sousa 已提交
75
    ///
76 77
    /// Warning: The API should be considered highly unstable, and it may be refactored or removed
    /// in the future.
78 79
    pub fn find_auto_trait_generics<A>(
        &self,
80
        ty: Ty<'tcx>,
81
        orig_env: ty::ParamEnv<'tcx>,
82
        trait_did: DefId,
83
        mut auto_trait_callback: impl FnMut(AutoTraitInfo<'tcx>) -> A,
84
    ) -> AutoTraitResult<A> {
85 86
        let tcx = self.tcx;

M
Mark Rousskov 已提交
87
        let trait_ref = ty::TraitRef { def_id: trait_did, substs: tcx.mk_substs_trait(ty, &[]) };
88

J
Jack Huey 已提交
89
        let trait_pred = ty::Binder::dummy(trait_ref);
90

91
        let bail_out = tcx.infer_ctxt().enter(|infcx| {
92
            let mut selcx = SelectionContext::new(&infcx);
93 94
            let result = selcx.select(&Obligation::new(
                ObligationCause::dummy(),
95
                orig_env,
96 97
                trait_pred.to_poly_trait_predicate(),
            ));
98

99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
            match result {
                Ok(Some(ImplSource::UserDefined(_))) => {
                    debug!(
                        "find_auto_trait_generics({:?}): \
                         manual impl found, bailing out",
                        trait_ref
                    );
                    return true;
                }
                _ => {}
            }

            let result = selcx.select(&Obligation::new(
                ObligationCause::dummy(),
                orig_env,
                trait_pred.to_poly_trait_predicate_negative_polarity(),
            ));

117
            match result {
118
                Ok(Some(ImplSource::UserDefined(_))) => {
119
                    debug!(
120
                        "find_auto_trait_generics({:?}): \
121
                         manual impl found, bailing out",
122
                        trait_ref
123
                    );
124
                    true
125
                }
M
Mark Rousskov 已提交
126
                _ => false,
127
            }
128
        });
129 130 131 132 133 134

        // If an explicit impl exists, it always takes priority over an auto impl
        if bail_out {
            return AutoTraitResult::ExplicitImpl;
        }

135
        tcx.infer_ctxt().enter(|infcx| {
136
            let mut fresh_preds = FxHashSet::default();
137 138 139 140 141 142

            // Due to the way projections are handled by SelectionContext, we need to run
            // evaluate_predicates twice: once on the original param env, and once on the result of
            // the first evaluate_predicates call.
            //
            // The problem is this: most of rustc, including SelectionContext and traits::project,
143
            // are designed to work with a concrete usage of a type (e.g., Vec<u8>
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
            // fn<T>() { Vec<T> }. This information will generally never change - given
            // the 'T' in fn<T>() { ... }, we'll never know anything else about 'T'.
            // If we're unable to prove that 'T' implements a particular trait, we're done -
            // there's nothing left to do but error out.
            //
            // However, synthesizing an auto trait impl works differently. Here, we start out with
            // a set of initial conditions - the ParamEnv of the struct/enum/union we're dealing
            // with - and progressively discover the conditions we need to fulfill for it to
            // implement a certain auto trait. This ends up breaking two assumptions made by trait
            // selection and projection:
            //
            // * We can always cache the result of a particular trait selection for the lifetime of
            // an InfCtxt
            // * Given a projection bound such as '<T as SomeTrait>::SomeItem = K', if 'T:
            // SomeTrait' doesn't hold, then we don't need to care about the 'SomeItem = K'
            //
            // We fix the first assumption by manually clearing out all of the InferCtxt's caches
            // in between calls to SelectionContext.select. This allows us to keep all of the
            // intermediate types we create bound to the 'tcx lifetime, rather than needing to lift
            // them between calls.
            //
            // We fix the second assumption by reprocessing the result of our first call to
            // evaluate_predicates. Using the example of '<T as SomeTrait>::SomeItem = K', our first
            // pass will pick up 'T: SomeTrait', but not 'SomeItem = K'. On our second pass,
            // traits::project will see that 'T: SomeTrait' is in our ParamEnv, allowing
            // SelectionContext to return it back to us.

171
            let Some((new_env, user_env)) = self.evaluate_predicates(
172
                &infcx,
173 174
                trait_did,
                ty,
175 176
                orig_env,
                orig_env,
177 178
                &mut fresh_preds,
                false,
179 180
            ) else {
                return AutoTraitResult::NegativeImpl;
181 182
            };

M
Mark Rousskov 已提交
183 184
            let (full_env, full_user_env) = self
                .evaluate_predicates(
185
                    &infcx,
M
Mark Rousskov 已提交
186 187 188 189 190 191
                    trait_did,
                    ty,
                    new_env,
                    user_env,
                    &mut fresh_preds,
                    true,
192
                )
M
Mark Rousskov 已提交
193 194 195
                .unwrap_or_else(|| {
                    panic!("Failed to fully process: {:?} {:?} {:?}", ty, trait_did, orig_env)
                });
196 197

            debug!(
198
                "find_auto_trait_generics({:?}): fulfilling \
199
                 with {:?}",
200
                trait_ref, full_env
201
            );
202 203 204 205 206 207
            infcx.clear_caches();

            // At this point, we already have all of the bounds we need. FulfillmentContext is used
            // to store all of the necessary region/lifetime bounds in the InferContext, as well as
            // an additional sanity check.
            let mut fulfill = FulfillmentContext::new();
208
            fulfill.register_bound(&infcx, full_env, ty, trait_did, ObligationCause::dummy());
209
            let errors = fulfill.select_all_or_error(&infcx);
D
fmt  
Deadbeef 已提交
210

211 212 213
            if !errors.is_empty() {
                panic!("Unable to fulfill trait {:?} for '{:?}': {:?}", trait_did, ty, errors);
            }
214

L
lcnr 已提交
215
            infcx.process_registered_region_obligations(&Default::default(), full_env);
216

217 218 219 220 221 222
            let region_data = infcx
                .inner
                .borrow_mut()
                .unwrap_region_constraints()
                .region_constraint_data()
                .clone();
223 224 225

            let vid_to_region = self.map_vid_to_region(&region_data);

M
Mark Rousskov 已提交
226
            let info = AutoTraitInfo { full_user_env, region_data, vid_to_region };
227

228
            AutoTraitResult::PositiveImpl(auto_trait_callback(info))
229
        })
230
    }
231
}
232

233
impl<'tcx> AutoTraitFinder<'tcx> {
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
    /// The core logic responsible for computing the bounds for our synthesized impl.
    ///
    /// To calculate the bounds, we call `SelectionContext.select` in a loop. Like
    /// `FulfillmentContext`, we recursively select the nested obligations of predicates we
    /// encounter. However, whenever we encounter an `UnimplementedError` involving a type
    /// parameter, we add it to our `ParamEnv`. Since our goal is to determine when a particular
    /// type implements an auto trait, Unimplemented errors tell us what conditions need to be met.
    ///
    /// This method ends up working somewhat similarly to `FulfillmentContext`, but with a few key
    /// differences. `FulfillmentContext` works under the assumption that it's dealing with concrete
    /// user code. According, it considers all possible ways that a `Predicate` could be met, which
    /// isn't always what we want for a synthesized impl. For example, given the predicate `T:
    /// Iterator`, `FulfillmentContext` can end up reporting an Unimplemented error for `T:
    /// IntoIterator` -- since there's an implementation of `Iterator` where `T: IntoIterator`,
    /// `FulfillmentContext` will drive `SelectionContext` to consider that impl before giving up.
    /// If we were to rely on `FulfillmentContext`s decision, we might end up synthesizing an impl
    /// like this:
E
Elliot Roberts 已提交
251 252 253
    /// ```ignore (illustrative)
    /// impl<T> Send for Foo<T> where T: IntoIterator
    /// ```
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
    /// While it might be technically true that Foo implements Send where `T: IntoIterator`,
    /// the bound is overly restrictive - it's really only necessary that `T: Iterator`.
    ///
    /// For this reason, `evaluate_predicates` handles predicates with type variables specially.
    /// When we encounter an `Unimplemented` error for a bound such as `T: Iterator`, we immediately
    /// add it to our `ParamEnv`, and add it to our stack for recursive evaluation. When we later
    /// select it, we'll pick up any nested bounds, without ever inferring that `T: IntoIterator`
    /// needs to hold.
    ///
    /// One additional consideration is supertrait bounds. Normally, a `ParamEnv` is only ever
    /// constructed once for a given type. As part of the construction process, the `ParamEnv` will
    /// have any supertrait bounds normalized -- e.g., if we have a type `struct Foo<T: Copy>`, the
    /// `ParamEnv` will contain `T: Copy` and `T: Clone`, since `Copy: Clone`. When we construct our
    /// own `ParamEnv`, we need to do this ourselves, through `traits::elaborate_predicates`, or
    /// else `SelectionContext` will choke on the missing predicates. However, this should never
    /// show up in the final synthesized generics: we don't want our generated docs page to contain
    /// something like `T: Copy + Clone`, as that's redundant. Therefore, we keep track of a
    /// separate `user_env`, which only holds the predicates that will actually be displayed to the
    /// user.
273
    fn evaluate_predicates(
274
        &self,
275
        infcx: &InferCtxt<'_, 'tcx>,
276
        trait_did: DefId,
277 278 279 280
        ty: Ty<'tcx>,
        param_env: ty::ParamEnv<'tcx>,
        user_env: ty::ParamEnv<'tcx>,
        fresh_preds: &mut FxHashSet<ty::Predicate<'tcx>>,
281
        only_projections: bool,
282
    ) -> Option<(ty::ParamEnv<'tcx>, ty::ParamEnv<'tcx>)> {
283 284
        let tcx = infcx.tcx;

Y
Yuri Astrakhan 已提交
285
        // Don't try to process any nested obligations involving predicates
286 287 288 289 290 291
        // that are already in the `ParamEnv` (modulo regions): we already
        // know that they must hold.
        for predicate in param_env.caller_bounds() {
            fresh_preds.insert(self.clean_pred(infcx, predicate));
        }

292
        let mut select = SelectionContext::new(&infcx);
293

294
        let mut already_visited = FxHashSet::default();
295
        let mut predicates = VecDeque::new();
J
Jack Huey 已提交
296
        predicates.push_back(ty::Binder::dummy(ty::TraitPredicate {
297 298 299 300
            trait_ref: ty::TraitRef {
                def_id: trait_did,
                substs: infcx.tcx.mk_substs_trait(ty, &[]),
            },
D
Deadbeef 已提交
301
            constness: ty::BoundConstness::NotConst,
302 303
            // Auto traits are positive
            polarity: ty::ImplPolarity::Positive,
304
        }));
305

M
Mark Rousskov 已提交
306 307
        let computed_preds = param_env.caller_bounds().iter();
        let mut user_computed_preds: FxHashSet<_> = user_env.caller_bounds().iter().collect();
308

309
        let mut new_env = param_env;
310
        let dummy_cause = ObligationCause::dummy();
311 312 313 314

        while let Some(pred) = predicates.pop_front() {
            infcx.clear_caches();

315
            if !already_visited.insert(pred) {
316 317 318
                continue;
            }

319
            // Call `infcx.resolve_vars_if_possible` to see if we can
320
            // get rid of any inference variables.
B
Bastian Kauschke 已提交
321 322
            let obligation =
                infcx.resolve_vars_if_possible(Obligation::new(dummy_cause.clone(), new_env, pred));
323
            let result = select.select(&obligation);
324

325 326
            match result {
                Ok(Some(ref impl_source)) => {
327
                    // If we see an explicit negative impl (e.g., `impl !Send for MyStruct`),
V
varkor 已提交
328
                    // we immediately bail out, since it's impossible for us to continue.
329

330 331
                    if let ImplSource::UserDefined(ImplSourceUserDefinedData {
                        impl_def_id, ..
332
                    }) = impl_source
333
                    {
334 335 336 337
                        // Blame 'tidy' for the weird bracket placement.
                        if infcx.tcx.impl_polarity(*impl_def_id) == ty::ImplPolarity::Negative {
                            debug!(
                                "evaluate_nested_obligations: found explicit negative impl\
M
Mark Rousskov 已提交
338
                                        {:?}, bailing out",
339 340 341
                                impl_def_id
                            );
                            return None;
M
Mark Rousskov 已提交
342
                        }
343 344
                    }

345
                    let obligations = impl_source.clone().nested_obligations().into_iter();
346

347 348 349 350 351 352 353 354 355
                    if !self.evaluate_nested_obligations(
                        ty,
                        obligations,
                        &mut user_computed_preds,
                        fresh_preds,
                        &mut predicates,
                        &mut select,
                        only_projections,
                    ) {
356 357 358
                        return None;
                    }
                }
359 360
                Ok(None) => {}
                Err(SelectionError::Unimplemented) => {
361
                    if self.is_param_no_infer(pred.skip_binder().trait_ref.substs) {
362
                        already_visited.remove(&pred);
D
Deadbeef 已提交
363
                        self.add_user_pred(&mut user_computed_preds, pred.to_predicate(self.tcx));
364 365
                        predicates.push_back(pred);
                    } else {
366
                        debug!(
367
                            "evaluate_nested_obligations: `Unimplemented` found, bailing: \
368
                             {:?} {:?} {:?}",
369 370 371 372
                            ty,
                            pred,
                            pred.skip_binder().trait_ref.substs
                        );
373 374 375 376 377 378
                        return None;
                    }
                }
                _ => panic!("Unexpected error for '{:?}': {:?}", ty, result),
            };

379 380 381 382 383
            let normalized_preds = elaborate_predicates(
                tcx,
                computed_preds.clone().chain(user_computed_preds.iter().cloned()),
            )
            .map(|o| o.predicate);
384 385 386 387 388
            new_env = ty::ParamEnv::new(
                tcx.mk_predicates(normalized_preds),
                param_env.reveal(),
                param_env.constness(),
            );
389 390
        }

391 392
        let final_user_env = ty::ParamEnv::new(
            tcx.mk_predicates(user_computed_preds.into_iter()),
M
Mark Rousskov 已提交
393
            user_env.reveal(),
394
            user_env.constness(),
395 396
        );
        debug!(
397
            "evaluate_nested_obligations(ty={:?}, trait_did={:?}): succeeded with '{:?}' \
398
             '{:?}'",
399
            ty, trait_did, new_env, final_user_env
400
        );
401

402
        Some((new_env, final_user_env))
403 404
    }

405 406 407 408 409 410 411 412 413 414 415
    /// This method is designed to work around the following issue:
    /// When we compute auto trait bounds, we repeatedly call `SelectionContext.select`,
    /// progressively building a `ParamEnv` based on the results we get.
    /// However, our usage of `SelectionContext` differs from its normal use within the compiler,
    /// in that we capture and re-reprocess predicates from `Unimplemented` errors.
    ///
    /// This can lead to a corner case when dealing with region parameters.
    /// During our selection loop in `evaluate_predicates`, we might end up with
    /// two trait predicates that differ only in their region parameters:
    /// one containing a HRTB lifetime parameter, and one containing a 'normal'
    /// lifetime parameter. For example:
E
Elliot Roberts 已提交
416 417 418 419
    /// ```ignore (illustrative)
    /// T as MyTrait<'a>
    /// T as MyTrait<'static>
    /// ```
420 421 422 423 424 425 426 427
    /// If we put both of these predicates in our computed `ParamEnv`, we'll
    /// confuse `SelectionContext`, since it will (correctly) view both as being applicable.
    ///
    /// To solve this, we pick the 'more strict' lifetime bound -- i.e., the HRTB
    /// Our end goal is to generate a user-visible description of the conditions
    /// under which a type implements an auto trait. A trait predicate involving
    /// a HRTB means that the type needs to work with any choice of lifetime,
    /// not just one specific lifetime (e.g., `'static`).
428
    fn add_user_pred(
N
Niko Matsakis 已提交
429
        &self,
430 431
        user_computed_preds: &mut FxHashSet<ty::Predicate<'tcx>>,
        new_pred: ty::Predicate<'tcx>,
N
Niko Matsakis 已提交
432
    ) {
433 434
        let mut should_add_new = true;
        user_computed_preds.retain(|&old_pred| {
D
Deadbeef 已提交
435 436
            if let (ty::PredicateKind::Trait(new_trait), ty::PredicateKind::Trait(old_trait)) =
                (new_pred.kind().skip_binder(), old_pred.kind().skip_binder())
B
Bastian Kauschke 已提交
437
            {
438
                if new_trait.def_id() == old_trait.def_id() {
439 440
                    let new_substs = new_trait.trait_ref.substs;
                    let old_substs = old_trait.trait_ref.substs;
441 442 443 444 445 446

                    if !new_substs.types().eq(old_substs.types()) {
                        // We can't compare lifetimes if the types are different,
                        // so skip checking `old_pred`.
                        return true;
                    }
447

J
Josh Stone 已提交
448 449 450
                    for (new_region, old_region) in
                        iter::zip(new_substs.regions(), old_substs.regions())
                    {
451
                        match (*new_region, *old_region) {
452 453
                            // If both predicates have an `ReLateBound` (a HRTB) in the
                            // same spot, we do nothing.
454
                            (ty::ReLateBound(_, _), ty::ReLateBound(_, _)) => {}
455

456
                            (ty::ReLateBound(_, _), _) | (_, ty::ReVar(_)) => {
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
                                // One of these is true:
                                // The new predicate has a HRTB in a spot where the old
                                // predicate does not (if they both had a HRTB, the previous
                                // match arm would have executed). A HRBT is a 'stricter'
                                // bound than anything else, so we want to keep the newer
                                // predicate (with the HRBT) in place of the old predicate.
                                //
                                // OR
                                //
                                // The old predicate has a region variable where the new
                                // predicate has some other kind of region. An region
                                // variable isn't something we can actually display to a user,
                                // so we choose their new predicate (which doesn't have a region
                                // variable).
                                //
                                // In both cases, we want to remove the old predicate,
                                // from `user_computed_preds`, and replace it with the new
                                // one. Having both the old and the new
                                // predicate in a `ParamEnv` would confuse `SelectionContext`.
                                //
                                // We're currently in the predicate passed to 'retain',
                                // so we return `false` to remove the old predicate from
                                // `user_computed_preds`.
                                return false;
                            }
482
                            (_, ty::ReLateBound(_, _)) | (ty::ReVar(_), _) => {
483 484 485 486 487 488 489 490 491 492 493 494 495 496 497
                                // This is the opposite situation as the previous arm.
                                // One of these is true:
                                //
                                // The old predicate has a HRTB lifetime in a place where the
                                // new predicate does not.
                                //
                                // OR
                                //
                                // The new predicate has a region variable where the old
                                // predicate has some other type of region.
                                //
                                // We want to leave the old
                                // predicate in `user_computed_preds`, and skip adding
                                // new_pred to `user_computed_params`.
                                should_add_new = false
498
                            }
499
                            _ => {}
500 501
                        }
                    }
N
Niko Matsakis 已提交
502
                }
503
            }
504
            true
505 506 507 508 509 510 511
        });

        if should_add_new {
            user_computed_preds.insert(new_pred);
        }
    }

512 513
    /// This is very similar to `handle_lifetimes`. However, instead of matching `ty::Region`s
    /// to each other, we match `ty::RegionVid`s to `ty::Region`s.
514
    fn map_vid_to_region<'cx>(
515 516 517
        &self,
        regions: &RegionConstraintData<'cx>,
    ) -> FxHashMap<ty::RegionVid, ty::Region<'cx>> {
518 519
        let mut vid_map: FxHashMap<RegionTarget<'cx>, RegionDeps<'cx>> = FxHashMap::default();
        let mut finished_map = FxHashMap::default();
520 521 522 523 524

        for constraint in regions.constraints.keys() {
            match constraint {
                &Constraint::VarSubVar(r1, r2) => {
                    {
N
Niko Matsakis 已提交
525
                        let deps1 = vid_map.entry(RegionTarget::RegionVid(r1)).or_default();
526 527 528
                        deps1.larger.insert(RegionTarget::RegionVid(r2));
                    }

N
Niko Matsakis 已提交
529
                    let deps2 = vid_map.entry(RegionTarget::RegionVid(r2)).or_default();
530 531 532 533
                    deps2.smaller.insert(RegionTarget::RegionVid(r1));
                }
                &Constraint::RegSubVar(region, vid) => {
                    {
N
Niko Matsakis 已提交
534
                        let deps1 = vid_map.entry(RegionTarget::Region(region)).or_default();
535 536 537
                        deps1.larger.insert(RegionTarget::RegionVid(vid));
                    }

N
Niko Matsakis 已提交
538
                    let deps2 = vid_map.entry(RegionTarget::RegionVid(vid)).or_default();
539 540 541 542 543 544 545
                    deps2.smaller.insert(RegionTarget::Region(region));
                }
                &Constraint::VarSubReg(vid, region) => {
                    finished_map.insert(vid, region);
                }
                &Constraint::RegSubReg(r1, r2) => {
                    {
N
Niko Matsakis 已提交
546
                        let deps1 = vid_map.entry(RegionTarget::Region(r1)).or_default();
547 548 549
                        deps1.larger.insert(RegionTarget::Region(r2));
                    }

N
Niko Matsakis 已提交
550
                    let deps2 = vid_map.entry(RegionTarget::Region(r2)).or_default();
551 552 553 554 555 556
                    deps2.smaller.insert(RegionTarget::Region(r1));
                }
            }
        }

        while !vid_map.is_empty() {
557
            let target = *vid_map.keys().next().expect("Keys somehow empty");
558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579
            let deps = vid_map.remove(&target).expect("Entry somehow missing");

            for smaller in deps.smaller.iter() {
                for larger in deps.larger.iter() {
                    match (smaller, larger) {
                        (&RegionTarget::Region(_), &RegionTarget::Region(_)) => {
                            if let Entry::Occupied(v) = vid_map.entry(*smaller) {
                                let smaller_deps = v.into_mut();
                                smaller_deps.larger.insert(*larger);
                                smaller_deps.larger.remove(&target);
                            }

                            if let Entry::Occupied(v) = vid_map.entry(*larger) {
                                let larger_deps = v.into_mut();
                                larger_deps.smaller.insert(*smaller);
                                larger_deps.smaller.remove(&target);
                            }
                        }
                        (&RegionTarget::RegionVid(v1), &RegionTarget::Region(r1)) => {
                            finished_map.insert(v1, r1);
                        }
                        (&RegionTarget::Region(_), &RegionTarget::RegionVid(_)) => {
580
                            // Do nothing; we don't care about regions that are smaller than vids.
581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601
                        }
                        (&RegionTarget::RegionVid(_), &RegionTarget::RegionVid(_)) => {
                            if let Entry::Occupied(v) = vid_map.entry(*smaller) {
                                let smaller_deps = v.into_mut();
                                smaller_deps.larger.insert(*larger);
                                smaller_deps.larger.remove(&target);
                            }

                            if let Entry::Occupied(v) = vid_map.entry(*larger) {
                                let larger_deps = v.into_mut();
                                larger_deps.smaller.insert(*smaller);
                                larger_deps.smaller.remove(&target);
                            }
                        }
                    }
                }
            }
        }
        finished_map
    }

C
csmoe 已提交
602
    fn is_param_no_infer(&self, substs: SubstsRef<'_>) -> bool {
603
        self.is_of_param(substs.type_at(0)) && !substs.types().any(|t| t.has_infer_types())
604 605
    }

606
    pub fn is_of_param(&self, ty: Ty<'_>) -> bool {
L
LeSeulArtichaut 已提交
607
        match ty.kind() {
V
varkor 已提交
608
            ty::Param(_) => true,
609
            ty::Projection(p) => self.is_of_param(p.self_ty()),
610
            _ => false,
611
        }
612 613
    }

614
    fn is_self_referential_projection(&self, p: ty::PolyProjectionPredicate<'_>) -> bool {
K
kadmin 已提交
615 616 617 618 619
        if let Term::Ty(ty) = p.term().skip_binder() {
            matches!(ty.kind(), ty::Projection(proj) if proj == &p.skip_binder().projection_ty)
        } else {
            false
        }
620 621
    }

622
    fn evaluate_nested_obligations(
623
        &self,
F
flip1995 已提交
624
        ty: Ty<'_>,
625 626 627 628 629
        nested: impl Iterator<Item = Obligation<'tcx, ty::Predicate<'tcx>>>,
        computed_preds: &mut FxHashSet<ty::Predicate<'tcx>>,
        fresh_preds: &mut FxHashSet<ty::Predicate<'tcx>>,
        predicates: &mut VecDeque<ty::PolyTraitPredicate<'tcx>>,
        select: &mut SelectionContext<'_, 'tcx>,
630 631
        only_projections: bool,
    ) -> bool {
632
        let dummy_cause = ObligationCause::dummy();
633

634 635 636
        for obligation in nested {
            let is_new_pred =
                fresh_preds.insert(self.clean_pred(select.infcx(), obligation.predicate));
637

638
            // Resolve any inference variables that we can, to help selection succeed
B
Bastian Kauschke 已提交
639
            let predicate = select.infcx().resolve_vars_if_possible(obligation.predicate);
640 641 642 643 644 645 646 647 648 649 650 651 652

            // We only add a predicate as a user-displayable bound if
            // it involves a generic parameter, and doesn't contain
            // any inference variables.
            //
            // Displaying a bound involving a concrete type (instead of a generic
            // parameter) would be pointless, since it's always true
            // (e.g. u8: Copy)
            // Displaying an inference variable is impossible, since they're
            // an internal compiler detail without a defined visual representation
            //
            // We check this by calling is_of_param on the relevant types
            // from the various possible predicates
653

J
Jack Huey 已提交
654
            let bound_predicate = predicate.kind();
655
            match bound_predicate.skip_binder() {
D
Deadbeef 已提交
656
                ty::PredicateKind::Trait(p) => {
657 658 659 660
                    // Add this to `predicates` so that we end up calling `select`
                    // with it. If this predicate ends up being unimplemented,
                    // then `evaluate_predicates` will handle adding it the `ParamEnv`
                    // if possible.
J
Jack Huey 已提交
661
                    predicates.push_back(bound_predicate.rebind(p));
662
                }
J
Jack Huey 已提交
663
                ty::PredicateKind::Projection(p) => {
J
Jack Huey 已提交
664
                    let p = bound_predicate.rebind(p);
M
Mark Rousskov 已提交
665 666 667 668
                    debug!(
                        "evaluate_nested_obligations: examining projection predicate {:?}",
                        predicate
                    );
669 670 671 672 673 674

                    // As described above, we only want to display
                    // bounds which include a generic parameter but don't include
                    // an inference variable.
                    // Additionally, we check if we've seen this predicate before,
                    // to avoid rendering duplicate bounds to the user.
675
                    if self.is_param_no_infer(p.skip_binder().projection_ty.substs)
K
kadmin 已提交
676
                        && !p.term().skip_binder().has_infer_types()
M
Mark Rousskov 已提交
677 678 679
                        && is_new_pred
                    {
                        debug!(
Y
Yuri Astrakhan 已提交
680
                            "evaluate_nested_obligations: adding projection predicate \
M
Mark Rousskov 已提交
681 682 683 684
                            to computed_preds: {:?}",
                            predicate
                        );

Y
Yuri Astrakhan 已提交
685
                        // Under unusual circumstances, we can end up with a self-referential
M
Mark Rousskov 已提交
686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702
                        // projection predicate. For example:
                        // <T as MyType>::Value == <T as MyType>::Value
                        // Not only is displaying this to the user pointless,
                        // having it in the ParamEnv will cause an issue if we try to call
                        // poly_project_and_unify_type on the predicate, since this kind of
                        // predicate will normally never end up in a ParamEnv.
                        //
                        // For these reasons, we ignore these weird predicates,
                        // ensuring that we're able to properly synthesize an auto trait impl
                        if self.is_self_referential_projection(p) {
                            debug!(
                                "evaluate_nested_obligations: encountered a projection
                                 predicate equating a type with itself! Skipping"
                            );
                        } else {
                            self.add_user_pred(computed_preds, predicate);
                        }
703 704
                    }

705 706 707 708 709 710 711
                    // There are three possible cases when we project a predicate:
                    //
                    // 1. We encounter an error. This means that it's impossible for
                    // our current type to implement the auto trait - there's bound
                    // that we could add to our ParamEnv that would 'fix' this kind
                    // of error, as it's not caused by an unimplemented type.
                    //
B
Brian Wignall 已提交
712
                    // 2. We successfully project the predicate (Ok(Some(_))), generating
713 714 715
                    //  some subobligations. We then process these subobligations
                    //  like any other generated sub-obligations.
                    //
M
Matthias Krüger 已提交
716
                    // 3. We receive an 'ambiguous' result (Ok(None))
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
                    // If we were actually trying to compile a crate,
                    // we would need to re-process this obligation later.
                    // However, all we care about is finding out what bounds
                    // are needed for our type to implement a particular auto trait.
                    // We've already added this obligation to our computed ParamEnv
                    // above (if it was necessary). Therefore, we don't need
                    // to do any further processing of the obligation.
                    //
                    // Note that we *must* try to project *all* projection predicates
                    // we encounter, even ones without inference variable.
                    // This ensures that we detect any projection errors,
                    // which indicate that our type can *never* implement the given
                    // auto trait. In that case, we will generate an explicit negative
                    // impl (e.g. 'impl !Send for MyType'). However, we don't
                    // try to process any of the generated subobligations -
                    // they contain no new information, since we already know
                    // that our type implements the projected-through trait,
                    // and can lead to weird region issues.
                    //
                    // Normally, we'll generate a negative impl as a result of encountering
                    // a type with an explicit negative impl of an auto trait
                    // (for example, raw pointers have !Send and !Sync impls)
                    // However, through some **interesting** manipulations of the type
                    // system, it's actually possible to write a type that never
                    // implements an auto trait due to a projection error, not a normal
                    // negative impl error. To properly handle this case, we need
                    // to ensure that we catch any potential projection errors,
                    // and turn them into an explicit negative impl for our type.
M
Mark Rousskov 已提交
745
                    debug!("Projecting and unifying projection predicate {:?}", predicate);
746

747
                    match project::poly_project_and_unify_type(select, &obligation.with(p)) {
748
                        ProjectAndUnifyResult::MismatchedProjectionTypes(e) => {
749 750 751 752 753 754 755
                            debug!(
                                "evaluate_nested_obligations: Unable to unify predicate \
                                 '{:?}' '{:?}', bailing out",
                                ty, e
                            );
                            return false;
                        }
756
                        ProjectAndUnifyResult::Recursive => {
757 758 759
                            debug!("evaluate_nested_obligations: recursive projection predicate");
                            return false;
                        }
760
                        ProjectAndUnifyResult::Holds(v) => {
761 762 763
                            // We only care about sub-obligations
                            // when we started out trying to unify
                            // some inference variables. See the comment above
Y
Yuri Astrakhan 已提交
764
                            // for more information
K
kadmin 已提交
765
                            if p.term().skip_binder().has_infer_types() {
766 767
                                if !self.evaluate_nested_obligations(
                                    ty,
768
                                    v.into_iter(),
769 770 771 772 773 774
                                    computed_preds,
                                    fresh_preds,
                                    predicates,
                                    select,
                                    only_projections,
                                ) {
775 776 777
                                    return false;
                                }
                            }
778
                        }
779
                        ProjectAndUnifyResult::FailedNormalization => {
780
                            // It's ok not to make progress when have no inference variables -
Y
Yuri Astrakhan 已提交
781
                            // in that case, we were only performing unification to check if an
B
Brian Wignall 已提交
782
                            // error occurred (which would indicate that it's impossible for our
783 784 785 786
                            // type to implement the auto trait).
                            // However, we should always make progress (either by generating
                            // subobligations or getting an error) when we started off with
                            // inference variables
K
kadmin 已提交
787
                            if p.term().skip_binder().has_infer_types() {
788 789 790 791 792
                                panic!("Unexpected result when selecting {:?} {:?}", ty, obligation)
                            }
                        }
                    }
                }
J
Jack Huey 已提交
793
                ty::PredicateKind::RegionOutlives(binder) => {
J
Jack Huey 已提交
794
                    let binder = bound_predicate.rebind(binder);
M
Mark Rousskov 已提交
795
                    if select.infcx().region_outlives_predicate(&dummy_cause, binder).is_err() {
796 797
                        return false;
                    }
798
                }
J
Jack Huey 已提交
799
                ty::PredicateKind::TypeOutlives(binder) => {
J
Jack Huey 已提交
800
                    let binder = bound_predicate.rebind(binder);
801
                    match (
802 803
                        binder.no_bound_vars(),
                        binder.map_bound_ref(|pred| pred.0).no_bound_vars(),
804
                    ) {
805
                        (None, Some(t_a)) => {
806 807
                            select.infcx().register_region_obligation_with_cause(
                                t_a,
V
varkor 已提交
808
                                select.infcx().tcx.lifetimes.re_static,
809
                                &dummy_cause,
810
                            );
811 812
                        }
                        (Some(ty::OutlivesPredicate(t_a, r_b)), _) => {
813 814 815 816
                            select.infcx().register_region_obligation_with_cause(
                                t_a,
                                r_b,
                                &dummy_cause,
817
                            );
818 819 820 821
                        }
                        _ => {}
                    };
                }
J
Jack Huey 已提交
822
                ty::PredicateKind::ConstEquate(c1, c2) => {
N
Nicholas Nethercote 已提交
823
                    let evaluate = |c: ty::Const<'tcx>| {
824
                        if let ty::ConstKind::Unevaluated(unevaluated) = c.kind() {
B
Bastian Kauschke 已提交
825 826
                            match select.infcx().const_eval_resolve(
                                obligation.param_env,
L
lcnr 已提交
827
                                unevaluated,
B
Bastian Kauschke 已提交
828 829
                                Some(obligation.cause.span),
                            ) {
830 831 832 833 834 835 836 837 838 839
                                Ok(Some(valtree)) => {
                                    Ok(ty::Const::from_value(select.tcx(), valtree, c.ty()))
                                }
                                Ok(None) => {
                                    let tcx = self.tcx;
                                    let def_id = unevaluated.def.did;
                                    let reported = tcx.sess.struct_span_err(tcx.def_span(def_id), &format!("unable to construct a constant value for the unevaluated constant {:?}", unevaluated)).emit();

                                    Err(ErrorHandled::Reported(reported))
                                }
B
Bastian Kauschke 已提交
840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860
                                Err(err) => Err(err),
                            }
                        } else {
                            Ok(c)
                        }
                    };

                    match (evaluate(c1), evaluate(c2)) {
                        (Ok(c1), Ok(c2)) => {
                            match select
                                .infcx()
                                .at(&obligation.cause, obligation.param_env)
                                .eq(c1, c2)
                            {
                                Ok(_) => (),
                                Err(_) => return false,
                            }
                        }
                        _ => return false,
                    }
                }
861 862 863 864 865 866 867 868 869 870 871
                // There's not really much we can do with these predicates -
                // we start out with a `ParamEnv` with no inference variables,
                // and these don't correspond to adding any new bounds to
                // the `ParamEnv`.
                ty::PredicateKind::WellFormed(..)
                | ty::PredicateKind::ObjectSafe(..)
                | ty::PredicateKind::ClosureKind(..)
                | ty::PredicateKind::Subtype(..)
                | ty::PredicateKind::ConstEvaluatable(..)
                | ty::PredicateKind::Coerce(..)
                | ty::PredicateKind::TypeWellFormedFromEnv(..) => {}
872 873
            };
        }
874
        true
875 876
    }

877
    pub fn clean_pred(
878
        &self,
879 880 881
        infcx: &InferCtxt<'_, 'tcx>,
        p: ty::Predicate<'tcx>,
    ) -> ty::Predicate<'tcx> {
882 883 884 885 886
        infcx.freshen(p)
    }
}

// Replaces all ReVars in a type with ty::Region's, using the provided map
887
pub struct RegionReplacer<'a, 'tcx> {
888
    vid_to_region: &'a FxHashMap<ty::RegionVid, ty::Region<'tcx>>,
889
    tcx: TyCtxt<'tcx>,
890 891
}

892 893
impl<'a, 'tcx> TypeFolder<'tcx> for RegionReplacer<'a, 'tcx> {
    fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
894 895 896
        self.tcx
    }

897
    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
898 899
        (match *r {
            ty::ReVar(vid) => self.vid_to_region.get(&vid).cloned(),
900
            _ => None,
M
Mark Rousskov 已提交
901
        })
902
        .unwrap_or_else(|| r.super_fold_with(self))
903 904
    }
}