2019-02-08 14:53:55 +01:00
|
|
|
//! See `README.md`.
|
2012-08-13 15:06:13 -07:00
|
|
|
|
2017-11-05 05:23:30 -05:00
|
|
|
use self::CombineMapType::*;
|
2018-11-05 09:34:37 +11:00
|
|
|
use self::UndoLog::*;
|
2013-05-17 15:28:44 -07:00
|
|
|
|
2020-02-25 16:41:29 +01:00
|
|
|
use super::{
|
|
|
|
InferCtxtUndoLogs, MiscVariable, RegionVariableOrigin, Rollback, Snapshot, SubregionOrigin,
|
|
|
|
};
|
2014-11-25 16:59:02 -05:00
|
|
|
|
2023-01-27 17:22:05 +03:00
|
|
|
use rustc_data_structures::fx::FxHashMap;
|
2022-01-28 11:25:15 +11:00
|
|
|
use rustc_data_structures::intern::Interned;
|
2019-06-17 23:56:35 -04:00
|
|
|
use rustc_data_structures::sync::Lrc;
|
2020-02-25 09:47:07 +01:00
|
|
|
use rustc_data_structures::undo_log::UndoLogs;
|
2018-01-29 13:45:12 -07:00
|
|
|
use rustc_data_structures::unify as ut;
|
2023-04-19 10:57:17 +00:00
|
|
|
use rustc_index::IndexVec;
|
2021-05-14 21:48:32 -04:00
|
|
|
use rustc_middle::infer::unify_key::{RegionVidKey, UnifiedRegion};
|
2020-03-29 17:19:48 +02:00
|
|
|
use rustc_middle::ty::ReStatic;
|
|
|
|
use rustc_middle::ty::{self, Ty, TyCtxt};
|
2023-11-13 14:00:05 +00:00
|
|
|
use rustc_middle::ty::{ReBound, ReVar};
|
2020-03-29 17:19:48 +02:00
|
|
|
use rustc_middle::ty::{Region, RegionVid};
|
2019-12-31 20:15:40 +03:00
|
|
|
use rustc_span::Span;
|
2012-12-13 13:05:22 -08:00
|
|
|
|
2017-11-07 21:29:28 +00:00
|
|
|
use std::collections::BTreeMap;
|
2019-03-25 22:26:37 +00:00
|
|
|
use std::ops::Range;
|
2019-05-31 15:09:04 +09:00
|
|
|
use std::{cmp, fmt, mem};
|
2012-09-04 11:54:36 -07:00
|
|
|
|
2019-02-20 05:39:04 -05:00
|
|
|
mod leak_check;
|
|
|
|
|
2020-03-29 16:41:09 +02:00
|
|
|
pub use rustc_middle::infer::MemberConstraint;
|
2020-01-22 13:31:42 +01:00
|
|
|
|
2022-02-09 19:37:10 -03:00
|
|
|
#[derive(Clone, Default)]
|
2020-02-25 09:47:07 +01:00
|
|
|
pub struct RegionConstraintStorage<'tcx> {
|
2017-11-05 14:37:55 -05:00
|
|
|
/// For each `RegionVid`, the corresponding `RegionVariableOrigin`.
|
2018-02-07 11:47:57 -07:00
|
|
|
var_infos: IndexVec<RegionVid, RegionVariableInfo>,
|
2017-11-05 14:37:55 -05:00
|
|
|
|
2017-11-05 11:59:49 -05:00
|
|
|
data: RegionConstraintData<'tcx>,
|
2017-11-05 14:37:55 -05:00
|
|
|
|
|
|
|
/// For a given pair of regions (R1, R2), maps to a region R3 that
|
|
|
|
/// is designated as their LUB (edges R1 <= R3 and R2 <= R3
|
|
|
|
/// exist). This prevents us from making many such regions.
|
2017-11-05 11:59:49 -05:00
|
|
|
lubs: CombineMap<'tcx>,
|
2017-11-05 14:37:55 -05:00
|
|
|
|
|
|
|
/// For a given pair of regions (R1, R2), maps to a region R3 that
|
|
|
|
/// is designated as their GLB (edges R3 <= R1 and R3 <= R2
|
|
|
|
/// exist). This prevents us from making many such regions.
|
2017-11-05 11:59:49 -05:00
|
|
|
glbs: CombineMap<'tcx>,
|
2017-11-05 14:37:55 -05:00
|
|
|
|
2022-03-30 15:14:15 -04:00
|
|
|
/// When we add a R1 == R2 constraint, we currently add (a) edges
|
2017-11-05 14:37:55 -05:00
|
|
|
/// R1 <= R2 and R2 <= R1 and (b) we unify the two regions in this
|
2021-05-15 12:26:50 -04:00
|
|
|
/// table. You can then call `opportunistic_resolve_var` early
|
2017-11-05 14:37:55 -05:00
|
|
|
/// which will map R1 and R2 to some common region (i.e., either
|
2020-06-16 18:27:40 +01:00
|
|
|
/// R1 or R2). This is important when fulfillment, dropck and other such
|
|
|
|
/// code is iterating to a fixed point, because otherwise we sometimes
|
|
|
|
/// would wind up with a fresh stream of region variables that have been
|
|
|
|
/// equated but appear distinct.
|
2021-05-14 21:48:32 -04:00
|
|
|
pub(super) unification_table: ut::UnificationTableStorage<RegionVidKey<'tcx>>,
|
2018-06-09 11:04:18 -04:00
|
|
|
|
|
|
|
/// a flag set to true when we perform any unifications; this is used
|
|
|
|
/// to micro-optimize `take_and_reset_data`
|
|
|
|
any_unifications: bool,
|
2017-11-05 11:59:49 -05:00
|
|
|
}
|
|
|
|
|
2020-04-28 21:05:12 +02:00
|
|
|
pub struct RegionConstraintCollector<'a, 'tcx> {
|
2020-02-25 09:47:07 +01:00
|
|
|
storage: &'a mut RegionConstraintStorage<'tcx>,
|
2020-02-25 16:41:29 +01:00
|
|
|
undo_log: &'a mut InferCtxtUndoLogs<'tcx>,
|
2020-02-25 09:47:07 +01:00
|
|
|
}
|
|
|
|
|
2021-12-13 16:50:58 -05:00
|
|
|
impl<'tcx> std::ops::Deref for RegionConstraintCollector<'_, 'tcx> {
|
2020-02-25 09:47:07 +01:00
|
|
|
type Target = RegionConstraintStorage<'tcx>;
|
2020-05-24 15:22:23 +02:00
|
|
|
#[inline]
|
2020-02-25 09:47:07 +01:00
|
|
|
fn deref(&self) -> &RegionConstraintStorage<'tcx> {
|
|
|
|
self.storage
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-13 16:50:58 -05:00
|
|
|
impl<'tcx> std::ops::DerefMut for RegionConstraintCollector<'_, 'tcx> {
|
2020-05-24 15:22:23 +02:00
|
|
|
#[inline]
|
2020-02-25 09:47:07 +01:00
|
|
|
fn deref_mut(&mut self) -> &mut RegionConstraintStorage<'tcx> {
|
|
|
|
self.storage
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-07 11:47:57 -07:00
|
|
|
pub type VarInfos = IndexVec<RegionVid, RegionVariableInfo>;
|
2017-11-05 14:06:46 -05:00
|
|
|
|
2017-11-05 11:59:49 -05:00
|
|
|
/// The full set of region constraints gathered up by the collector.
|
2017-11-05 14:37:55 -05:00
|
|
|
/// Describes constraints between the region variables and other
|
|
|
|
/// regions, as well as other conditions that must be verified, or
|
|
|
|
/// assumptions that can be made.
|
Generate documentation for auto-trait impls
A new section is added to both both struct and trait doc pages.
On struct/enum pages, a new 'Auto Trait Implementations' section displays any
synthetic implementations for auto traits. Currently, this is only done
for Send and Sync.
On trait pages, a new 'Auto Implementors' section displays all types
which automatically implement the trait. Effectively, this is a list of
all public types in the standard library.
Synthesized impls for a particular auto trait ('synthetic impls') take
into account generic bounds. For example, a type 'struct Foo<T>(T)' will
have 'impl<T> Send for Foo<T> where T: Send' generated for it.
Manual implementations of auto traits are also taken into account. If we have
the following types:
'struct Foo<T>(T)'
'struct Wrapper<T>(Foo<T>)'
'unsafe impl<T> Send for Wrapper<T>' // pretend that Wrapper<T> makes
this sound somehow
Then Wrapper will have the following impl generated:
'impl<T> Send for Wrapper<T>'
reflecting the fact that 'T: Send' need not hold for 'Wrapper<T>: Send'
to hold
Lifetimes, HRTBS, and projections (e.g. '<T as Iterator>::Item') are
taken into account by synthetic impls
However, if a type can *never* implement a particular auto trait
(e.g. 'struct MyStruct<T>(*const T)'), then a negative impl will be
generated (in this case, 'impl<T> !Send for MyStruct<T>')
All of this means that a user should be able to copy-paste a synthetic
impl into their code, without any observable changes in behavior
(assuming the rest of the program remains unchanged).
2017-11-22 16:16:55 -05:00
|
|
|
#[derive(Debug, Default, Clone)]
|
2017-11-05 11:59:49 -05:00
|
|
|
pub struct RegionConstraintData<'tcx> {
|
|
|
|
/// Constraints of the form `A <= B`, where either `A` or `B` can
|
|
|
|
/// be a region variable (or neither, as it happens).
|
|
|
|
pub constraints: BTreeMap<Constraint<'tcx>, SubregionOrigin<'tcx>>,
|
|
|
|
|
2019-06-18 08:52:23 -04:00
|
|
|
/// Constraints of the form `R0 member of [R1, ..., Rn]`, meaning that
|
2019-05-30 10:36:35 -04:00
|
|
|
/// `R0` must be equal to one of the regions `R1..Rn`. These occur
|
|
|
|
/// with `impl Trait` quite frequently.
|
2019-06-18 08:52:23 -04:00
|
|
|
pub member_constraints: Vec<MemberConstraint<'tcx>>,
|
2019-05-30 10:36:35 -04:00
|
|
|
|
2017-11-05 11:59:49 -05:00
|
|
|
/// A "verify" is something that we need to verify after inference
|
|
|
|
/// is done, but which does not directly affect inference in any
|
|
|
|
/// way.
|
|
|
|
///
|
|
|
|
/// An example is a `A <= B` where neither `A` nor `B` are
|
|
|
|
/// inference variables.
|
|
|
|
pub verifys: Vec<Verify<'tcx>>,
|
|
|
|
}
|
|
|
|
|
2019-02-08 14:53:55 +01:00
|
|
|
/// Represents a constraint that influences the inference process.
|
2019-10-20 15:54:53 +11:00
|
|
|
#[derive(Clone, Copy, PartialEq, Eq, Debug, PartialOrd, Ord)]
|
2016-08-25 23:58:52 +03:00
|
|
|
pub enum Constraint<'tcx> {
|
2019-02-08 14:53:55 +01:00
|
|
|
/// A region variable is a subregion of another.
|
2017-11-05 05:23:30 -05:00
|
|
|
VarSubVar(RegionVid, RegionVid),
|
2014-08-27 21:46:52 -04:00
|
|
|
|
2019-02-08 14:53:55 +01:00
|
|
|
/// A concrete region is a subregion of region variable.
|
2017-11-05 05:23:30 -05:00
|
|
|
RegSubVar(Region<'tcx>, RegionVid),
|
2014-08-27 21:46:52 -04:00
|
|
|
|
2019-02-08 14:53:55 +01:00
|
|
|
/// A region variable is a subregion of a concrete region. This does not
|
2017-06-03 18:37:29 +02:00
|
|
|
/// directly affect inference, but instead is checked after
|
|
|
|
/// inference is complete.
|
2017-11-05 05:23:30 -05:00
|
|
|
VarSubReg(RegionVid, Region<'tcx>),
|
2016-05-21 08:11:54 -04:00
|
|
|
|
2017-06-03 18:37:29 +02:00
|
|
|
/// A constraint where neither side is a variable. This does not
|
|
|
|
/// directly affect inference, but instead is checked after
|
|
|
|
/// inference is complete.
|
2017-11-05 05:23:30 -05:00
|
|
|
RegSubReg(Region<'tcx>, Region<'tcx>),
|
2014-08-27 21:46:52 -04:00
|
|
|
}
|
|
|
|
|
2018-11-20 10:24:38 -05:00
|
|
|
impl Constraint<'_> {
|
|
|
|
pub fn involves_placeholders(&self) -> bool {
|
|
|
|
match self {
|
|
|
|
Constraint::VarSubVar(_, _) => false,
|
|
|
|
Constraint::VarSubReg(_, r) | Constraint::RegSubVar(r, _) => r.is_placeholder(),
|
|
|
|
Constraint::RegSubReg(r, s) => r.is_placeholder() || s.is_placeholder(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Generate documentation for auto-trait impls
A new section is added to both both struct and trait doc pages.
On struct/enum pages, a new 'Auto Trait Implementations' section displays any
synthetic implementations for auto traits. Currently, this is only done
for Send and Sync.
On trait pages, a new 'Auto Implementors' section displays all types
which automatically implement the trait. Effectively, this is a list of
all public types in the standard library.
Synthesized impls for a particular auto trait ('synthetic impls') take
into account generic bounds. For example, a type 'struct Foo<T>(T)' will
have 'impl<T> Send for Foo<T> where T: Send' generated for it.
Manual implementations of auto traits are also taken into account. If we have
the following types:
'struct Foo<T>(T)'
'struct Wrapper<T>(Foo<T>)'
'unsafe impl<T> Send for Wrapper<T>' // pretend that Wrapper<T> makes
this sound somehow
Then Wrapper will have the following impl generated:
'impl<T> Send for Wrapper<T>'
reflecting the fact that 'T: Send' need not hold for 'Wrapper<T>: Send'
to hold
Lifetimes, HRTBS, and projections (e.g. '<T as Iterator>::Item') are
taken into account by synthetic impls
However, if a type can *never* implement a particular auto trait
(e.g. 'struct MyStruct<T>(*const T)'), then a negative impl will be
generated (in this case, 'impl<T> !Send for MyStruct<T>')
All of this means that a user should be able to copy-paste a synthetic
impl into their code, without any observable changes in behavior
(assuming the rest of the program remains unchanged).
2017-11-22 16:16:55 -05:00
|
|
|
#[derive(Debug, Clone)]
|
2016-05-21 08:11:54 -04:00
|
|
|
pub struct Verify<'tcx> {
|
2017-11-05 05:05:31 -05:00
|
|
|
pub kind: GenericKind<'tcx>,
|
|
|
|
pub origin: SubregionOrigin<'tcx>,
|
|
|
|
pub region: Region<'tcx>,
|
|
|
|
pub bound: VerifyBound<'tcx>,
|
2015-01-03 04:40:33 -05:00
|
|
|
}
|
|
|
|
|
2022-06-17 10:53:29 +01:00
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)]
|
2015-01-03 04:40:33 -05:00
|
|
|
pub enum GenericKind<'tcx> {
|
|
|
|
Param(ty::ParamTy),
|
2023-01-15 19:38:31 +03:00
|
|
|
Alias(ty::AliasTy<'tcx>),
|
2012-08-13 15:06:13 -07:00
|
|
|
}
|
|
|
|
|
2019-02-08 14:53:55 +01:00
|
|
|
/// Describes the things that some `GenericKind` value `G` is known to
|
2018-09-19 12:52:17 -04:00
|
|
|
/// outlive. Each variant of `VerifyBound` can be thought of as a
|
|
|
|
/// function:
|
2022-04-15 15:04:34 -07:00
|
|
|
/// ```ignore (pseudo-rust)
|
|
|
|
/// fn(min: Region) -> bool { .. }
|
|
|
|
/// ```
|
2018-09-19 12:52:17 -04:00
|
|
|
/// where `true` means that the region `min` meets that `G: min`.
|
|
|
|
/// (False means nothing.)
|
|
|
|
///
|
|
|
|
/// So, for example, if we have the type `T` and we have in scope that
|
|
|
|
/// `T: 'a` and `T: 'b`, then the verify bound might be:
|
2022-04-15 15:04:34 -07:00
|
|
|
/// ```ignore (pseudo-rust)
|
|
|
|
/// fn(min: Region) -> bool {
|
|
|
|
/// ('a: min) || ('b: min)
|
|
|
|
/// }
|
|
|
|
/// ```
|
2021-08-22 14:46:15 +02:00
|
|
|
/// This is described with an `AnyRegion('a, 'b)` node.
|
2022-07-13 19:42:08 +02:00
|
|
|
#[derive(Debug, Clone, TypeFoldable, TypeVisitable)]
|
2016-08-25 23:58:52 +03:00
|
|
|
pub enum VerifyBound<'tcx> {
|
2022-06-23 16:38:24 -04:00
|
|
|
/// See [`VerifyIfEq`] docs
|
2022-06-23 16:35:47 -04:00
|
|
|
IfEq(ty::Binder<'tcx, VerifyIfEq<'tcx>>),
|
2022-06-15 05:55:05 -04:00
|
|
|
|
2018-09-19 15:58:47 -04:00
|
|
|
/// Given a region `R`, expands to the function:
|
2018-09-19 12:52:17 -04:00
|
|
|
///
|
2022-04-15 15:04:34 -07:00
|
|
|
/// ```ignore (pseudo-rust)
|
2019-02-08 14:53:55 +01:00
|
|
|
/// fn(min) -> bool {
|
|
|
|
/// R: min
|
|
|
|
/// }
|
|
|
|
/// ```
|
2018-09-19 12:52:17 -04:00
|
|
|
///
|
2018-09-19 15:58:47 -04:00
|
|
|
/// This is used when we can establish that `G: R` -- therefore,
|
|
|
|
/// if `R: min`, then by transitivity `G: min`.
|
|
|
|
OutlivedBy(Region<'tcx>),
|
2015-08-07 10:33:18 -04:00
|
|
|
|
2019-10-08 05:06:21 -04:00
|
|
|
/// Given a region `R`, true if it is `'empty`.
|
|
|
|
IsEmpty,
|
|
|
|
|
2018-09-19 12:52:17 -04:00
|
|
|
/// Given a set of bounds `B`, expands to the function:
|
|
|
|
///
|
2022-04-15 15:04:34 -07:00
|
|
|
/// ```ignore (pseudo-rust)
|
2019-02-08 14:53:55 +01:00
|
|
|
/// fn(min) -> bool {
|
|
|
|
/// exists (b in B) { b(min) }
|
|
|
|
/// }
|
|
|
|
/// ```
|
2018-09-19 15:58:47 -04:00
|
|
|
///
|
|
|
|
/// In other words, if we meet some bound in `B`, that suffices.
|
2019-02-08 14:53:55 +01:00
|
|
|
/// This is used when all the bounds in `B` are known to apply to `G`.
|
2016-08-25 23:58:52 +03:00
|
|
|
AnyBound(Vec<VerifyBound<'tcx>>),
|
2015-08-07 10:33:18 -04:00
|
|
|
|
2018-09-19 12:52:17 -04:00
|
|
|
/// Given a set of bounds `B`, expands to the function:
|
|
|
|
///
|
2022-04-15 15:04:34 -07:00
|
|
|
/// ```ignore (pseudo-rust)
|
2019-02-08 14:53:55 +01:00
|
|
|
/// fn(min) -> bool {
|
|
|
|
/// forall (b in B) { b(min) }
|
|
|
|
/// }
|
|
|
|
/// ```
|
2018-09-19 15:58:47 -04:00
|
|
|
///
|
|
|
|
/// In other words, if we meet *all* bounds in `B`, that suffices.
|
|
|
|
/// This is used when *some* bound in `B` is known to suffice, but
|
|
|
|
/// we don't know which.
|
2016-08-25 23:58:52 +03:00
|
|
|
AllBounds(Vec<VerifyBound<'tcx>>),
|
2015-08-07 10:33:18 -04:00
|
|
|
}
|
|
|
|
|
2022-06-23 16:38:24 -04:00
|
|
|
/// This is a "conditional bound" that checks the result of inference
|
|
|
|
/// and supplies a bound if it ended up being relevant. It's used in situations
|
|
|
|
/// like this:
|
2022-06-15 05:55:05 -04:00
|
|
|
///
|
2023-05-07 00:12:29 +03:00
|
|
|
/// ```rust,ignore (pseudo-Rust)
|
2022-06-23 16:38:24 -04:00
|
|
|
/// fn foo<'a, 'b, T: SomeTrait<'a>>
|
|
|
|
/// where
|
|
|
|
/// <T as SomeTrait<'a>>::Item: 'b
|
2022-06-15 05:55:05 -04:00
|
|
|
/// ```
|
|
|
|
///
|
2022-06-23 16:38:24 -04:00
|
|
|
/// If we have an obligation like `<T as SomeTrait<'?x>>::Item: 'c`, then
|
|
|
|
/// we don't know yet whether it suffices to show that `'b: 'c`. If `'?x` winds
|
|
|
|
/// up being equal to `'a`, then the where-clauses on function applies, and
|
|
|
|
/// in that case we can show `'b: 'c`. But if `'?x` winds up being something
|
|
|
|
/// else, the bound isn't relevant.
|
2022-06-15 05:55:05 -04:00
|
|
|
///
|
2023-03-03 04:10:46 +01:00
|
|
|
/// In the [`VerifyBound`], this struct is enclosed in `Binder` to account
|
2022-06-23 16:38:24 -04:00
|
|
|
/// for cases like
|
2022-06-15 05:55:05 -04:00
|
|
|
///
|
2023-05-07 00:12:29 +03:00
|
|
|
/// ```rust,ignore (pseudo-Rust)
|
2022-06-23 16:38:24 -04:00
|
|
|
/// where for<'a> <T as SomeTrait<'a>::Item: 'a
|
2022-06-15 05:55:05 -04:00
|
|
|
/// ```
|
|
|
|
///
|
2022-06-23 16:38:24 -04:00
|
|
|
/// The idea is that we have to find some instantiation of `'a` that can
|
|
|
|
/// make `<T as SomeTrait<'a>>::Item` equal to the final value of `G`,
|
|
|
|
/// the generic we are checking.
|
|
|
|
///
|
|
|
|
/// ```ignore (pseudo-rust)
|
|
|
|
/// fn(min) -> bool {
|
|
|
|
/// exists<'a> {
|
|
|
|
/// if G == K {
|
|
|
|
/// B(min)
|
|
|
|
/// } else {
|
|
|
|
/// false
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
/// ```
|
2022-06-17 10:53:29 +01:00
|
|
|
#[derive(Debug, Copy, Clone, TypeFoldable, TypeVisitable)]
|
2022-06-15 05:55:05 -04:00
|
|
|
pub struct VerifyIfEq<'tcx> {
|
|
|
|
/// Type which must match the generic `G`
|
|
|
|
pub ty: Ty<'tcx>,
|
|
|
|
|
|
|
|
/// Bound that applies if `ty` is equal.
|
|
|
|
pub bound: Region<'tcx>,
|
|
|
|
}
|
|
|
|
|
2015-03-30 09:38:44 -04:00
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
2020-02-25 09:47:07 +01:00
|
|
|
pub(crate) struct TwoRegions<'tcx> {
|
2017-04-20 04:45:53 -04:00
|
|
|
a: Region<'tcx>,
|
|
|
|
b: Region<'tcx>,
|
2012-08-13 15:06:13 -07:00
|
|
|
}
|
|
|
|
|
2015-03-30 09:38:44 -04:00
|
|
|
#[derive(Copy, Clone, PartialEq)]
|
2020-02-25 09:47:07 +01:00
|
|
|
pub(crate) enum UndoLog<'tcx> {
|
2019-02-08 14:53:55 +01:00
|
|
|
/// We added `RegionVid`.
|
2012-09-07 07:37:19 -07:00
|
|
|
AddVar(RegionVid),
|
2016-04-20 19:51:56 -04:00
|
|
|
|
2019-02-08 14:53:55 +01:00
|
|
|
/// We added the given `constraint`.
|
2016-08-25 23:58:52 +03:00
|
|
|
AddConstraint(Constraint<'tcx>),
|
2016-04-20 19:51:56 -04:00
|
|
|
|
2019-02-08 14:53:55 +01:00
|
|
|
/// We added the given `verify`.
|
2015-03-25 17:06:52 -07:00
|
|
|
AddVerify(usize),
|
2016-04-20 19:51:56 -04:00
|
|
|
|
2019-02-08 14:53:55 +01:00
|
|
|
/// We added a GLB/LUB "combination variable".
|
2016-08-25 23:58:52 +03:00
|
|
|
AddCombination(CombineMapType, TwoRegions<'tcx>),
|
2012-08-13 15:06:13 -07:00
|
|
|
}
|
|
|
|
|
2015-03-30 09:38:44 -04:00
|
|
|
#[derive(Copy, Clone, PartialEq)]
|
2020-02-25 09:47:07 +01:00
|
|
|
pub(crate) enum CombineMapType {
|
2015-10-31 11:31:52 +01:00
|
|
|
Lub,
|
|
|
|
Glb,
|
2013-03-22 22:26:41 -04:00
|
|
|
}
|
|
|
|
|
2017-11-05 05:23:30 -05:00
|
|
|
type CombineMap<'tcx> = FxHashMap<TwoRegions<'tcx>, RegionVid>;
|
2012-08-13 15:06:13 -07:00
|
|
|
|
2018-02-07 11:47:57 -07:00
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
|
|
pub struct RegionVariableInfo {
|
|
|
|
pub origin: RegionVariableOrigin,
|
2018-02-07 12:22:47 -07:00
|
|
|
pub universe: ty::UniverseIndex,
|
2018-02-07 11:47:57 -07:00
|
|
|
}
|
|
|
|
|
2014-06-20 06:35:06 -04:00
|
|
|
pub struct RegionSnapshot {
|
2018-06-09 11:04:18 -04:00
|
|
|
any_unifications: bool,
|
2014-06-20 06:35:06 -04:00
|
|
|
}
|
|
|
|
|
2020-02-25 09:47:07 +01:00
|
|
|
impl<'tcx> RegionConstraintStorage<'tcx> {
|
2018-07-25 15:44:06 +03:00
|
|
|
pub fn new() -> Self {
|
|
|
|
Self::default()
|
2012-08-13 15:06:13 -07:00
|
|
|
}
|
|
|
|
|
2020-05-24 15:22:23 +02:00
|
|
|
#[inline]
|
2020-02-25 09:47:07 +01:00
|
|
|
pub(crate) fn with_log<'a>(
|
|
|
|
&'a mut self,
|
2020-02-25 16:41:29 +01:00
|
|
|
undo_log: &'a mut InferCtxtUndoLogs<'tcx>,
|
2020-04-28 21:05:12 +02:00
|
|
|
) -> RegionConstraintCollector<'a, 'tcx> {
|
2020-02-25 09:47:07 +01:00
|
|
|
RegionConstraintCollector { storage: self, undo_log }
|
|
|
|
}
|
|
|
|
|
|
|
|
fn rollback_undo_entry(&mut self, undo_entry: UndoLog<'tcx>) {
|
|
|
|
match undo_entry {
|
|
|
|
AddVar(vid) => {
|
|
|
|
self.var_infos.pop().unwrap();
|
|
|
|
assert_eq!(self.var_infos.len(), vid.index() as usize);
|
|
|
|
}
|
|
|
|
AddConstraint(ref constraint) => {
|
|
|
|
self.data.constraints.remove(constraint);
|
|
|
|
}
|
|
|
|
AddVerify(index) => {
|
|
|
|
self.data.verifys.pop();
|
|
|
|
assert_eq!(self.data.verifys.len(), index);
|
|
|
|
}
|
|
|
|
AddCombination(Glb, ref regions) => {
|
|
|
|
self.glbs.remove(regions);
|
|
|
|
}
|
|
|
|
AddCombination(Lub, ref regions) => {
|
|
|
|
self.lubs.remove(regions);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-28 21:05:12 +02:00
|
|
|
impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
|
2018-02-07 11:47:57 -07:00
|
|
|
pub fn num_region_vars(&self) -> usize {
|
|
|
|
self.var_infos.len()
|
2017-11-06 04:29:50 -05:00
|
|
|
}
|
|
|
|
|
Generate documentation for auto-trait impls
A new section is added to both both struct and trait doc pages.
On struct/enum pages, a new 'Auto Trait Implementations' section displays any
synthetic implementations for auto traits. Currently, this is only done
for Send and Sync.
On trait pages, a new 'Auto Implementors' section displays all types
which automatically implement the trait. Effectively, this is a list of
all public types in the standard library.
Synthesized impls for a particular auto trait ('synthetic impls') take
into account generic bounds. For example, a type 'struct Foo<T>(T)' will
have 'impl<T> Send for Foo<T> where T: Send' generated for it.
Manual implementations of auto traits are also taken into account. If we have
the following types:
'struct Foo<T>(T)'
'struct Wrapper<T>(Foo<T>)'
'unsafe impl<T> Send for Wrapper<T>' // pretend that Wrapper<T> makes
this sound somehow
Then Wrapper will have the following impl generated:
'impl<T> Send for Wrapper<T>'
reflecting the fact that 'T: Send' need not hold for 'Wrapper<T>: Send'
to hold
Lifetimes, HRTBS, and projections (e.g. '<T as Iterator>::Item') are
taken into account by synthetic impls
However, if a type can *never* implement a particular auto trait
(e.g. 'struct MyStruct<T>(*const T)'), then a negative impl will be
generated (in this case, 'impl<T> !Send for MyStruct<T>')
All of this means that a user should be able to copy-paste a synthetic
impl into their code, without any observable changes in behavior
(assuming the rest of the program remains unchanged).
2017-11-22 16:16:55 -05:00
|
|
|
pub fn region_constraint_data(&self) -> &RegionConstraintData<'tcx> {
|
|
|
|
&self.data
|
|
|
|
}
|
|
|
|
|
2017-11-05 11:59:49 -05:00
|
|
|
/// Once all the constraints have been gathered, extract out the final data.
|
2017-11-05 14:42:56 -05:00
|
|
|
///
|
|
|
|
/// Not legal during a snapshot.
|
2018-02-07 11:47:57 -07:00
|
|
|
pub fn into_infos_and_data(self) -> (VarInfos, RegionConstraintData<'tcx>) {
|
2020-02-25 09:47:07 +01:00
|
|
|
assert!(!UndoLogs::<super::UndoLog<'_>>::in_snapshot(&self.undo_log));
|
|
|
|
(mem::take(&mut self.storage.var_infos), mem::take(&mut self.storage.data))
|
2017-11-05 11:59:49 -05:00
|
|
|
}
|
|
|
|
|
2017-11-14 17:17:53 -05:00
|
|
|
/// Takes (and clears) the current set of constraints. Note that
|
|
|
|
/// the set of variables remains intact, but all relationships
|
2019-02-08 14:53:55 +01:00
|
|
|
/// between them are reset. This is used during NLL checking to
|
2017-11-14 17:17:53 -05:00
|
|
|
/// grab the set of constraints that arose from a particular
|
|
|
|
/// operation.
|
|
|
|
///
|
|
|
|
/// We don't want to leak relationships between variables between
|
|
|
|
/// points because just because (say) `r1 == r2` was true at some
|
|
|
|
/// point P in the graph doesn't imply that it will be true at
|
|
|
|
/// some other point Q, in NLL.
|
2017-11-05 14:42:56 -05:00
|
|
|
///
|
|
|
|
/// Not legal during a snapshot.
|
|
|
|
pub fn take_and_reset_data(&mut self) -> RegionConstraintData<'tcx> {
|
2020-02-25 09:47:07 +01:00
|
|
|
assert!(!UndoLogs::<super::UndoLog<'_>>::in_snapshot(&self.undo_log));
|
2017-11-14 17:17:53 -05:00
|
|
|
|
|
|
|
// If you add a new field to `RegionConstraintCollector`, you
|
|
|
|
// should think carefully about whether it needs to be cleared
|
|
|
|
// or updated in some way.
|
2020-02-25 09:47:07 +01:00
|
|
|
let RegionConstraintStorage {
|
2018-05-18 15:25:34 -04:00
|
|
|
var_infos: _,
|
2017-11-14 17:17:53 -05:00
|
|
|
data,
|
|
|
|
lubs,
|
|
|
|
glbs,
|
2020-02-25 09:47:07 +01:00
|
|
|
unification_table: _,
|
2018-06-09 11:04:18 -04:00
|
|
|
any_unifications,
|
2020-02-25 09:47:07 +01:00
|
|
|
} = self.storage;
|
2017-11-14 17:17:53 -05:00
|
|
|
|
|
|
|
// Clear the tables of (lubs, glbs), so that we will create
|
|
|
|
// fresh regions if we do a LUB operation. As it happens,
|
|
|
|
// LUB/GLB are not performed by the MIR type-checker, which is
|
|
|
|
// the one that uses this method, but it's good to be correct.
|
|
|
|
lubs.clear();
|
|
|
|
glbs.clear();
|
|
|
|
|
2020-02-25 09:47:07 +01:00
|
|
|
let data = mem::take(data);
|
|
|
|
|
2017-11-14 17:17:53 -05:00
|
|
|
// Clear all unifications and recreate the variables a "now
|
|
|
|
// un-unified" state. Note that when we unify `a` and `b`, we
|
|
|
|
// also insert `a <= b` and a `b <= a` edges, so the
|
|
|
|
// `RegionConstraintData` contains the relationship here.
|
2018-06-09 11:04:18 -04:00
|
|
|
if *any_unifications {
|
|
|
|
*any_unifications = false;
|
2023-03-08 14:03:20 +03:00
|
|
|
self.unification_table_mut().reset_unifications(|_| UnifiedRegion::new(None));
|
2018-06-09 11:04:18 -04:00
|
|
|
}
|
2017-11-14 17:17:53 -05:00
|
|
|
|
2020-02-25 09:47:07 +01:00
|
|
|
data
|
2017-11-05 14:42:56 -05:00
|
|
|
}
|
|
|
|
|
2023-05-23 18:56:25 +02:00
|
|
|
pub fn data(&self) -> &RegionConstraintData<'tcx> {
|
2018-02-25 10:58:54 -05:00
|
|
|
&self.data
|
|
|
|
}
|
|
|
|
|
2022-06-26 18:57:46 -04:00
|
|
|
pub(super) fn start_snapshot(&mut self) -> RegionSnapshot {
|
2020-02-25 09:47:07 +01:00
|
|
|
debug!("RegionConstraintCollector: start_snapshot");
|
2020-04-28 20:59:34 +02:00
|
|
|
RegionSnapshot { any_unifications: self.any_unifications }
|
2014-06-20 06:35:06 -04:00
|
|
|
}
|
|
|
|
|
2022-06-26 18:57:46 -04:00
|
|
|
pub(super) fn rollback_to(&mut self, snapshot: RegionSnapshot) {
|
2017-11-05 07:01:48 -05:00
|
|
|
debug!("RegionConstraintCollector: rollback_to({:?})", snapshot);
|
2018-06-09 11:04:18 -04:00
|
|
|
self.any_unifications = snapshot.any_unifications;
|
2012-08-13 15:06:13 -07:00
|
|
|
}
|
|
|
|
|
2022-06-26 18:57:46 -04:00
|
|
|
pub(super) fn new_region_var(
|
2018-09-07 16:58:35 -04:00
|
|
|
&mut self,
|
|
|
|
universe: ty::UniverseIndex,
|
|
|
|
origin: RegionVariableOrigin,
|
|
|
|
) -> RegionVid {
|
|
|
|
let vid = self.var_infos.push(RegionVariableInfo { origin, universe });
|
2015-12-12 19:02:33 +02:00
|
|
|
|
2023-03-08 14:03:20 +03:00
|
|
|
let u_vid = self.unification_table_mut().new_key(UnifiedRegion::new(None));
|
2021-05-14 21:48:32 -04:00
|
|
|
assert_eq!(vid, u_vid.vid);
|
2020-02-25 09:47:07 +01:00
|
|
|
self.undo_log.push(AddVar(vid));
|
2019-02-01 10:34:42 -05:00
|
|
|
debug!("created new region variable {:?} in {:?} with origin {:?}", vid, universe, origin);
|
2020-03-20 15:03:11 +01:00
|
|
|
vid
|
2012-08-13 15:06:13 -07:00
|
|
|
}
|
|
|
|
|
2018-02-07 12:22:47 -07:00
|
|
|
/// Returns the universe for the given variable.
|
2022-06-26 18:57:46 -04:00
|
|
|
pub(super) fn var_universe(&self, vid: RegionVid) -> ty::UniverseIndex {
|
2018-02-07 12:22:47 -07:00
|
|
|
self.var_infos[vid].universe
|
|
|
|
}
|
|
|
|
|
2021-06-07 20:25:19 +01:00
|
|
|
/// Returns the origin for the given variable.
|
2022-06-26 18:57:46 -04:00
|
|
|
pub(super) fn var_origin(&self, vid: RegionVid) -> RegionVariableOrigin {
|
2021-06-07 20:25:19 +01:00
|
|
|
self.var_infos[vid].origin
|
|
|
|
}
|
|
|
|
|
2017-11-05 06:25:23 -05:00
|
|
|
fn add_constraint(&mut self, constraint: Constraint<'tcx>, origin: SubregionOrigin<'tcx>) {
|
2012-08-13 15:06:13 -07:00
|
|
|
// cannot add constraints once regions are resolved
|
2017-11-05 11:59:49 -05:00
|
|
|
debug!("RegionConstraintCollector: add_constraint({:?})", constraint);
|
2012-08-13 15:06:13 -07:00
|
|
|
|
2017-11-09 09:56:14 -05:00
|
|
|
// never overwrite an existing (constraint, origin) - only insert one if it isn't
|
|
|
|
// present in the map yet. This prevents origins from outside the snapshot being
|
2018-11-27 02:59:49 +00:00
|
|
|
// replaced with "less informative" origins e.g., during calls to `can_eq`
|
2017-11-05 06:25:23 -05:00
|
|
|
let undo_log = &mut self.undo_log;
|
2020-02-25 09:47:07 +01:00
|
|
|
self.storage.data.constraints.entry(constraint).or_insert_with(|| {
|
|
|
|
undo_log.push(AddConstraint(constraint));
|
2017-11-05 11:59:49 -05:00
|
|
|
origin
|
|
|
|
});
|
2012-08-13 15:06:13 -07:00
|
|
|
}
|
|
|
|
|
2017-11-05 06:25:23 -05:00
|
|
|
fn add_verify(&mut self, verify: Verify<'tcx>) {
|
2014-08-27 21:46:52 -04:00
|
|
|
// cannot add verifys once regions are resolved
|
2017-11-05 07:01:48 -05:00
|
|
|
debug!("RegionConstraintCollector: add_verify({:?})", verify);
|
2014-08-27 21:46:52 -04:00
|
|
|
|
2015-08-07 10:33:18 -04:00
|
|
|
// skip no-op cases known to be satisfied
|
2022-03-02 16:02:37 -03:00
|
|
|
if let VerifyBound::AllBounds(ref bs) = verify.bound
|
|
|
|
&& bs.is_empty()
|
|
|
|
{
|
|
|
|
return;
|
2015-08-07 10:33:18 -04:00
|
|
|
}
|
|
|
|
|
2017-11-05 11:59:49 -05:00
|
|
|
let index = self.data.verifys.len();
|
|
|
|
self.data.verifys.push(verify);
|
2020-02-25 09:47:07 +01:00
|
|
|
self.undo_log.push(AddVerify(index));
|
2014-08-27 21:46:52 -04:00
|
|
|
}
|
|
|
|
|
2022-06-26 18:57:46 -04:00
|
|
|
pub(super) fn make_eqregion(
|
2017-11-05 06:25:23 -05:00
|
|
|
&mut self,
|
2017-11-05 05:52:59 -05:00
|
|
|
origin: SubregionOrigin<'tcx>,
|
|
|
|
sub: Region<'tcx>,
|
|
|
|
sup: Region<'tcx>,
|
|
|
|
) {
|
2014-07-22 07:46:36 -04:00
|
|
|
if sub != sup {
|
|
|
|
// Eventually, it would be nice to add direct support for
|
|
|
|
// equating regions.
|
|
|
|
self.make_subregion(origin.clone(), sub, sup);
|
|
|
|
self.make_subregion(origin, sup, sub);
|
2015-12-06 20:21:23 +02:00
|
|
|
|
2021-05-14 21:48:32 -04:00
|
|
|
match (sub, sup) {
|
2022-01-28 11:25:15 +11:00
|
|
|
(Region(Interned(ReVar(sub), _)), Region(Interned(ReVar(sup), _))) => {
|
2021-05-14 21:48:32 -04:00
|
|
|
debug!("make_eqregion: unifying {:?} with {:?}", sub, sup);
|
2023-02-17 09:27:43 +03:00
|
|
|
self.unification_table_mut().union(*sub, *sup);
|
2021-05-14 21:48:32 -04:00
|
|
|
self.any_unifications = true;
|
|
|
|
}
|
2022-01-28 11:25:15 +11:00
|
|
|
(Region(Interned(ReVar(vid), _)), value)
|
|
|
|
| (value, Region(Interned(ReVar(vid), _))) => {
|
2021-05-14 21:48:32 -04:00
|
|
|
debug!("make_eqregion: unifying {:?} with {:?}", vid, value);
|
2023-03-08 14:03:20 +03:00
|
|
|
self.unification_table_mut().union_value(*vid, UnifiedRegion::new(Some(value)));
|
2021-05-14 21:48:32 -04:00
|
|
|
self.any_unifications = true;
|
|
|
|
}
|
|
|
|
(_, _) => {}
|
2015-12-06 20:21:23 +02:00
|
|
|
}
|
2014-07-22 07:46:36 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-26 18:57:46 -04:00
|
|
|
pub(super) fn member_constraint(
|
2019-05-30 10:36:35 -04:00
|
|
|
&mut self,
|
2022-07-26 06:19:58 +00:00
|
|
|
key: ty::OpaqueTypeKey<'tcx>,
|
2019-06-17 08:40:50 -04:00
|
|
|
definition_span: Span,
|
2019-06-03 16:31:44 -04:00
|
|
|
hidden_ty: Ty<'tcx>,
|
2019-06-18 08:52:23 -04:00
|
|
|
member_region: ty::Region<'tcx>,
|
|
|
|
choice_regions: &Lrc<Vec<ty::Region<'tcx>>>,
|
2019-05-30 10:36:35 -04:00
|
|
|
) {
|
2019-06-18 08:52:23 -04:00
|
|
|
debug!("member_constraint({:?} in {:#?})", member_region, choice_regions);
|
2019-05-30 10:36:35 -04:00
|
|
|
|
2019-06-18 08:52:23 -04:00
|
|
|
if choice_regions.iter().any(|&r| r == member_region) {
|
2019-05-30 10:36:35 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-06-18 08:52:23 -04:00
|
|
|
self.data.member_constraints.push(MemberConstraint {
|
2022-07-26 06:19:58 +00:00
|
|
|
key,
|
2019-06-17 08:40:50 -04:00
|
|
|
definition_span,
|
2019-06-03 16:31:44 -04:00
|
|
|
hidden_ty,
|
2019-06-18 08:52:23 -04:00
|
|
|
member_region,
|
|
|
|
choice_regions: choice_regions.clone(),
|
2019-05-30 10:36:35 -04:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-08-20 13:36:04 +00:00
|
|
|
#[instrument(skip(self, origin), level = "debug")]
|
2022-06-26 18:57:46 -04:00
|
|
|
pub(super) fn make_subregion(
|
2017-11-05 06:25:23 -05:00
|
|
|
&mut self,
|
2017-11-05 05:52:59 -05:00
|
|
|
origin: SubregionOrigin<'tcx>,
|
|
|
|
sub: Region<'tcx>,
|
|
|
|
sup: Region<'tcx>,
|
|
|
|
) {
|
2012-08-13 15:06:13 -07:00
|
|
|
// cannot add constraints once regions are resolved
|
2021-08-20 13:36:04 +00:00
|
|
|
debug!("origin = {:#?}", origin);
|
2014-02-07 14:43:48 -05:00
|
|
|
|
2022-01-28 11:25:15 +11:00
|
|
|
match (*sub, *sup) {
|
2023-11-13 14:00:05 +00:00
|
|
|
(ReBound(..), _) | (_, ReBound(..)) => {
|
2017-11-05 05:52:59 -05:00
|
|
|
span_bug!(origin.span(), "cannot relate bound region: {:?} <= {:?}", sub, sup);
|
2015-10-31 11:31:52 +01:00
|
|
|
}
|
2022-01-28 11:25:15 +11:00
|
|
|
(_, ReStatic) => {
|
2015-10-31 11:31:52 +01:00
|
|
|
// all regions are subregions of static, so we can ignore this
|
|
|
|
}
|
2022-01-28 11:25:15 +11:00
|
|
|
(ReVar(sub_id), ReVar(sup_id)) => {
|
2017-11-05 05:23:30 -05:00
|
|
|
self.add_constraint(Constraint::VarSubVar(sub_id, sup_id), origin);
|
2015-10-31 11:31:52 +01:00
|
|
|
}
|
2022-01-28 11:25:15 +11:00
|
|
|
(_, ReVar(sup_id)) => {
|
2017-11-05 05:23:30 -05:00
|
|
|
self.add_constraint(Constraint::RegSubVar(sub, sup_id), origin);
|
2015-10-31 11:31:52 +01:00
|
|
|
}
|
2022-01-28 11:25:15 +11:00
|
|
|
(ReVar(sub_id), _) => {
|
2017-11-05 05:23:30 -05:00
|
|
|
self.add_constraint(Constraint::VarSubReg(sub_id, sup), origin);
|
2015-10-31 11:31:52 +01:00
|
|
|
}
|
|
|
|
_ => {
|
2017-11-05 05:23:30 -05:00
|
|
|
self.add_constraint(Constraint::RegSubReg(sub, sup), origin);
|
2015-10-31 11:31:52 +01:00
|
|
|
}
|
2012-08-13 15:06:13 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-26 18:57:46 -04:00
|
|
|
pub(super) fn verify_generic_bound(
|
2017-11-05 06:25:23 -05:00
|
|
|
&mut self,
|
2017-11-05 05:52:59 -05:00
|
|
|
origin: SubregionOrigin<'tcx>,
|
|
|
|
kind: GenericKind<'tcx>,
|
|
|
|
sub: Region<'tcx>,
|
|
|
|
bound: VerifyBound<'tcx>,
|
|
|
|
) {
|
2016-05-21 08:11:54 -04:00
|
|
|
self.add_verify(Verify { kind, origin, region: sub, bound });
|
2014-08-27 21:46:52 -04:00
|
|
|
}
|
|
|
|
|
2022-06-26 18:57:46 -04:00
|
|
|
pub(super) fn lub_regions(
|
2017-11-05 06:25:23 -05:00
|
|
|
&mut self,
|
2019-06-14 00:48:52 +03:00
|
|
|
tcx: TyCtxt<'tcx>,
|
2017-11-05 05:52:59 -05:00
|
|
|
origin: SubregionOrigin<'tcx>,
|
|
|
|
a: Region<'tcx>,
|
|
|
|
b: Region<'tcx>,
|
|
|
|
) -> Region<'tcx> {
|
2012-08-13 15:06:13 -07:00
|
|
|
// cannot add constraints once regions are resolved
|
2017-11-05 07:01:48 -05:00
|
|
|
debug!("RegionConstraintCollector: lub_regions({:?}, {:?})", a, b);
|
2022-01-28 11:25:15 +11:00
|
|
|
if a.is_static() || b.is_static() {
|
|
|
|
a // nothing lives longer than static
|
|
|
|
} else if a == b {
|
|
|
|
a // LUB(a,a) = a
|
|
|
|
} else {
|
|
|
|
self.combine_vars(tcx, Lub, a, b, origin)
|
2012-08-13 15:06:13 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-26 18:57:46 -04:00
|
|
|
pub(super) fn glb_regions(
|
2017-11-05 06:25:23 -05:00
|
|
|
&mut self,
|
2019-06-14 00:48:52 +03:00
|
|
|
tcx: TyCtxt<'tcx>,
|
2017-11-05 05:52:59 -05:00
|
|
|
origin: SubregionOrigin<'tcx>,
|
|
|
|
a: Region<'tcx>,
|
|
|
|
b: Region<'tcx>,
|
|
|
|
) -> Region<'tcx> {
|
2012-08-13 15:06:13 -07:00
|
|
|
// cannot add constraints once regions are resolved
|
2017-11-05 07:01:48 -05:00
|
|
|
debug!("RegionConstraintCollector: glb_regions({:?}, {:?})", a, b);
|
2022-01-28 11:25:15 +11:00
|
|
|
if a.is_static() {
|
|
|
|
b // static lives longer than everything else
|
|
|
|
} else if b.is_static() {
|
|
|
|
a // static lives longer than everything else
|
|
|
|
} else if a == b {
|
|
|
|
a // GLB(a,a) = a
|
|
|
|
} else {
|
|
|
|
self.combine_vars(tcx, Glb, a, b, origin)
|
2012-08-13 15:06:13 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-16 14:40:53 +03:00
|
|
|
/// Resolves a region var to its value in the unification table, if it exists.
|
|
|
|
/// Otherwise, it is resolved to the root `ReVar` in the table.
|
|
|
|
pub fn opportunistic_resolve_var(
|
2021-05-14 21:48:32 -04:00
|
|
|
&mut self,
|
|
|
|
tcx: TyCtxt<'tcx>,
|
2023-02-16 14:40:53 +03:00
|
|
|
vid: ty::RegionVid,
|
2021-05-14 21:48:32 -04:00
|
|
|
) -> ty::Region<'tcx> {
|
2023-02-17 09:27:43 +03:00
|
|
|
let mut ut = self.unification_table_mut(); // FIXME(rust-lang/ena#42): unnecessary mut
|
|
|
|
let root_vid = ut.find(vid).vid;
|
2023-03-08 14:03:20 +03:00
|
|
|
let resolved = ut
|
|
|
|
.probe_value(root_vid)
|
|
|
|
.get_value_ignoring_universes()
|
2023-05-29 17:54:53 +00:00
|
|
|
.unwrap_or_else(|| ty::Region::new_var(tcx, root_vid));
|
2023-03-05 11:54:57 +03:00
|
|
|
|
|
|
|
// Don't resolve a variable to a region that it cannot name.
|
|
|
|
if self.var_universe(vid).can_name(self.universe(resolved)) {
|
|
|
|
resolved
|
|
|
|
} else {
|
2023-05-29 17:54:53 +00:00
|
|
|
ty::Region::new_var(tcx, vid)
|
2021-05-14 21:48:32 -04:00
|
|
|
}
|
2015-12-06 20:21:23 +02:00
|
|
|
}
|
|
|
|
|
2017-11-05 06:25:23 -05:00
|
|
|
fn combine_map(&mut self, t: CombineMapType) -> &mut CombineMap<'tcx> {
|
2013-05-23 21:37:37 -04:00
|
|
|
match t {
|
2017-11-05 06:25:23 -05:00
|
|
|
Glb => &mut self.glbs,
|
|
|
|
Lub => &mut self.lubs,
|
2013-05-23 21:37:37 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-05 06:07:22 -05:00
|
|
|
fn combine_vars(
|
2017-11-05 06:25:23 -05:00
|
|
|
&mut self,
|
2019-06-14 00:48:52 +03:00
|
|
|
tcx: TyCtxt<'tcx>,
|
2017-11-05 05:52:59 -05:00
|
|
|
t: CombineMapType,
|
|
|
|
a: Region<'tcx>,
|
|
|
|
b: Region<'tcx>,
|
|
|
|
origin: SubregionOrigin<'tcx>,
|
2017-11-05 06:07:22 -05:00
|
|
|
) -> Region<'tcx> {
|
2020-03-06 19:28:44 +01:00
|
|
|
let vars = TwoRegions { a, b };
|
2017-11-05 06:25:23 -05:00
|
|
|
if let Some(&c) = self.combine_map(t).get(&vars) {
|
2023-05-29 17:54:53 +00:00
|
|
|
return ty::Region::new_var(tcx, c);
|
2013-03-22 22:26:41 -04:00
|
|
|
}
|
2018-02-07 12:22:47 -07:00
|
|
|
let a_universe = self.universe(a);
|
|
|
|
let b_universe = self.universe(b);
|
|
|
|
let c_universe = cmp::max(a_universe, b_universe);
|
|
|
|
let c = self.new_region_var(c_universe, MiscVariable(origin.span()));
|
2017-11-05 06:25:23 -05:00
|
|
|
self.combine_map(t).insert(vars, c);
|
2020-02-25 09:47:07 +01:00
|
|
|
self.undo_log.push(AddCombination(t, vars));
|
2023-05-29 17:54:53 +00:00
|
|
|
let new_r = ty::Region::new_var(tcx, c);
|
2021-06-14 23:40:09 +02:00
|
|
|
for old_r in [a, b] {
|
2017-11-05 06:07:22 -05:00
|
|
|
match t {
|
|
|
|
Glb => self.make_subregion(origin.clone(), new_r, old_r),
|
|
|
|
Lub => self.make_subregion(origin.clone(), old_r, new_r),
|
|
|
|
}
|
|
|
|
}
|
2014-12-20 00:09:35 -08:00
|
|
|
debug!("combine_vars() c={:?}", c);
|
2017-11-05 06:07:22 -05:00
|
|
|
new_r
|
2012-08-13 15:06:13 -07:00
|
|
|
}
|
|
|
|
|
make generalization code create new variables in correct universe
In our type inference system, when we "generalize" a type T to become
a suitable value for a type variable V, we sometimes wind up creating
new inference variables. So, for example, if we are making V be some
subtype of `&'X u32`, then we might instantiate V with `&'Y u32`.
This generalized type is then related `&'Y u32 <: &'X u32`, resulting
in a region constriant `'Y: 'X`. Previously, however, we were making
these fresh variables like `'Y` in the "current universe", but they
should be created in the universe of V. Moreover, we sometimes cheat
in an invariant context and avoid creating fresh variables if we know
the result must be equal -- we can only do that when the universes
work out.
2019-02-01 10:41:08 -05:00
|
|
|
pub fn universe(&self, region: Region<'tcx>) -> ty::UniverseIndex {
|
2018-02-07 12:22:47 -07:00
|
|
|
match *region {
|
2023-02-07 14:55:16 +00:00
|
|
|
ty::ReStatic
|
|
|
|
| ty::ReErased
|
2023-11-14 13:13:27 +00:00
|
|
|
| ty::ReLateParam(..)
|
|
|
|
| ty::ReEarlyParam(..)
|
2023-02-07 14:55:16 +00:00
|
|
|
| ty::ReError(_) => ty::UniverseIndex::ROOT,
|
2018-09-27 17:57:35 -04:00
|
|
|
ty::RePlaceholder(placeholder) => placeholder.universe,
|
2020-03-11 22:24:20 +00:00
|
|
|
ty::ReVar(vid) => self.var_universe(vid),
|
2023-11-13 14:00:05 +00:00
|
|
|
ty::ReBound(..) => bug!("universe(): encountered bound region {:?}", region),
|
2018-02-07 12:22:47 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-25 21:28:39 +00:00
|
|
|
pub fn vars_since_snapshot(
|
|
|
|
&self,
|
2020-04-28 20:59:34 +02:00
|
|
|
value_count: usize,
|
2019-03-25 22:26:37 +00:00
|
|
|
) -> (Range<RegionVid>, Vec<RegionVariableOrigin>) {
|
2021-05-15 12:10:56 -04:00
|
|
|
let range = RegionVid::from(value_count)..RegionVid::from(self.unification_table.len());
|
2019-03-25 22:26:37 +00:00
|
|
|
(
|
|
|
|
range.clone(),
|
|
|
|
(range.start.index()..range.end.index())
|
2020-01-22 16:30:15 +01:00
|
|
|
.map(|index| self.var_infos[ty::RegionVid::from(index)].origin)
|
2019-03-25 22:26:37 +00:00
|
|
|
.collect(),
|
|
|
|
)
|
2012-11-01 15:16:46 -07:00
|
|
|
}
|
|
|
|
|
2020-05-14 00:08:00 +02:00
|
|
|
/// See `InferCtxt::region_constraints_added_in_snapshot`.
|
2023-05-23 18:56:25 +02:00
|
|
|
pub fn region_constraints_added_in_snapshot(&self, mark: &Snapshot<'tcx>) -> bool {
|
2020-02-25 09:47:07 +01:00
|
|
|
self.undo_log
|
2020-02-25 17:09:01 +01:00
|
|
|
.region_constraints_in_snapshot(mark)
|
2023-05-23 18:56:25 +02:00
|
|
|
.any(|&elt| matches!(elt, AddConstraint(_)))
|
2018-10-16 05:42:18 -04:00
|
|
|
}
|
2020-02-25 09:47:07 +01:00
|
|
|
|
2020-05-24 15:22:23 +02:00
|
|
|
#[inline]
|
2023-02-17 09:27:43 +03:00
|
|
|
fn unification_table_mut(&mut self) -> super::UnificationTable<'_, 'tcx, RegionVidKey<'tcx>> {
|
2020-02-25 09:47:07 +01:00
|
|
|
ut::UnificationTable::with_log(&mut self.storage.unification_table, self.undo_log)
|
|
|
|
}
|
2014-08-27 21:46:52 -04:00
|
|
|
}
|
2015-01-03 04:40:33 -05:00
|
|
|
|
2015-12-06 20:21:23 +02:00
|
|
|
impl fmt::Debug for RegionSnapshot {
|
2018-08-29 22:02:42 -07:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2020-02-25 09:47:07 +01:00
|
|
|
write!(f, "RegionSnapshot")
|
2015-12-06 20:21:23 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-18 08:51:23 +03:00
|
|
|
impl<'tcx> fmt::Debug for GenericKind<'tcx> {
|
2018-08-29 22:02:42 -07:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2015-01-03 04:40:33 -05:00
|
|
|
match *self {
|
2023-07-25 23:04:01 +02:00
|
|
|
GenericKind::Param(ref p) => write!(f, "{p:?}"),
|
|
|
|
GenericKind::Alias(ref p) => write!(f, "{p:?}"),
|
2015-01-03 04:40:33 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-18 08:51:23 +03:00
|
|
|
impl<'tcx> fmt::Display for GenericKind<'tcx> {
|
2018-08-29 22:02:42 -07:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2015-01-03 04:40:33 -05:00
|
|
|
match *self {
|
2023-07-25 23:04:01 +02:00
|
|
|
GenericKind::Param(ref p) => write!(f, "{p}"),
|
|
|
|
GenericKind::Alias(ref p) => write!(f, "{p}"),
|
2015-01-03 04:40:33 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-14 00:48:52 +03:00
|
|
|
impl<'tcx> GenericKind<'tcx> {
|
|
|
|
pub fn to_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
|
2015-01-03 04:40:33 -05:00
|
|
|
match *self {
|
2015-10-31 11:31:52 +01:00
|
|
|
GenericKind::Param(ref p) => p.to_ty(tcx),
|
2023-01-15 19:38:31 +03:00
|
|
|
GenericKind::Alias(ref p) => p.to_ty(tcx),
|
2015-01-03 04:40:33 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-08-07 10:33:18 -04:00
|
|
|
|
2019-06-11 12:21:38 +03:00
|
|
|
impl<'tcx> VerifyBound<'tcx> {
|
2015-08-07 10:33:18 -04:00
|
|
|
pub fn must_hold(&self) -> bool {
|
|
|
|
match self {
|
2022-06-23 16:35:47 -04:00
|
|
|
VerifyBound::IfEq(..) => false,
|
2022-01-28 11:25:15 +11:00
|
|
|
VerifyBound::OutlivedBy(re) => re.is_static(),
|
2019-10-08 05:06:21 -04:00
|
|
|
VerifyBound::IsEmpty => false,
|
2018-09-19 12:52:17 -04:00
|
|
|
VerifyBound::AnyBound(bs) => bs.iter().any(|b| b.must_hold()),
|
|
|
|
VerifyBound::AllBounds(bs) => bs.iter().all(|b| b.must_hold()),
|
2015-08-07 10:33:18 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn cannot_hold(&self) -> bool {
|
|
|
|
match self {
|
2022-06-23 16:35:47 -04:00
|
|
|
VerifyBound::IfEq(..) => false,
|
2019-10-08 05:06:21 -04:00
|
|
|
VerifyBound::IsEmpty => false,
|
2018-09-19 15:58:47 -04:00
|
|
|
VerifyBound::OutlivedBy(_) => false,
|
2018-09-19 12:52:17 -04:00
|
|
|
VerifyBound::AnyBound(bs) => bs.iter().all(|b| b.cannot_hold()),
|
|
|
|
VerifyBound::AllBounds(bs) => bs.iter().any(|b| b.cannot_hold()),
|
2015-08-07 10:33:18 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-25 23:58:52 +03:00
|
|
|
pub fn or(self, vb: VerifyBound<'tcx>) -> VerifyBound<'tcx> {
|
2015-08-07 10:33:18 -04:00
|
|
|
if self.must_hold() || vb.cannot_hold() {
|
|
|
|
self
|
|
|
|
} else if self.cannot_hold() || vb.must_hold() {
|
|
|
|
vb
|
|
|
|
} else {
|
|
|
|
VerifyBound::AnyBound(vec![self, vb])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-11-05 18:47:09 -05:00
|
|
|
|
|
|
|
impl<'tcx> RegionConstraintData<'tcx> {
|
2019-02-08 14:53:55 +01:00
|
|
|
/// Returns `true` if this region constraint data contains no constraints, and `false`
|
|
|
|
/// otherwise.
|
2017-11-05 18:47:09 -05:00
|
|
|
pub fn is_empty(&self) -> bool {
|
2023-01-27 17:22:05 +03:00
|
|
|
let RegionConstraintData { constraints, member_constraints, verifys } = self;
|
|
|
|
constraints.is_empty() && member_constraints.is_empty() && verifys.is_empty()
|
2017-11-05 18:47:09 -05:00
|
|
|
}
|
|
|
|
}
|
2020-02-25 09:47:07 +01:00
|
|
|
|
|
|
|
impl<'tcx> Rollback<UndoLog<'tcx>> for RegionConstraintStorage<'tcx> {
|
|
|
|
fn reverse(&mut self, undo: UndoLog<'tcx>) {
|
|
|
|
self.rollback_undo_entry(undo)
|
|
|
|
}
|
|
|
|
}
|