mod.rs 94.9 KB
Newer Older
1
use std::collections::VecDeque;
2 3
use std::rc::Rc;

4
use rustc_data_structures::binary_search_util;
5
use rustc_data_structures::frozen::Frozen;
6
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
7
use rustc_data_structures::graph::scc::Sccs;
8
use rustc_hir::def_id::DefId;
M
Mark Rousskov 已提交
9
use rustc_index::vec::IndexVec;
C
Camille GILLOT 已提交
10 11
use rustc_infer::infer::canonical::QueryOutlivesConstraint;
use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound};
12
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin};
M
Mazdak Farrokhzad 已提交
13 14
use rustc_middle::mir::{
    Body, ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegionRequirements,
15
    ConstraintCategory, Local, Location, ReturnConstraint,
M
Mazdak Farrokhzad 已提交
16 17
};
use rustc_middle::ty::{self, subst::SubstsRef, RegionVid, Ty, TyCtxt, TypeFoldable};
18
use rustc_span::Span;
19

20
use crate::{
M
Mark Mansi 已提交
21
    constraints::{
M
Mark Rousskov 已提交
22
        graph::NormalConstraintGraph, ConstraintSccIndex, OutlivesConstraint, OutlivesConstraintSet,
M
Mark Mansi 已提交
23
    },
24
    diagnostics::{RegionErrorKind, RegionErrors, UniverseInfo},
M
Mark Mansi 已提交
25
    member_constraints::{MemberConstraintSet, NllMemberConstraintIndex},
M
Mark Rousskov 已提交
26
    nll::{PoloniusOutput, ToRegionVid},
27
    region_infer::reverse_sccs::ReverseSccGraph,
M
Mark Mansi 已提交
28
    region_infer::values::{
M
Mark Rousskov 已提交
29 30
        LivenessValues, PlaceholderIndices, RegionElement, RegionValueElements, RegionValues,
        ToElementIndex,
M
Mark Mansi 已提交
31 32 33
    },
    type_check::{free_region_relations::UniversalRegionRelations, Locations},
    universal_regions::UniversalRegions,
M
Mark Mansi 已提交
34 35
};

36 37
mod dump_mir;
mod graphviz;
38
mod opaque_types;
39
mod reverse_sccs;
40

41
pub mod values;
42

43
pub struct RegionInferenceContext<'tcx> {
A
Alexander Regueiro 已提交
44
    /// Contains the definition for every region variable. Region
45
    /// variables are identified by their index (`RegionVid`). The
46 47
    /// definition contains information about where the region came
    /// from as well as its final inferred value.
48
    definitions: IndexVec<RegionVid, RegionDefinition<'tcx>>,
49

50 51
    /// The liveness constraints added to each region. For most
    /// regions, these start out empty and steadily grow, though for
52 53
    /// each universally quantified region R they start out containing
    /// the entire CFG and `end(R)`.
54
    liveness_constraints: LivenessValues<RegionVid>,
55

56
    /// The outlives constraints computed by the type-check.
57
    constraints: Frozen<OutlivesConstraintSet<'tcx>>,
58

59 60 61
    /// The constraint-set, but in graph form, making it easy to traverse
    /// the constraints adjacent to a particular region. Used to construct
    /// the SCC (see `constraint_sccs`) and for error reporting.
62
    constraint_graph: Frozen<NormalConstraintGraph>,
63

64 65
    /// The SCC computed from `constraints` and the constraint
    /// graph. We have an edge from SCC A to SCC B if `A: B`. Used to
66
    /// compute the values of each region.
67
    constraint_sccs: Rc<Sccs<RegionVid, ConstraintSccIndex>>,
68

69 70 71 72
    /// Reverse of the SCC constraint graph --  i.e., an edge `A -> B` exists if
    /// `B: A`. This is used to compute the universal regions that are required
    /// to outlive a given SCC. Computed lazily.
    rev_scc_graph: Option<Rc<ReverseSccGraph>>,
73

N
Niko Matsakis 已提交
74
    /// The "R0 member of [R1..Rn]" constraints, indexed by SCC.
75
    member_constraints: Rc<MemberConstraintSet<'tcx, ConstraintSccIndex>>,
76

N
Niko Matsakis 已提交
77
    /// Records the member constraints that we applied to each scc.
78 79
    /// This is useful for error reporting. Once constraint
    /// propagation is done, this vector is sorted according to
N
Niko Matsakis 已提交
80
    /// `member_region_scc`.
81
    member_constraints_applied: Vec<AppliedMemberConstraint>,
82

83
    /// Map closure bounds to a `Span` that should be used for error reporting.
84
    closure_bounds_mapping:
N
Niko Matsakis 已提交
85
        FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>>,
86

87
    /// Map universe indexes to information on why we created it.
88
    universe_causes: IndexVec<ty::UniverseIndex, UniverseInfo<'tcx>>,
89

N
Niko Matsakis 已提交
90 91 92
    /// Contains the minimum universe of any variable within the same
    /// SCC. We will ensure that no SCC contains values that are not
    /// visible from this index.
93
    scc_universes: IndexVec<ConstraintSccIndex, ty::UniverseIndex>,
N
Niko Matsakis 已提交
94

95 96 97 98 99 100 101
    /// Contains a "representative" from each SCC. This will be the
    /// minimal RegionVid belonging to that universe. It is used as a
    /// kind of hacky way to manage checking outlives relationships,
    /// since we can 'canonicalize' each region to the representative
    /// of its SCC and be sure that -- if they have the same repr --
    /// they *must* be equal (though not having the same repr does not
    /// mean they are unequal).
102
    scc_representatives: IndexVec<ConstraintSccIndex, ty::RegionVid>,
103

104 105 106
    /// The final inferred values of the region variables; we compute
    /// one value per SCC. To get the value for any given *region*,
    /// you first find which scc it is a part of.
107
    scc_values: RegionValues<ConstraintSccIndex>,
108

109
    /// Type constraints that we check after solving.
110
    type_tests: Vec<TypeTest<'tcx>>,
111

112
    /// Information about the universally quantified regions in scope
113
    /// on this function.
114
    universal_regions: Rc<UniversalRegions<'tcx>>,
115 116 117

    /// Information about how the universally quantified regions in
    /// scope on this function relate to one another.
118
    universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
119 120
}

N
Niko Matsakis 已提交
121 122
/// Each time that `apply_member_constraint` is successful, it appends
/// one of these structs to the `member_constraints_applied` field.
123 124
/// This is used in error reporting to trace out what happened.
///
N
Niko Matsakis 已提交
125
/// The way that `apply_member_constraint` works is that it effectively
126 127 128 129
/// adds a new lower bound to the SCC it is analyzing: so you wind up
/// with `'R: 'O` where `'R` is the pick-region and `'O` is the
/// minimal viable option.
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
M
Mark Mansi 已提交
130
pub(crate) struct AppliedMemberConstraint {
N
Niko Matsakis 已提交
131
    /// The SCC that was affected. (The "member region".)
132
    ///
N
Niko Matsakis 已提交
133
    /// The vector if `AppliedMemberConstraint` elements is kept sorted
134
    /// by this field.
135
    pub(crate) member_region_scc: ConstraintSccIndex,
136

N
Niko Matsakis 已提交
137 138
    /// The "best option" that `apply_member_constraint` found -- this was
    /// added as an "ad-hoc" lower-bound to `member_region_scc`.
139
    pub(crate) min_choice: ty::RegionVid,
140

N
Niko Matsakis 已提交
141
    /// The "member constraint index" -- we can find out details about
142
    /// the constraint from
N
Niko Matsakis 已提交
143
    /// `set.member_constraints[member_constraint_index]`.
144
    pub(crate) member_constraint_index: NllMemberConstraintIndex,
145 146
}

M
Mark Mansi 已提交
147
pub(crate) struct RegionDefinition<'tcx> {
148
    /// What kind of variable is this -- a free region? existential
149
    /// variable? etc. (See the `NllRegionVariableOrigin` for more
150
    /// info.)
151
    pub(crate) origin: NllRegionVariableOrigin,
152

N
Niko Matsakis 已提交
153 154 155
    /// Which universe is this region variable defined in? This is
    /// most often `ty::UniverseIndex::ROOT`, but when we encounter
    /// forall-quantifiers like `for<'a> { 'a = 'b }`, we would create
156
    /// the variable for `'a` in a fresh universe that extends ROOT.
157
    pub(crate) universe: ty::UniverseIndex,
N
Niko Matsakis 已提交
158

159 160
    /// If this is 'static or an early-bound region, then this is
    /// `Some(X)` where `X` is the name of the region.
161
    pub(crate) external_name: Option<ty::Region<'tcx>>,
162 163
}

164
/// N.B., the variants in `Cause` are intentionally ordered. Lower
P
Paul Daniel Faria 已提交
165 166
/// values are preferred when it comes to error messages. Do not
/// reorder willy nilly.
167
#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
P
Paul Daniel Faria 已提交
168 169 170 171 172 173
pub(crate) enum Cause {
    /// point inserted because Local was live at the given Location
    LiveVar(Local, Location),

    /// point inserted because Local was dropped at the given Location
    DropVar(Local, Location),
S
Santiago Pastorino 已提交
174 175
}

176
/// A "type test" corresponds to an outlives constraint between a type
A
Alexander Regueiro 已提交
177
/// and a lifetime, like `T: 'x` or `<T as Foo>::Bar: 'x`. They are
178 179 180 181 182 183 184 185 186 187 188 189
/// translated from the `Verify` region constraints in the ordinary
/// inference context.
///
/// These sorts of constraints are handled differently than ordinary
/// constraints, at least at present. During type checking, the
/// `InferCtxt::process_registered_region_obligations` method will
/// attempt to convert a type test like `T: 'x` into an ordinary
/// outlives constraint when possible (for example, `&'a T: 'b` will
/// be converted into `'a: 'b` and registered as a `Constraint`).
///
/// In some cases, however, there are outlives relationships that are
/// not converted into a region constraint, but rather into one of
A
Alexander Regueiro 已提交
190
/// these "type tests". The distinction is that a type test does not
191 192
/// influence the inference result, but instead just examines the
/// values that we ultimately inferred for each region variable and
A
Alexander Regueiro 已提交
193
/// checks that they meet certain extra criteria. If not, an error
194 195
/// can be issued.
///
196 197 198 199 200 201
/// One reason for this is that these type tests typically boil down
/// to a check like `'a: 'x` where `'a` is a universally quantified
/// region -- and therefore not one whose value is really meant to be
/// *inferred*, precisely (this is not always the case: one can have a
/// type test like `<Foo as Trait<'?0>>::Bar: 'x`, where `'?0` is an
/// inference variable). Another reason is that these type tests can
202 203 204 205 206
/// involve *disjunction* -- that is, they can be satisfied in more
/// than one way.
///
/// For more information about this translation, see
/// `InferCtxt::process_registered_region_obligations` and
207
/// `InferCtxt::type_must_outlive` in `rustc_infer::infer::InferCtxt`.
208 209 210 211 212 213 214 215
#[derive(Clone, Debug)]
pub struct TypeTest<'tcx> {
    /// The type `T` that must outlive the region.
    pub generic_kind: GenericKind<'tcx>,

    /// The region `'x` that the type must outlive.
    pub lower_bound: RegionVid,

216 217
    /// Where did this constraint arise and why?
    pub locations: Locations,
218 219 220

    /// A test which, if met by the region `'x`, proves that this type
    /// constraint is satisfied.
221
    pub verify_bound: VerifyBound<'tcx>,
222 223
}

224 225 226 227 228 229 230 231 232
/// When we have an unmet lifetime constraint, we try to propagate it outward (e.g. to a closure
/// environment). If we can't, it is an error.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum RegionRelationCheckResult {
    Ok,
    Propagated,
    Error,
}

233 234
#[derive(Clone, PartialEq, Eq, Debug)]
enum Trace<'tcx> {
235
    StartRegion,
236
    FromOutlivesConstraint(OutlivesConstraint<'tcx>),
237 238 239
    NotVisited,
}

240
impl<'tcx> RegionInferenceContext<'tcx> {
241 242 243
    /// Creates a new region inference context with a total of
    /// `num_region_variables` valid inference variables; the first N
    /// of those will be constant regions representing the free
244
    /// regions defined in `universal_regions`.
245 246 247
    ///
    /// The `outlives_constraints` and `type_tests` are an initial set
    /// of constraints produced by the MIR type check.
248
    pub(crate) fn new(
249
        var_infos: VarInfos,
250
        universal_regions: Rc<UniversalRegions<'tcx>>,
251
        placeholder_indices: Rc<PlaceholderIndices>,
252
        universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
253
        outlives_constraints: OutlivesConstraintSet<'tcx>,
N
Niko Matsakis 已提交
254
        member_constraints_in: MemberConstraintSet<'tcx, RegionVid>,
255 256 257 258
        closure_bounds_mapping: FxHashMap<
            Location,
            FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>,
        >,
259
        universe_causes: IndexVec<ty::UniverseIndex, UniverseInfo<'tcx>>,
260
        type_tests: Vec<TypeTest<'tcx>>,
261
        liveness_constraints: LivenessValues<RegionVid>,
262
        elements: &Rc<RegionValueElements>,
263
    ) -> Self {
264
        // Create a RegionDefinition for each inference variable.
265
        let definitions: IndexVec<_, _> = var_infos
266
            .into_iter()
N
Niko Matsakis 已提交
267
            .map(|info| RegionDefinition::new(info.universe, info.origin))
268 269
            .collect();

270 271
        let constraints = Frozen::freeze(outlives_constraints);
        let constraint_graph = Frozen::freeze(constraints.graph(definitions.len()));
W
Wesley Wiser 已提交
272 273
        let fr_static = universal_regions.fr_static;
        let constraint_sccs = Rc::new(constraints.compute_sccs(&constraint_graph, fr_static));
274

275
        let mut scc_values =
276
            RegionValues::new(elements, universal_regions.len(), &placeholder_indices);
277

278
        for region in liveness_constraints.rows() {
279
            let scc = constraint_sccs.scc(region);
280
            scc_values.merge_liveness(scc, region, &liveness_constraints);
281
        }
282

N
Niko Matsakis 已提交
283 284
        let scc_universes = Self::compute_scc_universes(&constraint_sccs, &definitions);

285 286
        let scc_representatives = Self::compute_scc_representatives(&constraint_sccs, &definitions);

N
Niko Matsakis 已提交
287 288
        let member_constraints =
            Rc::new(member_constraints_in.into_mapped(|r| constraint_sccs.scc(r)));
289

290
        let mut result = Self {
291
            definitions,
292
            liveness_constraints,
293
            constraints,
294
            constraint_graph,
295
            constraint_sccs,
296
            rev_scc_graph: None,
N
Niko Matsakis 已提交
297 298
            member_constraints,
            member_constraints_applied: Vec::new(),
299
            closure_bounds_mapping,
300
            universe_causes,
N
Niko Matsakis 已提交
301
            scc_universes,
302
            scc_representatives,
303
            scc_values,
304
            type_tests,
305
            universal_regions,
306
            universal_region_relations,
307 308
        };

N
Niko Matsakis 已提交
309
        result.init_free_and_bound_regions();
310 311 312 313

        result
    }

N
Niko Matsakis 已提交
314 315 316 317 318 319 320 321
    /// Each SCC is the combination of many region variables which
    /// have been equated. Therefore, we can associate a universe with
    /// each SCC which is minimum of all the universes of its
    /// constituent regions -- this is because whatever value the SCC
    /// takes on must be a value that each of the regions within the
    /// SCC could have as well. This implies that the SCC must have
    /// the minimum, or narrowest, universe.
    fn compute_scc_universes(
N
Niko Matsakis 已提交
322
        constraint_sccs: &Sccs<RegionVid, ConstraintSccIndex>,
N
Niko Matsakis 已提交
323 324
        definitions: &IndexVec<RegionVid, RegionDefinition<'tcx>>,
    ) -> IndexVec<ConstraintSccIndex, ty::UniverseIndex> {
N
Niko Matsakis 已提交
325
        let num_sccs = constraint_sccs.num_sccs();
N
Niko Matsakis 已提交
326 327
        let mut scc_universes = IndexVec::from_elem_n(ty::UniverseIndex::MAX, num_sccs);

328 329 330 331 332
        debug!("compute_scc_universes()");

        // For each region R in universe U, ensure that the universe for the SCC
        // that contains R is "no bigger" than U. This effectively sets the universe
        // for each SCC to be the minimum of the regions within.
N
Niko Matsakis 已提交
333
        for (region_vid, region_definition) in definitions.iter_enumerated() {
N
Niko Matsakis 已提交
334
            let scc = constraint_sccs.scc(region_vid);
N
Niko Matsakis 已提交
335
            let scc_universe = &mut scc_universes[scc];
336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378
            let scc_min = std::cmp::min(region_definition.universe, *scc_universe);
            if scc_min != *scc_universe {
                *scc_universe = scc_min;
                debug!(
                    "compute_scc_universes: lowered universe of {scc:?} to {scc_min:?} \
                    because it contains {region_vid:?} in {region_universe:?}",
                    scc = scc,
                    scc_min = scc_min,
                    region_vid = region_vid,
                    region_universe = region_definition.universe,
                );
            }
        }

        // Walk each SCC `A` and `B` such that `A: B`
        // and ensure that universe(A) can see universe(B).
        //
        // This serves to enforce the 'empty/placeholder' hierarchy
        // (described in more detail on `RegionKind`):
        //
        // ```
        // static -----+
        //   |         |
        // empty(U0) placeholder(U1)
        //   |      /
        // empty(U1)
        // ```
        //
        // In particular, imagine we have variables R0 in U0 and R1
        // created in U1, and constraints like this;
        //
        // ```
        // R1: !1 // R1 outlives the placeholder in U1
        // R1: R0 // R1 outlives R0
        // ```
        //
        // Here, we wish for R1 to be `'static`, because it
        // cannot outlive `placeholder(U1)` and `empty(U0)` any other way.
        //
        // Thanks to this loop, what happens is that the `R1: R0`
        // constraint lowers the universe of `R1` to `U0`, which in turn
        // means that the `R1: !1` constraint will (later) cause
        // `R1` to become `'static`.
379
        for scc_a in constraint_sccs.all_sccs() {
N
Niko Matsakis 已提交
380
            for &scc_b in constraint_sccs.successors(scc_a) {
381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396
                let scc_universe_a = scc_universes[scc_a];
                let scc_universe_b = scc_universes[scc_b];
                let scc_universe_min = std::cmp::min(scc_universe_a, scc_universe_b);
                if scc_universe_a != scc_universe_min {
                    scc_universes[scc_a] = scc_universe_min;

                    debug!(
                        "compute_scc_universes: lowered universe of {scc_a:?} to {scc_universe_min:?} \
                        because {scc_a:?}: {scc_b:?} and {scc_b:?} is in universe {scc_universe_b:?}",
                        scc_a = scc_a,
                        scc_b = scc_b,
                        scc_universe_min = scc_universe_min,
                        scc_universe_b = scc_universe_b
                    );
                }
            }
N
Niko Matsakis 已提交
397 398 399 400 401 402 403
        }

        debug!("compute_scc_universes: scc_universe = {:#?}", scc_universes);

        scc_universes
    }

404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
    /// For each SCC, we compute a unique `RegionVid` (in fact, the
    /// minimal one that belongs to the SCC). See
    /// `scc_representatives` field of `RegionInferenceContext` for
    /// more details.
    fn compute_scc_representatives(
        constraints_scc: &Sccs<RegionVid, ConstraintSccIndex>,
        definitions: &IndexVec<RegionVid, RegionDefinition<'tcx>>,
    ) -> IndexVec<ConstraintSccIndex, ty::RegionVid> {
        let num_sccs = constraints_scc.num_sccs();
        let next_region_vid = definitions.next_index();
        let mut scc_representatives = IndexVec::from_elem_n(next_region_vid, num_sccs);

        for region_vid in definitions.indices() {
            let scc = constraints_scc.scc(region_vid);
            let prev_min = scc_representatives[scc];
            scc_representatives[scc] = region_vid.min(prev_min);
        }

        scc_representatives
    }

425 426 427
    /// Initializes the region variables for each universally
    /// quantified region (lifetime parameter). The first N variables
    /// always correspond to the regions appearing in the function
A
Alexander Regueiro 已提交
428
    /// signature (both named and anonymous) and where-clauses. This
429 430
    /// function iterates over those regions and initializes them with
    /// minimum values.
431 432 433 434 435 436 437 438 439 440 441
    ///
    /// For example:
    ///
    ///     fn foo<'a, 'b>(..) where 'a: 'b
    ///
    /// would initialize two variables like so:
    ///
    ///     R0 = { CFG, R0 } // 'a
    ///     R1 = { CFG, R0, R1 } // 'b
    ///
    /// Here, R0 represents `'a`, and it contains (a) the entire CFG
442 443 444
    /// and (b) any universally quantified regions that it outlives,
    /// which in this case is just itself. R1 (`'b`) in contrast also
    /// outlives `'a` and hence contains R0 and R1.
N
Niko Matsakis 已提交
445
    fn init_free_and_bound_regions(&mut self) {
446 447
        // Update the names (if any)
        for (external_name, variable) in self.universal_regions.named_universal_regions() {
448 449
            debug!(
                "init_universal_regions: region {:?} has external name {:?}",
450
                variable, external_name
451
            );
452 453
            self.definitions[variable].external_name = Some(external_name);
        }
454

N
Niko Matsakis 已提交
455
        for variable in self.definitions.indices() {
456 457
            let scc = self.constraint_sccs.scc(variable);

N
Niko Matsakis 已提交
458
            match self.definitions[variable].origin {
459
                NllRegionVariableOrigin::FreeRegion => {
N
Niko Matsakis 已提交
460 461 462 463
                    // For each free, universally quantified region X:

                    // Add all nodes in the CFG to liveness constraints
                    self.liveness_constraints.add_all_points(variable);
464
                    self.scc_values.add_all_points(scc);
465

N
Niko Matsakis 已提交
466
                    // Add `end(X)` into the set for X.
467
                    self.scc_values.add_element(scc, variable);
N
Niko Matsakis 已提交
468 469
                }

470
                NllRegionVariableOrigin::Placeholder(placeholder) => {
471
                    // Each placeholder region is only visible from
472
                    // its universe `ui` and its extensions. So we
473 474
                    // can't just add it into `scc` unless the
                    // universe of the scc can name this region.
475
                    let scc_universe = self.scc_universes[scc];
476
                    if scc_universe.can_name(placeholder.universe) {
477
                        self.scc_values.add_element(scc, placeholder);
478
                    } else {
N
Niko Matsakis 已提交
479 480 481
                        debug!(
                            "init_free_and_bound_regions: placeholder {:?} is \
                             not compatible with universe {:?} of its SCC {:?}",
482
                            placeholder, scc_universe, scc,
N
Niko Matsakis 已提交
483
                        );
484 485
                        self.add_incompatible_universe(scc);
                    }
N
Niko Matsakis 已提交
486
                }
487

488 489
                NllRegionVariableOrigin::RootEmptyRegion
                | NllRegionVariableOrigin::Existential { .. } => {
N
Niko Matsakis 已提交
490 491 492
                    // For existential, regions, nothing to do.
                }
            }
493 494 495
        }
    }

496
    /// Returns an iterator over all the region indices.
497
    pub fn regions(&self) -> impl Iterator<Item = RegionVid> {
498 499 500
        self.definitions.indices()
    }

501 502 503 504 505 506 507 508
    /// Given a universal region in scope on the MIR, returns the
    /// corresponding index.
    ///
    /// (Panics if `r` is not a registered universal region.)
    pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
        self.universal_regions.to_region_vid(r)
    }

A
Alexander Regueiro 已提交
509
    /// Adds annotations for `#[rustc_regions]`; see `UniversalRegions::annotate`.
510
    crate fn annotate(&self, tcx: TyCtxt<'tcx>, err: &mut rustc_errors::DiagnosticBuilder<'_>) {
511 512 513
        self.universal_regions.annotate(tcx, err)
    }

A
Alexander Regueiro 已提交
514
    /// Returns `true` if the region `r` contains the point `p`.
515
    ///
516
    /// Panics if called before `solve()` executes,
517 518 519
    crate fn region_contains(&self, r: impl ToRegionVid, p: impl ToElementIndex) -> bool {
        let scc = self.constraint_sccs.scc(r.to_region_vid());
        self.scc_values.contains(scc, p)
520 521
    }

522
    /// Returns access to the value of `r` for debugging purposes.
N
Niko Matsakis 已提交
523
    crate fn region_value_str(&self, r: RegionVid) -> String {
524 525
        let scc = self.constraint_sccs.scc(r.to_region_vid());
        self.scc_values.region_value_str(scc)
526 527
    }

N
Niko Matsakis 已提交
528 529 530 531 532 533
    /// Returns access to the value of `r` for debugging purposes.
    crate fn region_universe(&self, r: RegionVid) -> ty::UniverseIndex {
        let scc = self.constraint_sccs.scc(r.to_region_vid());
        self.scc_universes[scc]
    }

534
    /// Once region solving has completed, this function will return
N
Niko Matsakis 已提交
535
    /// the member constraints that were applied to the value of a given
N
Niko Matsakis 已提交
536
    /// region `r`. See `AppliedMemberConstraint`.
537
    pub(crate) fn applied_member_constraints(
M
Mark Rousskov 已提交
538 539
        &self,
        r: impl ToRegionVid,
M
Mark Mansi 已提交
540
    ) -> &[AppliedMemberConstraint] {
541 542
        let scc = self.constraint_sccs.scc(r.to_region_vid());
        binary_search_util::binary_search_slice(
N
Niko Matsakis 已提交
543 544
            &self.member_constraints_applied,
            |applied| applied.member_region_scc,
545 546 547 548
            &scc,
        )
    }

A
Alexander Regueiro 已提交
549
    /// Performs region inference and report errors if we see any
550 551
    /// unsatisfiable constraints. If this is a closure, returns the
    /// region requirements to propagate to our creator, if any.
552
    pub(super) fn solve(
553
        &mut self,
554
        infcx: &InferCtxt<'_, 'tcx>,
555
        body: &Body<'tcx>,
556
        polonius_output: Option<Rc<PoloniusOutput>>,
557
    ) -> (Option<ClosureRegionRequirements<'tcx>>, RegionErrors<'tcx>) {
D
Dylan MacKenzie 已提交
558
        let mir_def_id = body.source.def_id();
559
        self.propagate_constraints(body);
560

561 562
        let mut errors_buffer = RegionErrors::new();

563 564 565 566 567
        // If this is a closure, we can propagate unsatisfied
        // `outlives_requirements` to our creator, so create a vector
        // to store those. Otherwise, we'll pass in `None` to the
        // functions below, which will trigger them to report errors
        // eagerly.
M
Matthias Krüger 已提交
568
        let mut outlives_requirements = infcx.tcx.is_closure(mir_def_id).then(Vec::new);
569

570
        self.check_type_tests(infcx, body, outlives_requirements.as_mut(), &mut errors_buffer);
571

572 573 574 575 576 577 578
        // In Polonius mode, the errors about missing universal region relations are in the output
        // and need to be emitted or propagated. Otherwise, we need to check whether the
        // constraints were too strong, and if so, emit or propagate those errors.
        if infcx.tcx.sess.opts.debugging_opts.polonius {
            self.check_polonius_subset_errors(
                body,
                outlives_requirements.as_mut(),
579
                &mut errors_buffer,
580 581 582
                polonius_output.expect("Polonius output is unavailable despite `-Z polonius`"),
            );
        } else {
583
            self.check_universal_regions(body, outlives_requirements.as_mut(), &mut errors_buffer);
584
        }
585

586 587 588
        if errors_buffer.is_empty() {
            self.check_member_constraints(infcx, &mut errors_buffer);
        }
589

590
        let outlives_requirements = outlives_requirements.unwrap_or_default();
591 592

        if outlives_requirements.is_empty() {
593
            (None, errors_buffer)
594 595
        } else {
            let num_external_vids = self.universal_regions.num_global_and_external_regions();
596 597 598 599
            (
                Some(ClosureRegionRequirements { num_external_vids, outlives_requirements }),
                errors_buffer,
            )
600 601
        }
    }
602

603 604 605 606
    /// Propagate the region constraints: this will grow the values
    /// for each region variable until all the constraints are
    /// satisfied. Note that some values may grow **too** large to be
    /// feasible, but we check this later.
607
    fn propagate_constraints(&mut self, _body: &Body<'tcx>) {
608
        debug!("propagate_constraints()");
S
Santiago Pastorino 已提交
609

610
        debug!("propagate_constraints: constraints={:#?}", {
611
            let mut constraints: Vec<_> = self.constraints.outlives().iter().collect();
612 613
            constraints.sort();
            constraints
N
Niko Matsakis 已提交
614 615 616
                .into_iter()
                .map(|c| (c, self.constraint_sccs.scc(c.sup), self.constraint_sccs.scc(c.sub)))
                .collect::<Vec<_>>()
617 618
        });

619
        // To propagate constraints, we walk the DAG induced by the
620 621 622
        // SCC. For each SCC, we visit its successors and compute
        // their values, then we union all those values to get our
        // own.
623 624
        let constraint_sccs = self.constraint_sccs.clone();
        for scc in constraint_sccs.all_sccs() {
625
            self.compute_value_for_scc(scc);
626
        }
627

N
Niko Matsakis 已提交
628
        // Sort the applied member constraints so we can binary search
629
        // through them later.
N
Niko Matsakis 已提交
630
        self.member_constraints_applied.sort_by_key(|applied| applied.member_region_scc);
631
    }
632

633
    /// Computes the value of the SCC `scc_a`, which has not yet been
N
Niko Matsakis 已提交
634 635 636
    /// computed, by unioning the values of its successors.
    /// Assumes that all successors have been computed already
    /// (which is assured by iterating over SCCs in dependency order).
637
    fn compute_value_for_scc(&mut self, scc_a: ConstraintSccIndex) {
638
        let constraint_sccs = self.constraint_sccs.clone();
639

640 641
        // Walk each SCC `B` such that `A: B`...
        for &scc_b in constraint_sccs.successors(scc_a) {
642
            debug!("propagate_constraint_sccs: scc_a = {:?} scc_b = {:?}", scc_a, scc_b);
643

N
Niko Matsakis 已提交
644 645 646 647 648 649 650 651 652
            // ...and add elements from `B` into `A`. One complication
            // arises because of universes: If `B` contains something
            // that `A` cannot name, then `A` can only contain `B` if
            // it outlives static.
            if self.universe_compatible(scc_b, scc_a) {
                // `A` can name everything that is in `B`, so just
                // merge the bits.
                self.scc_values.add_region(scc_a, scc_b);
            } else {
653
                self.add_incompatible_universe(scc_a);
N
Niko Matsakis 已提交
654
            }
655 656
        }

N
Niko Matsakis 已提交
657
        // Now take member constraints into account.
N
Niko Matsakis 已提交
658 659
        let member_constraints = self.member_constraints.clone();
        for m_c_i in member_constraints.indices(scc_a) {
660
            self.apply_member_constraint(scc_a, m_c_i, member_constraints.choice_regions(m_c_i));
661 662
        }

663 664 665 666 667
        debug!(
            "propagate_constraint_sccs: scc_a = {:?} has value {:?}",
            scc_a,
            self.scc_values.region_value_str(scc_a),
        );
668 669
    }

N
Niko Matsakis 已提交
670
    /// Invoked for each `R0 member of [R1..Rn]` constraint.
671
    ///
N
Niko Matsakis 已提交
672
    /// `scc` is the SCC containing R0, and `choice_regions` are the
673 674 675 676 677 678 679 680
    /// `R1..Rn` regions -- they are always known to be universal
    /// regions (and if that's not true, we just don't attempt to
    /// enforce the constraint).
    ///
    /// The current value of `scc` at the time the method is invoked
    /// is considered a *lower bound*.  If possible, we will modify
    /// the constraint to set it equal to one of the option regions.
    /// If we make any changes, returns true, else false.
N
Niko Matsakis 已提交
681
    fn apply_member_constraint(
682 683
        &mut self,
        scc: ConstraintSccIndex,
N
Niko Matsakis 已提交
684 685
        member_constraint_index: NllMemberConstraintIndex,
        choice_regions: &[ty::RegionVid],
686
    ) -> bool {
N
Niko Matsakis 已提交
687
        debug!("apply_member_constraint(scc={:?}, choice_regions={:#?})", scc, choice_regions,);
688 689 690

        // Create a mutable vector of the options. We'll try to winnow
        // them down.
N
Niko Matsakis 已提交
691
        let mut choice_regions: Vec<ty::RegionVid> = choice_regions.to_vec();
692

N
Niko Matsakis 已提交
693
        // The 'member region' in a member constraint is part of the
694 695 696 697 698
        // hidden type, which must be in the root universe. Therefore,
        // it cannot have any placeholders in its value.
        assert!(self.scc_universes[scc] == ty::UniverseIndex::ROOT);
        debug_assert!(
            self.scc_values.placeholders_contained_in(scc).next().is_none(),
N
Niko Matsakis 已提交
699
            "scc {:?} in a member constraint has placeholder value: {:?}",
700 701 702 703 704
            scc,
            self.scc_values.region_value_str(scc),
        );

        // The existing value for `scc` is a lower-bound. This will
N
Niko Matsakis 已提交
705 706 707 708
        // consist of some set `{P} + {LB}` of points `{P}` and
        // lower-bound free regions `{LB}`. As each choice region `O`
        // is a free region, it will outlive the points. But we can
        // only consider the option `O` if `O: LB`.
N
Niko Matsakis 已提交
709
        choice_regions.retain(|&o_r| {
710 711 712 713
            self.scc_values
                .universal_regions_outlived_by(scc)
                .all(|lb| self.universal_region_relations.outlives(o_r, lb))
        });
N
Niko Matsakis 已提交
714
        debug!("apply_member_constraint: after lb, choice_regions={:?}", choice_regions);
715

N
Niko Matsakis 已提交
716
        // Now find all the *upper bounds* -- that is, each UB is a
N
Niko Matsakis 已提交
717 718
        // free region that must outlive the member region `R0` (`UB:
        // R0`). Therefore, we need only keep an option `O` if `UB: O`
N
Niko Matsakis 已提交
719
        // for all UB.
720 721 722 723 724
        let rev_scc_graph = self.reverse_scc_graph();
        let universal_region_relations = &self.universal_region_relations;
        for ub in rev_scc_graph.upper_bounds(scc) {
            debug!("apply_member_constraint: ub={:?}", ub);
            choice_regions.retain(|&o_r| universal_region_relations.outlives(ub, o_r));
725
        }
726
        debug!("apply_member_constraint: after ub, choice_regions={:?}", choice_regions);
727 728

        // If we ruled everything out, we're done.
N
Niko Matsakis 已提交
729
        if choice_regions.is_empty() {
730 731 732
            return false;
        }

N
Niko Matsakis 已提交
733 734 735
        // Otherwise, we need to find the minimum remaining choice, if
        // any, and take that.
        debug!("apply_member_constraint: choice_regions remaining are {:#?}", choice_regions);
736 737 738
        let min = |r1: ty::RegionVid, r2: ty::RegionVid| -> Option<ty::RegionVid> {
            let r1_outlives_r2 = self.universal_region_relations.outlives(r1, r2);
            let r2_outlives_r1 = self.universal_region_relations.outlives(r2, r1);
V
varkor 已提交
739 740 741 742 743
            match (r1_outlives_r2, r2_outlives_r1) {
                (true, true) => Some(r1.min(r2)),
                (true, false) => Some(r2),
                (false, true) => Some(r1),
                (false, false) => None,
744 745
            }
        };
N
Niko Matsakis 已提交
746 747
        let mut min_choice = choice_regions[0];
        for &other_option in &choice_regions[1..] {
748
            debug!(
N
Niko Matsakis 已提交
749 750
                "apply_member_constraint: min_choice={:?} other_option={:?}",
                min_choice, other_option,
751
            );
N
Niko Matsakis 已提交
752 753
            match min(min_choice, other_option) {
                Some(m) => min_choice = m,
754 755
                None => {
                    debug!(
N
Niko Matsakis 已提交
756 757
                        "apply_member_constraint: {:?} and {:?} are incomparable; no min choice",
                        min_choice, other_option,
758 759 760 761 762 763
                    );
                    return false;
                }
            }
        }

N
Niko Matsakis 已提交
764
        let min_choice_scc = self.constraint_sccs.scc(min_choice);
765
        debug!(
N
Niko Matsakis 已提交
766
            "apply_member_constraint: min_choice={:?} best_choice_scc={:?}",
M
Mark Rousskov 已提交
767
            min_choice, min_choice_scc,
768
        );
N
Niko Matsakis 已提交
769 770 771 772 773
        if self.scc_values.add_region(scc, min_choice_scc) {
            self.member_constraints_applied.push(AppliedMemberConstraint {
                member_region_scc: scc,
                min_choice,
                member_constraint_index,
774 775 776 777 778 779
            });

            true
        } else {
            false
        }
780 781
    }

A
Alexander Regueiro 已提交
782
    /// Returns `true` if all the elements in the value of `scc_b` are nameable
N
Niko Matsakis 已提交
783 784 785 786 787 788 789 790
    /// in `scc_a`. Used during constraint propagation, and only once
    /// the value of `scc_b` has been computed.
    fn universe_compatible(&self, scc_b: ConstraintSccIndex, scc_a: ConstraintSccIndex) -> bool {
        let universe_a = self.scc_universes[scc_a];

        // Quick check: if scc_b's declared universe is a subset of
        // scc_a's declared univese (typically, both are ROOT), then
        // it cannot contain any problematic universe elements.
791
        if universe_a.can_name(self.scc_universes[scc_b]) {
N
Niko Matsakis 已提交
792 793 794 795 796 797
            return true;
        }

        // Otherwise, we have to iterate over the universe elements in
        // B's value, and check whether all of them are nameable
        // from universe_a
798
        self.scc_values.placeholders_contained_in(scc_b).all(|p| universe_a.can_name(p.universe))
N
Niko Matsakis 已提交
799 800
    }

801 802 803 804 805 806 807 808
    /// Extend `scc` so that it can outlive some placeholder region
    /// from a universe it can't name; at present, the only way for
    /// this to be true is if `scc` outlives `'static`. This is
    /// actually stricter than necessary: ideally, we'd support bounds
    /// like `for<'a: 'b`>` that might then allow us to approximate
    /// `'a` with `'b` and not `'static`. But it will have to do for
    /// now.
    fn add_incompatible_universe(&mut self, scc: ConstraintSccIndex) {
N
Niko Matsakis 已提交
809 810
        debug!("add_incompatible_universe(scc={:?})", scc);

811 812 813 814 815
        let fr_static = self.universal_regions.fr_static;
        self.scc_values.add_all_points(scc);
        self.scc_values.add_element(scc, fr_static);
    }

816
    /// Once regions have been propagated, this method is used to see
N
Niko Matsakis 已提交
817 818 819
    /// whether the "type tests" produced by typeck were satisfied;
    /// type tests encode type-outlives relationships like `T:
    /// 'a`. See `TypeTest` for more details.
820
    fn check_type_tests(
821
        &self,
822
        infcx: &InferCtxt<'_, 'tcx>,
823
        body: &Body<'tcx>,
824
        mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>,
825
        errors_buffer: &mut RegionErrors<'tcx>,
826
    ) {
827 828
        let tcx = infcx.tcx;

829 830 831 832 833
        // Sometimes we register equivalent type-tests that would
        // result in basically the exact same error being reported to
        // the user. Avoid that.
        let mut deduplicate_errors = FxHashSet::default();

834 835 836
        for type_test in &self.type_tests {
            debug!("check_type_test: {:?}", type_test);

837 838 839
            let generic_ty = type_test.generic_kind.to_ty(tcx);
            if self.eval_verify_bound(
                tcx,
840
                body,
841 842 843 844
                generic_ty,
                type_test.lower_bound,
                &type_test.verify_bound,
            ) {
845
                continue;
846
            }
847

848
            if let Some(propagated_outlives_requirements) = &mut propagated_outlives_requirements {
S
Santiago Pastorino 已提交
849 850
                if self.try_promote_type_test(
                    infcx,
851
                    body,
S
Santiago Pastorino 已提交
852 853 854
                    type_test,
                    propagated_outlives_requirements,
                ) {
855 856 857 858
                    continue;
                }
            }

859
            // Type-test failed. Report the error.
B
Bastian Kauschke 已提交
860
            let erased_generic_kind = infcx.tcx.erase_regions(type_test.generic_kind);
M
Mark Mansi 已提交
861 862

            // Skip duplicate-ish errors.
863
            if deduplicate_errors.insert((
N
Niko Matsakis 已提交
864
                erased_generic_kind,
865
                type_test.lower_bound,
N
Niko Matsakis 已提交
866 867
                type_test.locations,
            )) {
868 869 870 871
                debug!(
                    "check_type_test: reporting error for erased_generic_kind={:?}, \
                     lower_bound_region={:?}, \
                     type_test.locations={:?}",
872
                    erased_generic_kind, type_test.lower_bound, type_test.locations,
873 874
                );

875
                errors_buffer.push(RegionErrorKind::TypeTestError { type_test: type_test.clone() });
876 877 878 879
            }
        }
    }

N
Niko Matsakis 已提交
880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903
    /// Invoked when we have some type-test (e.g., `T: 'X`) that we cannot
    /// prove to be satisfied. If this is a closure, we will attempt to
    /// "promote" this type-test into our `ClosureRegionRequirements` and
    /// hence pass it up the creator. To do this, we have to phrase the
    /// type-test in terms of external free regions, as local free
    /// regions are not nameable by the closure's creator.
    ///
    /// Promotion works as follows: we first check that the type `T`
    /// contains only regions that the creator knows about. If this is
    /// true, then -- as a consequence -- we know that all regions in
    /// the type `T` are free regions that outlive the closure body. If
    /// false, then promotion fails.
    ///
    /// Once we've promoted T, we have to "promote" `'X` to some region
    /// that is "external" to the closure. Generally speaking, a region
    /// may be the union of some points in the closure body as well as
    /// various free lifetimes. We can ignore the points in the closure
    /// body: if the type T can be expressed in terms of external regions,
    /// we know it outlives the points in the closure body. That
    /// just leaves the free regions.
    ///
    /// The idea then is to lower the `T: 'X` constraint into multiple
    /// bounds -- e.g., if `'X` is the union of two free lifetimes,
    /// `'1` and `'2`, then we would create `T: '1` and `T: '2`.
904
    fn try_promote_type_test(
905
        &self,
906
        infcx: &InferCtxt<'_, 'tcx>,
907
        body: &Body<'tcx>,
908
        type_test: &TypeTest<'tcx>,
909
        propagated_outlives_requirements: &mut Vec<ClosureOutlivesRequirement<'tcx>>,
910 911 912
    ) -> bool {
        let tcx = infcx.tcx;

913
        let TypeTest { generic_kind, lower_bound, locations, verify_bound: _ } = type_test;
914 915

        let generic_ty = generic_kind.to_ty(tcx);
N
Niko Matsakis 已提交
916 917 918 919
        let subject = match self.try_promote_type_test_subject(infcx, generic_ty) {
            Some(s) => s,
            None => return false,
        };
920

M
Mikhail Modin 已提交
921 922 923 924 925
        // For each region outlived by lower_bound find a non-local,
        // universal region (it may be the same region) and add it to
        // `ClosureOutlivesRequirement`.
        let r_scc = self.constraint_sccs.scc(*lower_bound);
        for ur in self.scc_values.universal_regions_outlived_by(r_scc) {
926 927 928 929 930 931 932 933 934 935 936 937 938
            // Check whether we can already prove that the "subject" outlives `ur`.
            // If so, we don't have to propagate this requirement to our caller.
            //
            // To continue the example from the function, if we are trying to promote
            // a requirement that `T: 'X`, and we know that `'X = '1 + '2` (i.e., the union
            // `'1` and `'2`), then in this loop `ur` will be `'1` (and `'2`). So here
            // we check whether `T: '1` is something we *can* prove. If so, no need
            // to propagate that requirement.
            //
            // This is needed because -- particularly in the case
            // where `ur` is a local bound -- we are sometimes in a
            // position to prove things that our caller cannot.  See
            // #53570 for an example.
939
            if self.eval_verify_bound(tcx, body, generic_ty, ur, &type_test.verify_bound) {
940 941 942
                continue;
            }

N
Niko Matsakis 已提交
943 944
            debug!("try_promote_type_test: ur={:?}", ur);

945
            let non_local_ub = self.universal_region_relations.non_local_upper_bounds(&ur);
N
Niko Matsakis 已提交
946
            debug!("try_promote_type_test: non_local_ub={:?}", non_local_ub);
M
Mikhail Modin 已提交
947

948 949 950 951 952 953 954 955 956 957 958
            // This is slightly too conservative. To show T: '1, given `'2: '1`
            // and `'3: '1` we only need to prove that T: '2 *or* T: '3, but to
            // avoid potential non-determinism we approximate this by requiring
            // T: '1 and T: '2.
            for &upper_bound in non_local_ub {
                debug_assert!(self.universal_regions.is_universal_region(upper_bound));
                debug_assert!(!self.universal_regions.is_local_free_region(upper_bound));

                let requirement = ClosureOutlivesRequirement {
                    subject,
                    outlived_free_region: upper_bound,
959
                    blame_span: locations.span(body),
960 961 962 963 964
                    category: ConstraintCategory::Boring,
                };
                debug!("try_promote_type_test: pushing {:#?}", requirement);
                propagated_outlives_requirements.push(requirement);
            }
M
Mikhail Modin 已提交
965
        }
966 967 968
        true
    }

N
Niko Matsakis 已提交
969 970
    /// When we promote a type test `T: 'r`, we have to convert the
    /// type `T` into something we can store in a query result (so
971
    /// something allocated for `'tcx`). This is problematic if `ty`
N
Niko Matsakis 已提交
972 973 974 975 976 977
    /// contains regions. During the course of NLL region checking, we
    /// will have replaced all of those regions with fresh inference
    /// variables. To create a test subject, we want to replace those
    /// inference variables with some region from the closure
    /// signature -- this is not always possible, so this is a
    /// fallible process. Presuming we do find a suitable region, we
M
Matthew Jasper 已提交
978 979 980
    /// will use it's *external name*, which will be a `RegionKind`
    /// variant that can be used in query responses such as
    /// `ReEarlyBound`.
981
    fn try_promote_type_test_subject(
N
Niko Matsakis 已提交
982
        &self,
983
        infcx: &InferCtxt<'_, 'tcx>,
N
Niko Matsakis 已提交
984
        ty: Ty<'tcx>,
985
    ) -> Option<ClosureOutlivesSubject<'tcx>> {
N
Niko Matsakis 已提交
986 987 988 989
        let tcx = infcx.tcx;

        debug!("try_promote_type_test_subject(ty = {:?})", ty);

B
Bastian Kauschke 已提交
990
        let ty = tcx.fold_regions(ty, &mut false, |r, _depth| {
N
Niko Matsakis 已提交
991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028
            let region_vid = self.to_region_vid(r);

            // The challenge if this. We have some region variable `r`
            // whose value is a set of CFG points and universal
            // regions. We want to find if that set is *equivalent* to
            // any of the named regions found in the closure.
            //
            // To do so, we compute the
            // `non_local_universal_upper_bound`. This will be a
            // non-local, universal region that is greater than `r`.
            // However, it might not be *contained* within `r`, so
            // then we further check whether this bound is contained
            // in `r`. If so, we can say that `r` is equivalent to the
            // bound.
            //
            // Let's work through a few examples. For these, imagine
            // that we have 3 non-local regions (I'll denote them as
            // `'static`, `'a`, and `'b`, though of course in the code
            // they would be represented with indices) where:
            //
            // - `'static: 'a`
            // - `'static: 'b`
            //
            // First, let's assume that `r` is some existential
            // variable with an inferred value `{'a, 'static}` (plus
            // some CFG nodes). In this case, the non-local upper
            // bound is `'static`, since that outlives `'a`. `'static`
            // is also a member of `r` and hence we consider `r`
            // equivalent to `'static` (and replace it with
            // `'static`).
            //
            // Now let's consider the inferred value `{'a, 'b}`. This
            // means `r` is effectively `'a | 'b`. I'm not sure if
            // this can come about, actually, but assuming it did, we
            // would get a non-local upper bound of `'static`. Since
            // `'static` is not contained in `r`, we would fail to
            // find an equivalent.
            let upper_bound = self.non_local_universal_upper_bound(region_vid);
1029
            if self.region_contains(region_vid, upper_bound) {
M
Matthew Jasper 已提交
1030
                self.definitions[upper_bound].external_name.unwrap_or(r)
N
Niko Matsakis 已提交
1031
            } else {
M
Matthew Jasper 已提交
1032
                // In the case of a failure, use a `ReVar` result. This will
1033
                // cause the `needs_infer` later on to return `None`.
N
Niko Matsakis 已提交
1034 1035 1036
                r
            }
        });
M
Matthew Jasper 已提交
1037

N
Niko Matsakis 已提交
1038 1039
        debug!("try_promote_type_test_subject: folded ty = {:?}", ty);

1040 1041
        // `needs_infer` will only be true if we failed to promote some region.
        if ty.needs_infer() {
1042 1043
            return None;
        }
N
Niko Matsakis 已提交
1044 1045 1046 1047 1048 1049 1050 1051

        Some(ClosureOutlivesSubject::Ty(ty))
    }

    /// Given some universal or existential region `r`, finds a
    /// non-local, universal region `r+` that outlives `r` at entry to (and
    /// exit from) the closure. In the worst case, this will be
    /// `'static`.
1052
    ///
N
Niko Matsakis 已提交
1053 1054 1055 1056 1057 1058
    /// This is used for two purposes. First, if we are propagated
    /// some requirement `T: r`, we can use this method to enlarge `r`
    /// to something we can encode for our creator (which only knows
    /// about non-local, universal regions). It is also used when
    /// encoding `T` as part of `try_promote_type_test_subject` (see
    /// that fn for details).
1059
    ///
1060 1061 1062 1063
    /// This is based on the result `'y` of `universal_upper_bound`,
    /// except that it converts further takes the non-local upper
    /// bound of `'y`, so that the final result is non-local.
    fn non_local_universal_upper_bound(&self, r: RegionVid) -> RegionVid {
1064
        debug!("non_local_universal_upper_bound(r={:?}={})", r, self.region_value_str(r));
1065 1066 1067 1068 1069

        let lub = self.universal_upper_bound(r);

        // Grow further to get smallest universal region known to
        // creator.
1070
        let non_local_lub = self.universal_region_relations.non_local_upper_bound(lub);
1071

1072
        debug!("non_local_universal_upper_bound: non_local_lub={:?}", non_local_lub);
1073 1074 1075 1076 1077 1078 1079 1080

        non_local_lub
    }

    /// Returns a universally quantified region that outlives the
    /// value of `r` (`r` may be existentially or universally
    /// quantified).
    ///
N
Niko Matsakis 已提交
1081 1082 1083 1084 1085
    /// Since `r` is (potentially) an existential region, it has some
    /// value which may include (a) any number of points in the CFG
    /// and (b) any number of `end('x)` elements of universally
    /// quantified regions. To convert this into a single universal
    /// region we do as follows:
1086 1087 1088 1089 1090
    ///
    /// - Ignore the CFG points in `'r`. All universally quantified regions
    ///   include the CFG anyhow.
    /// - For each `end('x)` element in `'r`, compute the mutual LUB, yielding
    ///   a result `'y`.
1091
    pub(crate) fn universal_upper_bound(&self, r: RegionVid) -> RegionVid {
1092
        debug!("universal_upper_bound(r={:?}={})", r, self.region_value_str(r));
1093 1094 1095 1096

        // Find the smallest universal region that contains all other
        // universal regions within `region`.
        let mut lub = self.universal_regions.fr_fn_body;
1097 1098
        let r_scc = self.constraint_sccs.scc(r);
        for ur in self.scc_values.universal_regions_outlived_by(r_scc) {
1099
            lub = self.universal_region_relations.postdom_upper_bound(lub, ur);
1100 1101
        }

1102
        debug!("universal_upper_bound: r={:?} lub={:?}", r, lub);
1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117

        lub
    }

    /// Like `universal_upper_bound`, but returns an approximation more suitable
    /// for diagnostics. If `r` contains multiple disjoint universal regions
    /// (e.g. 'a and 'b in `fn foo<'a, 'b> { ... }`, we pick the lower-numbered region.
    /// This corresponds to picking named regions over unnamed regions
    /// (e.g. picking early-bound regions over a closure late-bound region).
    ///
    /// This means that the returned value may not be a true upper bound, since
    /// only 'static is known to outlive disjoint universal regions.
    /// Therefore, this method should only be used in diagnostic code,
    /// where displaying *some* named universal region is better than
    /// falling back to 'static.
1118
    pub(crate) fn approx_universal_upper_bound(&self, r: RegionVid) -> RegionVid {
1119 1120 1121 1122 1123 1124 1125 1126 1127 1128
        debug!("approx_universal_upper_bound(r={:?}={})", r, self.region_value_str(r));

        // Find the smallest universal region that contains all other
        // universal regions within `region`.
        let mut lub = self.universal_regions.fr_fn_body;
        let r_scc = self.constraint_sccs.scc(r);
        let static_r = self.universal_regions.fr_static;
        for ur in self.scc_values.universal_regions_outlived_by(r_scc) {
            let new_lub = self.universal_region_relations.postdom_upper_bound(lub, ur);
            debug!("approx_universal_upper_bound: ur={:?} lub={:?} new_lub={:?}", ur, lub, new_lub);
1129 1130 1131 1132
            // The upper bound of two non-static regions is static: this
            // means we know nothing about the relationship between these
            // two regions. Pick a 'better' one to use when constructing
            // a diagnostic
1133
            if ur != static_r && lub != static_r && new_lub == static_r {
1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146
                // Prefer the region with an `external_name` - this
                // indicates that the region is early-bound, so working with
                // it can produce a nicer error.
                if self.region_definition(ur).external_name.is_some() {
                    lub = ur;
                } else if self.region_definition(lub).external_name.is_some() {
                    // Leave lub unchanged
                } else {
                    // If we get here, we don't have any reason to prefer
                    // one region over the other. Just pick the
                    // one with the lower index for now.
                    lub = std::cmp::min(ur, lub);
                }
1147 1148 1149 1150 1151 1152
            } else {
                lub = new_lub;
            }
        }

        debug!("approx_universal_upper_bound: r={:?} lub={:?}", r, lub);
1153

1154
        lub
1155 1156
    }

A
Alexander Regueiro 已提交
1157 1158
    /// Tests if `test` is true when applied to `lower_bound` at
    /// `point`.
1159 1160
    fn eval_verify_bound(
        &self,
1161
        tcx: TyCtxt<'tcx>,
1162
        body: &Body<'tcx>,
1163
        generic_ty: Ty<'tcx>,
1164 1165 1166
        lower_bound: RegionVid,
        verify_bound: &VerifyBound<'tcx>,
    ) -> bool {
1167
        debug!("eval_verify_bound(lower_bound={:?}, verify_bound={:?})", lower_bound, verify_bound);
1168

1169
        match verify_bound {
1170
            VerifyBound::IfEq(test_ty, verify_bound1) => {
1171
                self.eval_if_eq(tcx, body, generic_ty, lower_bound, test_ty, verify_bound1)
1172
            }
1173

1174 1175 1176 1177 1178
            VerifyBound::IsEmpty => {
                let lower_bound_scc = self.constraint_sccs.scc(lower_bound);
                self.scc_values.elements_contained_in(lower_bound_scc).next().is_none()
            }

1179 1180
            VerifyBound::OutlivedBy(r) => {
                let r_vid = self.to_region_vid(r);
1181
                self.eval_outlives(r_vid, lower_bound)
1182
            }
1183

1184
            VerifyBound::AnyBound(verify_bounds) => verify_bounds.iter().any(|verify_bound| {
1185
                self.eval_verify_bound(tcx, body, generic_ty, lower_bound, verify_bound)
1186
            }),
1187

1188
            VerifyBound::AllBounds(verify_bounds) => verify_bounds.iter().all(|verify_bound| {
1189
                self.eval_verify_bound(tcx, body, generic_ty, lower_bound, verify_bound)
1190
            }),
1191 1192 1193
        }
    }

1194 1195
    fn eval_if_eq(
        &self,
1196
        tcx: TyCtxt<'tcx>,
1197
        body: &Body<'tcx>,
1198 1199 1200 1201 1202 1203 1204 1205
        generic_ty: Ty<'tcx>,
        lower_bound: RegionVid,
        test_ty: Ty<'tcx>,
        verify_bound: &VerifyBound<'tcx>,
    ) -> bool {
        let generic_ty_normalized = self.normalize_to_scc_representatives(tcx, generic_ty);
        let test_ty_normalized = self.normalize_to_scc_representatives(tcx, test_ty);
        if generic_ty_normalized == test_ty_normalized {
1206
            self.eval_verify_bound(tcx, body, generic_ty, lower_bound, verify_bound)
1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220
        } else {
            false
        }
    }

    /// This is a conservative normalization procedure. It takes every
    /// free region in `value` and replaces it with the
    /// "representative" of its SCC (see `scc_representatives` field).
    /// We are guaranteed that if two values normalize to the same
    /// thing, then they are equal; this is a conservative check in
    /// that they could still be equal even if they normalize to
    /// different results. (For example, there might be two regions
    /// with the same value that are not in the same SCC).
    ///
A
Alexander Regueiro 已提交
1221
    /// N.B., this is not an ideal approach and I would like to revisit
1222 1223 1224
    /// it. However, it works pretty well in practice. In particular,
    /// this is needed to deal with projection outlives bounds like
    ///
J
Joshua Nelson 已提交
1225
    /// ```text
1226 1227
    /// <T as Foo<'0>>::Item: '1
    /// ```
1228 1229 1230
    ///
    /// In particular, this routine winds up being important when
    /// there are bounds like `where <T as Foo<'a>>::Item: 'b` in the
A
Alexander Regueiro 已提交
1231
    /// environment. In this case, if we can show that `'0 == 'a`,
1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243
    /// and that `'b: '1`, then we know that the clause is
    /// satisfied. In such cases, particularly due to limitations of
    /// the trait solver =), we usually wind up with a where-clause like
    /// `T: Foo<'a>` in scope, which thus forces `'0 == 'a` to be added as
    /// a constraint, and thus ensures that they are in the same SCC.
    ///
    /// So why can't we do a more correct routine? Well, we could
    /// *almost* use the `relate_tys` code, but the way it is
    /// currently setup it creates inference variables to deal with
    /// higher-ranked things and so forth, and right now the inference
    /// context is not permitted to make more inference variables. So
    /// we use this kind of hacky solution.
1244
    fn normalize_to_scc_representatives<T>(&self, tcx: TyCtxt<'tcx>, value: T) -> T
1245 1246 1247
    where
        T: TypeFoldable<'tcx>,
    {
B
Bastian Kauschke 已提交
1248
        tcx.fold_regions(value, &mut false, |r, _db| {
1249 1250 1251 1252 1253 1254 1255
            let vid = self.to_region_vid(r);
            let scc = self.constraint_sccs.scc(vid);
            let repr = self.scc_representatives[scc];
            tcx.mk_region(ty::ReVar(repr))
        })
    }

1256 1257 1258 1259 1260 1261 1262
    // Evaluate whether `sup_region == sub_region`.
    fn eval_equal(&self, r1: RegionVid, r2: RegionVid) -> bool {
        self.eval_outlives(r1, r2) && self.eval_outlives(r2, r1)
    }

    // Evaluate whether `sup_region: sub_region`.
    fn eval_outlives(&self, sup_region: RegionVid, sub_region: RegionVid) -> bool {
S
Santiago Pastorino 已提交
1263
        debug!("eval_outlives({:?}: {:?})", sup_region, sub_region);
1264

1265 1266 1267 1268 1269 1270 1271 1272 1273 1274
        debug!(
            "eval_outlives: sup_region's value = {:?} universal={:?}",
            self.region_value_str(sup_region),
            self.universal_regions.is_universal_region(sup_region),
        );
        debug!(
            "eval_outlives: sub_region's value = {:?} universal={:?}",
            self.region_value_str(sub_region),
            self.universal_regions.is_universal_region(sub_region),
        );
1275

1276 1277 1278
        let sub_region_scc = self.constraint_sccs.scc(sub_region);
        let sup_region_scc = self.constraint_sccs.scc(sup_region);

1279 1280 1281 1282 1283 1284
        // Both the `sub_region` and `sup_region` consist of the union
        // of some number of universal regions (along with the union
        // of various points in the CFG; ignore those points for
        // now). Therefore, the sup-region outlives the sub-region if,
        // for each universal region R1 in the sub-region, there
        // exists some region R2 in the sup-region that outlives R1.
1285 1286
        let universal_outlives =
            self.scc_values.universal_regions_outlived_by(sub_region_scc).all(|r1| {
1287 1288
                self.scc_values
                    .universal_regions_outlived_by(sup_region_scc)
1289
                    .any(|r2| self.universal_region_relations.outlives(r2, r1))
1290 1291 1292 1293
            });

        if !universal_outlives {
            return false;
1294
        }
1295 1296 1297 1298 1299 1300 1301

        // Now we have to compare all the points in the sub region and make
        // sure they exist in the sup region.

        if self.universal_regions.is_universal_region(sup_region) {
            // Micro-opt: universal regions contain all points.
            return true;
1302
        }
1303

1304
        self.scc_values.contains_points(sup_region_scc, sub_region_scc)
1305 1306
    }

1307 1308 1309
    /// Once regions have been propagated, this method is used to see
    /// whether any of the constraints were too strong. In particular,
    /// we want to check for a case where a universally quantified
A
Alexander Regueiro 已提交
1310
    /// region exceeded its bounds. Consider:
1311 1312 1313 1314 1315 1316 1317 1318 1319
    ///
    ///     fn foo<'a, 'b>(x: &'a u32) -> &'b u32 { x }
    ///
    /// In this case, returning `x` requires `&'a u32 <: &'b u32`
    /// and hence we establish (transitively) a constraint that
    /// `'a: 'b`. The `propagate_constraints` code above will
    /// therefore add `end('a)` into the region for `'b` -- but we
    /// have no evidence that `'b` outlives `'a`, so we want to report
    /// an error.
1320 1321 1322 1323
    ///
    /// If `propagated_outlives_requirements` is `Some`, then we will
    /// push unsatisfied obligations into there. Otherwise, we'll
    /// report them as errors.
1324
    fn check_universal_regions(
1325
        &self,
1326
        body: &Body<'tcx>,
1327
        mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>,
1328
        errors_buffer: &mut RegionErrors<'tcx>,
1329
    ) {
1330 1331
        for (fr, fr_definition) in self.definitions.iter_enumerated() {
            match fr_definition.origin {
1332
                NllRegionVariableOrigin::FreeRegion => {
1333 1334 1335 1336
                    // Go through each of the universal regions `fr` and check that
                    // they did not grow too large, accumulating any requirements
                    // for our caller into the `outlives_requirements` vector.
                    self.check_universal_region(
1337
                        body,
1338 1339
                        fr,
                        &mut propagated_outlives_requirements,
M
Mark Mansi 已提交
1340
                        errors_buffer,
1341 1342 1343
                    );
                }

1344
                NllRegionVariableOrigin::Placeholder(placeholder) => {
1345
                    self.check_bound_universal_region(fr, placeholder, errors_buffer);
N
Niko Matsakis 已提交
1346 1347
                }

1348 1349
                NllRegionVariableOrigin::RootEmptyRegion
                | NllRegionVariableOrigin::Existential { .. } => {
1350 1351 1352
                    // nothing to check here
                }
            }
1353
        }
1354 1355
    }

1356 1357 1358 1359 1360 1361 1362 1363
    /// Checks if Polonius has found any unexpected free region relations.
    ///
    /// In Polonius terms, a "subset error" (or "illegal subset relation error") is the equivalent
    /// of NLL's "checking if any region constraints were too strong": a placeholder origin `'a`
    /// was unexpectedly found to be a subset of another placeholder origin `'b`, and means in NLL
    /// terms that the "longer free region" `'a` outlived the "shorter free region" `'b`.
    ///
    /// More details can be found in this blog post by Niko:
S
Smitty 已提交
1364
    /// <https://smallcultfollowing.com/babysteps/blog/2019/01/17/polonius-and-region-errors/>
1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380
    ///
    /// In the canonical example
    ///
    ///     fn foo<'a, 'b>(x: &'a u32) -> &'b u32 { x }
    ///
    /// returning `x` requires `&'a u32 <: &'b u32` and hence we establish (transitively) a
    /// constraint that `'a: 'b`. It is an error that we have no evidence that this
    /// constraint holds.
    ///
    /// If `propagated_outlives_requirements` is `Some`, then we will
    /// push unsatisfied obligations into there. Otherwise, we'll
    /// report them as errors.
    fn check_polonius_subset_errors(
        &self,
        body: &Body<'tcx>,
        mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>,
1381
        errors_buffer: &mut RegionErrors<'tcx>,
1382 1383
        polonius_output: Rc<PoloniusOutput>,
    ) {
R
Remy Rakic 已提交
1384 1385 1386 1387
        debug!(
            "check_polonius_subset_errors: {} subset_errors",
            polonius_output.subset_errors.len()
        );
1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416

        // Similarly to `check_universal_regions`: a free region relation, which was not explicitly
        // declared ("known") was found by Polonius, so emit an error, or propagate the
        // requirements for our caller into the `propagated_outlives_requirements` vector.
        //
        // Polonius doesn't model regions ("origins") as CFG-subsets or durations, but the
        // `longer_fr` and `shorter_fr` terminology will still be used here, for consistency with
        // the rest of the NLL infrastructure. The "subset origin" is the "longer free region",
        // and the "superset origin" is the outlived "shorter free region".
        //
        // Note: Polonius will produce a subset error at every point where the unexpected
        // `longer_fr`'s "placeholder loan" is contained in the `shorter_fr`. This can be helpful
        // for diagnostics in the future, e.g. to point more precisely at the key locations
        // requiring this constraint to hold. However, the error and diagnostics code downstream
        // expects that these errors are not duplicated (and that they are in a certain order).
        // Otherwise, diagnostics messages such as the ones giving names like `'1` to elided or
        // anonymous lifetimes for example, could give these names differently, while others like
        // the outlives suggestions or the debug output from `#[rustc_regions]` would be
        // duplicated. The polonius subset errors are deduplicated here, while keeping the
        // CFG-location ordering.
        let mut subset_errors: Vec<_> = polonius_output
            .subset_errors
            .iter()
            .flat_map(|(_location, subset_errors)| subset_errors.iter())
            .collect();
        subset_errors.sort();
        subset_errors.dedup();

        for (longer_fr, shorter_fr) in subset_errors.into_iter() {
M
Mark Rousskov 已提交
1417 1418
            debug!(
                "check_polonius_subset_errors: subset_error longer_fr={:?},\
1419
                 shorter_fr={:?}",
M
Mark Rousskov 已提交
1420 1421
                longer_fr, shorter_fr
            );
1422

1423
            let propagated = self.try_propagate_universal_region_error(
1424 1425 1426 1427 1428
                *longer_fr,
                *shorter_fr,
                body,
                &mut propagated_outlives_requirements,
            );
1429 1430 1431 1432
            if propagated == RegionRelationCheckResult::Error {
                errors_buffer.push(RegionErrorKind::RegionError {
                    longer_fr: *longer_fr,
                    shorter_fr: *shorter_fr,
1433
                    fr_origin: NllRegionVariableOrigin::FreeRegion,
1434 1435
                    is_reported: true,
                });
1436
            }
1437 1438 1439 1440 1441 1442
        }

        // Handle the placeholder errors as usual, until the chalk-rustc-polonius triumvirate has
        // a more complete picture on how to separate this responsibility.
        for (fr, fr_definition) in self.definitions.iter_enumerated() {
            match fr_definition.origin {
1443
                NllRegionVariableOrigin::FreeRegion => {
1444 1445 1446
                    // handled by polonius above
                }

1447
                NllRegionVariableOrigin::Placeholder(placeholder) => {
1448
                    self.check_bound_universal_region(fr, placeholder, errors_buffer);
1449 1450
                }

1451 1452
                NllRegionVariableOrigin::RootEmptyRegion
                | NllRegionVariableOrigin::Existential { .. } => {
1453 1454 1455 1456 1457 1458
                    // nothing to check here
                }
            }
        }
    }

A
Alexander Regueiro 已提交
1459
    /// Checks the final value for the free region `fr` to see if it
1460 1461 1462 1463 1464 1465 1466
    /// grew too large. In particular, examine what `end(X)` points
    /// wound up in `fr`'s final value; for each `end(X)` where `X !=
    /// fr`, we want to check that `fr: X`. If not, that's either an
    /// error, or something we have to propagate to our creator.
    ///
    /// Things that are to be propagated are accumulated into the
    /// `outlives_requirements` vector.
1467
    fn check_universal_region(
1468
        &self,
1469
        body: &Body<'tcx>,
1470
        longer_fr: RegionVid,
1471
        propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>,
1472
        errors_buffer: &mut RegionErrors<'tcx>,
1473
    ) {
1474
        debug!("check_universal_region(fr={:?})", longer_fr);
1475

1476 1477
        let longer_fr_scc = self.constraint_sccs.scc(longer_fr);

N
Niko Matsakis 已提交
1478 1479 1480
        // Because this free region must be in the ROOT universe, we
        // know it cannot contain any bound universes.
        assert!(self.scc_universes[longer_fr_scc] == ty::UniverseIndex::ROOT);
1481
        debug_assert!(self.scc_values.placeholders_contained_in(longer_fr_scc).next().is_none());
N
Niko Matsakis 已提交
1482

1483 1484 1485 1486 1487 1488 1489 1490
        // Only check all of the relations for the main representative of each
        // SCC, otherwise just check that we outlive said representative. This
        // reduces the number of redundant relations propagated out of
        // closures.
        // Note that the representative will be a universal region if there is
        // one in this SCC, so we will always check the representative here.
        let representative = self.scc_representatives[longer_fr_scc];
        if representative != longer_fr {
1491
            if let RegionRelationCheckResult::Error = self.check_universal_region_relation(
1492 1493
                longer_fr,
                representative,
1494
                body,
1495
                propagated_outlives_requirements,
1496 1497 1498 1499
            ) {
                errors_buffer.push(RegionErrorKind::RegionError {
                    longer_fr,
                    shorter_fr: representative,
1500
                    fr_origin: NllRegionVariableOrigin::FreeRegion,
1501 1502 1503
                    is_reported: true,
                });
            }
1504 1505 1506
            return;
        }

1507 1508
        // Find every region `o` such that `fr: o`
        // (because `fr` includes `end(o)`).
1509
        let mut error_reported = false;
1510
        for shorter_fr in self.scc_values.universal_regions_outlived_by(longer_fr_scc) {
1511
            if let RegionRelationCheckResult::Error = self.check_universal_region_relation(
1512 1513
                longer_fr,
                shorter_fr,
1514
                body,
1515 1516
                propagated_outlives_requirements,
            ) {
1517 1518 1519 1520 1521 1522
                // We only report the first region error. Subsequent errors are hidden so as
                // not to overwhelm the user, but we do record them so as to potentially print
                // better diagnostics elsewhere...
                errors_buffer.push(RegionErrorKind::RegionError {
                    longer_fr,
                    shorter_fr,
1523
                    fr_origin: NllRegionVariableOrigin::FreeRegion,
1524 1525 1526 1527
                    is_reported: !error_reported,
                });

                error_reported = true;
1528
            }
1529 1530
        }
    }
1531

1532 1533 1534
    /// Checks that we can prove that `longer_fr: shorter_fr`. If we can't we attempt to propagate
    /// the constraint outward (e.g. to a closure environment), but if that fails, there is an
    /// error.
1535 1536 1537 1538
    fn check_universal_region_relation(
        &self,
        longer_fr: RegionVid,
        shorter_fr: RegionVid,
1539
        body: &Body<'tcx>,
1540
        propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>,
1541
    ) -> RegionRelationCheckResult {
1542
        // If it is known that `fr: o`, carry on.
1543
        if self.universal_region_relations.outlives(longer_fr, shorter_fr) {
1544
            RegionRelationCheckResult::Ok
1545 1546 1547 1548 1549 1550 1551
        } else {
            // If we are not in a context where we can't propagate errors, or we
            // could not shrink `fr` to something smaller, then just report an
            // error.
            //
            // Note: in this case, we use the unapproximated regions to report the
            // error. This gives better error messages in some cases.
1552
            self.try_propagate_universal_region_error(
1553 1554
                longer_fr,
                shorter_fr,
1555 1556 1557
                body,
                propagated_outlives_requirements,
            )
1558
        }
1559 1560
    }

1561
    /// Attempt to propagate a region error (e.g. `'a: 'b`) that is not met to a closure's
W
Who? Me?! 已提交
1562
    /// creator. If we cannot, then the caller should report an error to the user.
1563
    fn try_propagate_universal_region_error(
1564 1565 1566 1567 1568
        &self,
        longer_fr: RegionVid,
        shorter_fr: RegionVid,
        body: &Body<'tcx>,
        propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>,
1569
    ) -> RegionRelationCheckResult {
1570
        if let Some(propagated_outlives_requirements) = propagated_outlives_requirements {
1571 1572 1573
            // Shrink `longer_fr` until we find a non-local region (if we do).
            // We'll call it `fr-` -- it's ever so slightly smaller than
            // `longer_fr`.
M
Mark Rousskov 已提交
1574 1575
            if let Some(fr_minus) = self.universal_region_relations.non_local_lower_bound(longer_fr)
            {
1576
                debug!("try_propagate_universal_region_error: fr_minus={:?}", fr_minus);
1577

M
Mark Rousskov 已提交
1578 1579 1580
                let blame_span_category = self.find_outlives_blame_span(
                    body,
                    longer_fr,
1581
                    NllRegionVariableOrigin::FreeRegion,
M
Mark Rousskov 已提交
1582 1583
                    shorter_fr,
                );
1584

1585 1586 1587
                // Grow `shorter_fr` until we find some non-local regions. (We
                // always will.)  We'll call them `shorter_fr+` -- they're ever
                // so slightly larger than `shorter_fr`.
M
Mark Rousskov 已提交
1588 1589
                let shorter_fr_plus =
                    self.universal_region_relations.non_local_upper_bounds(&shorter_fr);
1590
                debug!(
1591
                    "try_propagate_universal_region_error: shorter_fr_plus={:?}",
R
Remy Rakic 已提交
1592
                    shorter_fr_plus
1593
                );
1594 1595 1596 1597 1598 1599 1600 1601 1602
                for &&fr in &shorter_fr_plus {
                    // Push the constraint `fr-: shorter_fr+`
                    propagated_outlives_requirements.push(ClosureOutlivesRequirement {
                        subject: ClosureOutlivesSubject::Region(fr_minus),
                        outlived_free_region: fr,
                        blame_span: blame_span_category.1,
                        category: blame_span_category.0,
                    });
                }
1603
                return RegionRelationCheckResult::Propagated;
1604
            }
1605
        }
1606

1607
        RegionRelationCheckResult::Error
1608
    }
N
Niko Matsakis 已提交
1609

1610
    fn check_bound_universal_region(
N
Niko Matsakis 已提交
1611 1612
        &self,
        longer_fr: RegionVid,
S
scalexm 已提交
1613
        placeholder: ty::PlaceholderRegion,
1614
        errors_buffer: &mut RegionErrors<'tcx>,
N
Niko Matsakis 已提交
1615
    ) {
1616
        debug!("check_bound_universal_region(fr={:?}, placeholder={:?})", longer_fr, placeholder,);
N
Niko Matsakis 已提交
1617 1618

        let longer_fr_scc = self.constraint_sccs.scc(longer_fr);
1619
        debug!("check_bound_universal_region: longer_fr_scc={:?}", longer_fr_scc,);
N
Niko Matsakis 已提交
1620 1621 1622 1623 1624

        // If we have some bound universal region `'a`, then the only
        // elements it can contain is itself -- we don't know anything
        // else about it!
        let error_element = match {
1625 1626 1627 1628 1629
            self.scc_values.elements_contained_in(longer_fr_scc).find(|element| match element {
                RegionElement::Location(_) => true,
                RegionElement::RootUniversalRegion(_) => true,
                RegionElement::PlaceholderRegion(placeholder1) => placeholder != *placeholder1,
            })
N
Niko Matsakis 已提交
1630 1631 1632 1633
        } {
            Some(v) => v,
            None => return,
        };
1634
        debug!("check_bound_universal_region: error_element = {:?}", error_element);
N
Niko Matsakis 已提交
1635 1636

        // Find the region that introduced this `error_element`.
1637
        errors_buffer.push(RegionErrorKind::BoundUniversalRegionError {
M
Mark Rousskov 已提交
1638
            longer_fr,
1639
            error_element,
1640
            placeholder,
1641
        });
N
Niko Matsakis 已提交
1642
    }
1643

N
Niko Matsakis 已提交
1644
    fn check_member_constraints(
1645 1646
        &self,
        infcx: &InferCtxt<'_, 'tcx>,
1647
        errors_buffer: &mut RegionErrors<'tcx>,
1648
    ) {
N
Niko Matsakis 已提交
1649 1650 1651 1652 1653
        let member_constraints = self.member_constraints.clone();
        for m_c_i in member_constraints.all_indices() {
            debug!("check_member_constraint(m_c_i={:?})", m_c_i);
            let m_c = &member_constraints[m_c_i];
            let member_region_vid = m_c.member_region_vid;
N
Niko Matsakis 已提交
1654
            debug!(
N
Niko Matsakis 已提交
1655 1656 1657
                "check_member_constraint: member_region_vid={:?} with value {}",
                member_region_vid,
                self.region_value_str(member_region_vid),
N
Niko Matsakis 已提交
1658
            );
N
Niko Matsakis 已提交
1659 1660
            let choice_regions = member_constraints.choice_regions(m_c_i);
            debug!("check_member_constraint: choice_regions={:?}", choice_regions);
1661

N
Niko Matsakis 已提交
1662
            // Did the member region wind up equal to any of the option regions?
M
Mark Rousskov 已提交
1663 1664 1665
            if let Some(o) =
                choice_regions.iter().find(|&&o_r| self.eval_equal(o_r, m_c.member_region_vid))
            {
N
Niko Matsakis 已提交
1666
                debug!("check_member_constraint: evaluated as equal to {:?}", o);
1667 1668 1669
                continue;
            }

N
Niko Matsakis 已提交
1670
            // If not, report an error.
N
Niko Matsakis 已提交
1671
            let member_region = infcx.tcx.mk_region(ty::ReVar(member_region_vid));
1672
            errors_buffer.push(RegionErrorKind::UnexpectedHiddenRegion {
1673
                span: m_c.definition_span,
1674
                hidden_ty: m_c.hidden_ty,
N
Niko Matsakis 已提交
1675
                member_region,
1676
            });
1677 1678
        }
    }
1679

1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715
    /// We have a constraint `fr1: fr2` that is not satisfied, where
    /// `fr2` represents some universal region. Here, `r` is some
    /// region where we know that `fr1: r` and this function has the
    /// job of determining whether `r` is "to blame" for the fact that
    /// `fr1: fr2` is required.
    ///
    /// This is true under two conditions:
    ///
    /// - `r == fr2`
    /// - `fr2` is `'static` and `r` is some placeholder in a universe
    ///   that cannot be named by `fr1`; in that case, we will require
    ///   that `fr1: 'static` because it is the only way to `fr1: r` to
    ///   be satisfied. (See `add_incompatible_universe`.)
    crate fn provides_universal_region(
        &self,
        r: RegionVid,
        fr1: RegionVid,
        fr2: RegionVid,
    ) -> bool {
        debug!("provides_universal_region(r={:?}, fr1={:?}, fr2={:?})", r, fr1, fr2);
        let result = {
            r == fr2 || {
                fr2 == self.universal_regions.fr_static && self.cannot_name_placeholder(fr1, r)
            }
        };
        debug!("provides_universal_region: result = {:?}", result);
        result
    }

    /// If `r2` represents a placeholder region, then this returns
    /// `true` if `r1` cannot name that placeholder in its
    /// value; otherwise, returns `false`.
    crate fn cannot_name_placeholder(&self, r1: RegionVid, r2: RegionVid) -> bool {
        debug!("cannot_name_value_of(r1={:?}, r2={:?})", r1, r2);

        match self.definitions[r2].origin {
1716
            NllRegionVariableOrigin::Placeholder(placeholder) => {
1717 1718 1719 1720 1721 1722 1723 1724
                let universe1 = self.definitions[r1].universe;
                debug!(
                    "cannot_name_value_of: universe1={:?} placeholder={:?}",
                    universe1, placeholder
                );
                universe1.cannot_name(placeholder.universe)
            }

1725 1726 1727
            NllRegionVariableOrigin::RootEmptyRegion
            | NllRegionVariableOrigin::FreeRegion
            | NllRegionVariableOrigin::Existential { .. } => false,
1728 1729 1730 1731 1732 1733
        }
    }

    crate fn retrieve_closure_constraint_info(
        &self,
        body: &Body<'tcx>,
1734 1735
        constraint: &OutlivesConstraint<'tcx>,
    ) -> BlameConstraint<'tcx> {
1736
        let loc = match constraint.locations {
1737 1738 1739 1740 1741 1742 1743 1744
            Locations::All(span) => {
                return BlameConstraint {
                    category: constraint.category,
                    from_closure: false,
                    span,
                    variance_info: constraint.variance_info.clone(),
                };
            }
1745 1746 1747 1748 1749
            Locations::Single(loc) => loc,
        };

        let opt_span_category =
            self.closure_bounds_mapping[&loc].get(&(constraint.sup, constraint.sub));
1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762
        opt_span_category
            .map(|&(category, span)| BlameConstraint {
                category,
                from_closure: true,
                span: span,
                variance_info: constraint.variance_info.clone(),
            })
            .unwrap_or(BlameConstraint {
                category: constraint.category,
                from_closure: false,
                span: body.source_info(loc).span,
                variance_info: constraint.variance_info.clone(),
            })
1763 1764 1765 1766 1767 1768 1769
    }

    /// Finds a good span to blame for the fact that `fr1` outlives `fr2`.
    crate fn find_outlives_blame_span(
        &self,
        body: &Body<'tcx>,
        fr1: RegionVid,
1770
        fr1_origin: NllRegionVariableOrigin,
1771 1772
        fr2: RegionVid,
    ) -> (ConstraintCategory, Span) {
1773 1774 1775 1776
        let BlameConstraint { category, span, .. } =
            self.best_blame_constraint(body, fr1, fr1_origin, |r| {
                self.provides_universal_region(r, fr1, fr2)
            });
1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791
        (category, span)
    }

    /// Walks the graph of constraints (where `'a: 'b` is considered
    /// an edge `'a -> 'b`) to find all paths from `from_region` to
    /// `to_region`. The paths are accumulated into the vector
    /// `results`. The paths are stored as a series of
    /// `ConstraintIndex` values -- in other words, a list of *edges*.
    ///
    /// Returns: a series of constraints as well as the region `R`
    /// that passed the target test.
    crate fn find_constraint_paths_between_regions(
        &self,
        from_region: RegionVid,
        target_test: impl Fn(RegionVid) -> bool,
1792
    ) -> Option<(Vec<OutlivesConstraint<'tcx>>, RegionVid)> {
1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815
        let mut context = IndexVec::from_elem(Trace::NotVisited, &self.definitions);
        context[from_region] = Trace::StartRegion;

        // Use a deque so that we do a breadth-first search. We will
        // stop at the first match, which ought to be the shortest
        // path (fewest constraints).
        let mut deque = VecDeque::new();
        deque.push_back(from_region);

        while let Some(r) = deque.pop_front() {
            debug!(
                "find_constraint_paths_between_regions: from_region={:?} r={:?} value={}",
                from_region,
                r,
                self.region_value_str(r),
            );

            // Check if we reached the region we were looking for. If so,
            // we can reconstruct the path that led to it and return it.
            if target_test(r) {
                let mut result = vec![];
                let mut p = r;
                loop {
1816
                    match context[p].clone() {
1817 1818 1819 1820 1821 1822
                        Trace::NotVisited => {
                            bug!("found unvisited region {:?} on path to {:?}", p, r)
                        }

                        Trace::FromOutlivesConstraint(c) => {
                            p = c.sup;
1823
                            result.push(c);
1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845
                        }

                        Trace::StartRegion => {
                            result.reverse();
                            return Some((result, r));
                        }
                    }
                }
            }

            // Otherwise, walk over the outgoing constraints and
            // enqueue any regions we find, keeping track of how we
            // reached them.

            // A constraint like `'r: 'x` can come from our constraint
            // graph.
            let fr_static = self.universal_regions.fr_static;
            let outgoing_edges_from_graph =
                self.constraint_graph.outgoing_edges(r, &self.constraints, fr_static);

            // Always inline this closure because it can be hot.
            let mut handle_constraint = #[inline(always)]
1846
            |constraint: OutlivesConstraint<'tcx>| {
1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869
                debug_assert_eq!(constraint.sup, r);
                let sub_region = constraint.sub;
                if let Trace::NotVisited = context[sub_region] {
                    context[sub_region] = Trace::FromOutlivesConstraint(constraint);
                    deque.push_back(sub_region);
                }
            };

            // This loop can be hot.
            for constraint in outgoing_edges_from_graph {
                handle_constraint(constraint);
            }

            // Member constraints can also give rise to `'r: 'x` edges that
            // were not part of the graph initially, so watch out for those.
            // (But they are extremely rare; this loop is very cold.)
            for constraint in self.applied_member_constraints(r) {
                let p_c = &self.member_constraints[constraint.member_constraint_index];
                let constraint = OutlivesConstraint {
                    sup: r,
                    sub: constraint.min_choice,
                    locations: Locations::All(p_c.definition_span),
                    category: ConstraintCategory::OpaqueType,
1870
                    variance_info: ty::VarianceDiagInfo::default(),
1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881
                };
                handle_constraint(constraint);
            }
        }

        None
    }

    /// Finds some region R such that `fr1: R` and `R` is live at `elem`.
    crate fn find_sub_region_live_at(&self, fr1: RegionVid, elem: Location) -> RegionVid {
        debug!("find_sub_region_live_at(fr1={:?}, elem={:?})", fr1, elem);
1882 1883 1884 1885 1886 1887
        debug!("find_sub_region_live_at: {:?} is in scc {:?}", fr1, self.constraint_sccs.scc(fr1));
        debug!(
            "find_sub_region_live_at: {:?} is in universe {:?}",
            fr1,
            self.scc_universes[self.constraint_sccs.scc(fr1)]
        );
1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908
        self.find_constraint_paths_between_regions(fr1, |r| {
            // First look for some `r` such that `fr1: r` and `r` is live at `elem`
            debug!(
                "find_sub_region_live_at: liveness_constraints for {:?} are {:?}",
                r,
                self.liveness_constraints.region_value_str(r),
            );
            self.liveness_constraints.contains(r, elem)
        })
        .or_else(|| {
            // If we fail to find that, we may find some `r` such that
            // `fr1: r` and `r` is a placeholder from some universe
            // `fr1` cannot name. This would force `fr1` to be
            // `'static`.
            self.find_constraint_paths_between_regions(fr1, |r| {
                self.cannot_name_placeholder(fr1, r)
            })
        })
        .or_else(|| {
            // If we fail to find THAT, it may be that `fr1` is a
            // placeholder that cannot "fit" into its SCC. In that
1909
            // case, there should be some `r` where `fr1: r` and `fr1` is a
1910 1911
            // placeholder that `r` cannot name. We can blame that
            // edge.
1912 1913 1914 1915 1916
            //
            // Remember that if `R1: R2`, then the universe of R1
            // must be able to name the universe of R2, because R2 will
            // be at least `'empty(Universe(R2))`, and `R1` must be at
            // larger than that.
1917
            self.find_constraint_paths_between_regions(fr1, |r| {
1918
                self.cannot_name_placeholder(r, fr1)
1919 1920 1921 1922 1923 1924
            })
        })
        .map(|(_path, r)| r)
        .unwrap()
    }

1925
    /// Get the region outlived by `longer_fr` and live at `element`.
1926 1927 1928 1929 1930 1931
    crate fn region_from_element(
        &self,
        longer_fr: RegionVid,
        element: &RegionElement,
    ) -> RegionVid {
        match *element {
1932 1933 1934 1935 1936
            RegionElement::Location(l) => self.find_sub_region_live_at(longer_fr, l),
            RegionElement::RootUniversalRegion(r) => r,
            RegionElement::PlaceholderRegion(error_placeholder) => self
                .definitions
                .iter_enumerated()
1937
                .find_map(|(r, definition)| match definition.origin {
1938
                    NllRegionVariableOrigin::Placeholder(p) if p == error_placeholder => Some(r),
1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955
                    _ => None,
                })
                .unwrap(),
        }
    }

    /// Get the region definition of `r`.
    crate fn region_definition(&self, r: RegionVid) -> &RegionDefinition<'tcx> {
        &self.definitions[r]
    }

    /// Check if the SCC of `r` contains `upper`.
    crate fn upper_bound_in_region_scc(&self, r: RegionVid, upper: RegionVid) -> bool {
        let r_scc = self.constraint_sccs.scc(r);
        self.scc_values.contains(r_scc, upper)
    }

M
Mark Mansi 已提交
1956 1957
    crate fn universal_regions(&self) -> &UniversalRegions<'tcx> {
        self.universal_regions.as_ref()
1958 1959
    }

1960 1961 1962 1963 1964 1965 1966 1967 1968 1969
    /// Tries to find the best constraint to blame for the fact that
    /// `R: from_region`, where `R` is some region that meets
    /// `target_test`. This works by following the constraint graph,
    /// creating a constraint path that forces `R` to outlive
    /// `from_region`, and then finding the best choices within that
    /// path to blame.
    crate fn best_blame_constraint(
        &self,
        body: &Body<'tcx>,
        from_region: RegionVid,
1970
        from_region_origin: NllRegionVariableOrigin,
1971
        target_test: impl Fn(RegionVid) -> bool,
1972
    ) -> BlameConstraint<'tcx> {
1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983
        debug!(
            "best_blame_constraint(from_region={:?}, from_region_origin={:?})",
            from_region, from_region_origin
        );

        // Find all paths
        let (path, target_region) =
            self.find_constraint_paths_between_regions(from_region, target_test).unwrap();
        debug!(
            "best_blame_constraint: path={:#?}",
            path.iter()
1984
                .map(|c| format!(
1985 1986 1987 1988 1989 1990 1991 1992 1993
                    "{:?} ({:?}: {:?})",
                    c,
                    self.constraint_sccs.scc(c.sup),
                    self.constraint_sccs.scc(c.sub),
                ))
                .collect::<Vec<_>>()
        );

        // Classify each of the constraints along the path.
1994
        let mut categorized_path: Vec<BlameConstraint<'tcx>> = path
1995 1996 1997 1998 1999
            .iter()
            .map(|constraint| {
                if constraint.category == ConstraintCategory::ClosureBounds {
                    self.retrieve_closure_constraint_info(body, &constraint)
                } else {
2000 2001 2002 2003 2004 2005
                    BlameConstraint {
                        category: constraint.category,
                        from_closure: false,
                        span: constraint.locations.span(body),
                        variance_info: constraint.variance_info.clone(),
                    }
2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068
                }
            })
            .collect();
        debug!("best_blame_constraint: categorized_path={:#?}", categorized_path);

        // To find the best span to cite, we first try to look for the
        // final constraint that is interesting and where the `sup` is
        // not unified with the ultimate target region. The reason
        // for this is that we have a chain of constraints that lead
        // from the source to the target region, something like:
        //
        //    '0: '1 ('0 is the source)
        //    '1: '2
        //    '2: '3
        //    '3: '4
        //    '4: '5
        //    '5: '6 ('6 is the target)
        //
        // Some of those regions are unified with `'6` (in the same
        // SCC).  We want to screen those out. After that point, the
        // "closest" constraint we have to the end is going to be the
        // most likely to be the point where the value escapes -- but
        // we still want to screen for an "interesting" point to
        // highlight (e.g., a call site or something).
        let target_scc = self.constraint_sccs.scc(target_region);
        let mut range = 0..path.len();

        // As noted above, when reporting an error, there is typically a chain of constraints
        // leading from some "source" region which must outlive some "target" region.
        // In most cases, we prefer to "blame" the constraints closer to the target --
        // but there is one exception. When constraints arise from higher-ranked subtyping,
        // we generally prefer to blame the source value,
        // as the "target" in this case tends to be some type annotation that the user gave.
        // Therefore, if we find that the region origin is some instantiation
        // of a higher-ranked region, we start our search from the "source" point
        // rather than the "target", and we also tweak a few other things.
        //
        // An example might be this bit of Rust code:
        //
        // ```rust
        // let x: fn(&'static ()) = |_| {};
        // let y: for<'a> fn(&'a ()) = x;
        // ```
        //
        // In MIR, this will be converted into a combination of assignments and type ascriptions.
        // In particular, the 'static is imposed through a type ascription:
        //
        // ```rust
        // x = ...;
        // AscribeUserType(x, fn(&'static ())
        // y = x;
        // ```
        //
        // We wind up ultimately with constraints like
        //
        // ```rust
        // !a: 'temp1 // from the `y = x` statement
        // 'temp1: 'temp2
        // 'temp2: 'static // from the AscribeUserType
        // ```
        //
        // and here we prefer to blame the source (the y = x statement).
        let blame_source = match from_region_origin {
2069 2070 2071 2072 2073
            NllRegionVariableOrigin::FreeRegion
            | NllRegionVariableOrigin::Existential { from_forall: false } => true,
            NllRegionVariableOrigin::RootEmptyRegion
            | NllRegionVariableOrigin::Placeholder(_)
            | NllRegionVariableOrigin::Existential { from_forall: true } => false,
2074 2075 2076
        };

        let find_region = |i: &usize| {
2077
            let constraint = &path[*i];
2078 2079 2080 2081

            let constraint_sup_scc = self.constraint_sccs.scc(constraint.sup);

            if blame_source {
2082
                match categorized_path[*i].category {
2083 2084 2085 2086 2087
                    ConstraintCategory::OpaqueType
                    | ConstraintCategory::Boring
                    | ConstraintCategory::BoringNoLocation
                    | ConstraintCategory::Internal => false,
                    ConstraintCategory::TypeAnnotation
2088
                    | ConstraintCategory::Return(_)
2089 2090 2091 2092
                    | ConstraintCategory::Yield => true,
                    _ => constraint_sup_scc != target_scc,
                }
            } else {
2093
                match categorized_path[*i].category {
2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112
                    ConstraintCategory::OpaqueType
                    | ConstraintCategory::Boring
                    | ConstraintCategory::BoringNoLocation
                    | ConstraintCategory::Internal => false,
                    _ => true,
                }
            }
        };

        let best_choice =
            if blame_source { range.rev().find(find_region) } else { range.find(find_region) };

        debug!(
            "best_blame_constraint: best_choice={:?} blame_source={}",
            best_choice, blame_source
        );

        if let Some(i) = best_choice {
            if let Some(next) = categorized_path.get(i + 1) {
2113 2114
                if matches!(categorized_path[i].category, ConstraintCategory::Return(_))
                    && next.category == ConstraintCategory::OpaqueType
2115 2116 2117
                {
                    // The return expression is being influenced by the return type being
                    // impl Trait, point at the return type and not the return expr.
2118
                    return next.clone();
2119 2120
                }
            }
2121

2122 2123
            if categorized_path[i].category == ConstraintCategory::Return(ReturnConstraint::Normal)
            {
2124
                let field = categorized_path.iter().find_map(|p| {
2125 2126 2127 2128 2129
                    if let ConstraintCategory::ClosureUpvar(f) = p.category {
                        Some(f)
                    } else {
                        None
                    }
2130 2131 2132
                });

                if let Some(field) = field {
2133
                    categorized_path[i].category =
2134 2135 2136 2137
                        ConstraintCategory::Return(ReturnConstraint::ClosureUpvar(field));
                }
            }

2138
            return categorized_path[i].clone();
2139 2140 2141 2142 2143 2144
        }

        // If that search fails, that is.. unusual. Maybe everything
        // is in the same SCC or something. In that case, find what
        // appears to be the most interesting point to report to the
        // user via an even more ad-hoc guess.
2145
        categorized_path.sort_by(|p0, p1| p0.category.cmp(&p1.category));
2146 2147
        debug!("`: sorted_path={:#?}", categorized_path);

2148
        categorized_path.remove(0)
2149
    }
2150 2151 2152 2153

    crate fn universe_info(&self, universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
        self.universe_causes[universe].clone()
    }
2154
}
2155 2156

impl<'tcx> RegionDefinition<'tcx> {
N
Niko Matsakis 已提交
2157
    fn new(universe: ty::UniverseIndex, rv_origin: RegionVariableOrigin) -> Self {
2158
        // Create a new region definition. Note that, for free
2159
        // regions, the `external_name` field gets updated later in
2160
        // `init_universal_regions`.
2161 2162

        let origin = match rv_origin {
2163 2164
            RegionVariableOrigin::Nll(origin) => origin,
            _ => NllRegionVariableOrigin::Existential { from_forall: false },
2165 2166
        };

2167
        Self { origin, universe, external_name: None }
2168 2169
    }
}
2170

2171
pub trait ClosureRegionRequirementsExt<'tcx> {
N
Niko Matsakis 已提交
2172
    fn apply_requirements(
2173
        &self,
2174
        tcx: TyCtxt<'tcx>,
2175
        closure_def_id: DefId,
C
csmoe 已提交
2176
        closure_substs: SubstsRef<'tcx>,
2177
    ) -> Vec<QueryOutlivesConstraint<'tcx>>;
2178 2179
}

2180
impl<'tcx> ClosureRegionRequirementsExt<'tcx> for ClosureRegionRequirements<'tcx> {
2181 2182 2183
    /// Given an instance T of the closure type, this method
    /// instantiates the "extra" requirements that we computed for the
    /// closure into the inference context. This has the effect of
P
Paul Daniel Faria 已提交
2184
    /// adding new outlives obligations to existing variables.
2185 2186 2187 2188 2189 2190 2191 2192
    ///
    /// As described on `ClosureRegionRequirements`, the extra
    /// requirements are expressed in terms of regionvids that index
    /// into the free regions that appear on the closure type. So, to
    /// do this, we first copy those regions out from the type T into
    /// a vector. Then we can just index into that vector to extract
    /// out the corresponding region from T and apply the
    /// requirements.
N
Niko Matsakis 已提交
2193
    fn apply_requirements(
2194
        &self,
2195
        tcx: TyCtxt<'tcx>,
2196
        closure_def_id: DefId,
C
csmoe 已提交
2197
        closure_substs: SubstsRef<'tcx>,
2198
    ) -> Vec<QueryOutlivesConstraint<'tcx>> {
2199
        debug!(
M
Matthew Jasper 已提交
2200 2201
            "apply_requirements(closure_def_id={:?}, closure_substs={:?})",
            closure_def_id, closure_substs
2202 2203
        );

M
Matthew Jasper 已提交
2204
        // Extract the values of the free regions in `closure_substs`
2205 2206
        // into a vector.  These are the regions that we will be
        // relating to one another.
M
Mikhail Modin 已提交
2207
        let closure_mapping = &UniversalRegions::closure_mapping(
N
Niko Matsakis 已提交
2208
            tcx,
M
Matthew Jasper 已提交
2209
            closure_substs,
N
Niko Matsakis 已提交
2210 2211 2212
            self.num_external_vids,
            tcx.closure_base_def_id(closure_def_id),
        );
2213 2214 2215
        debug!("apply_requirements: closure_mapping={:?}", closure_mapping);

        // Create the predicates.
2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231
        self.outlives_requirements
            .iter()
            .map(|outlives_requirement| {
                let outlived_region = closure_mapping[outlives_requirement.outlived_free_region];

                match outlives_requirement.subject {
                    ClosureOutlivesSubject::Region(region) => {
                        let region = closure_mapping[region];
                        debug!(
                            "apply_requirements: region={:?} \
                             outlived_region={:?} \
                             outlives_requirement={:?}",
                            region, outlived_region, outlives_requirement,
                        );
                        ty::Binder::dummy(ty::OutlivesPredicate(region.into(), outlived_region))
                    }
2232

2233 2234 2235 2236 2237 2238 2239 2240 2241
                    ClosureOutlivesSubject::Ty(ty) => {
                        debug!(
                            "apply_requirements: ty={:?} \
                             outlived_region={:?} \
                             outlives_requirement={:?}",
                            ty, outlived_region, outlives_requirement,
                        );
                        ty::Binder::dummy(ty::OutlivesPredicate(ty.into(), outlived_region))
                    }
2242
                }
2243 2244
            })
            .collect()
2245 2246
    }
}
2247 2248 2249 2250 2251 2252 2253 2254

#[derive(Clone, Debug)]
pub struct BlameConstraint<'tcx> {
    pub category: ConstraintCategory,
    pub from_closure: bool,
    pub span: Span,
    pub variance_info: ty::VarianceDiagInfo<'tcx>,
}