Skip to content

Commit 21789a8

Browse files
authored
Rollup merge of rust-lang#152968 - khyperia:regionkind-comment, r=BoxyUwU
Flip "region lattice" in RegionKind doc comment If we assume that references take their region covariantly, and use that to define the subtyping relationship of regions, `'empty` is ⊤ (top) and `'static` is ⊥ (bottom), and that `'a <: 'b` is defined as `'a >= 'b`. However, the RegionKind doc comment's "region lattice" had `'static` at Top. While this is perhaps technically correct (a so-called "region lattice" is not a "type lattice"), it confused me a lot, and took me half an hour to be like "no, ok, I *do* understand things correctly, this region lattice is just flipped from the subtype lattice". Seems better to just have them be the same! I also took the opportunity to rewrite some parts of the comment with notes that would have helped me when starting out. Bikesheds welcome (as long as they don't go on forever)! For context: the comment "`'static` is Top" was [written in 2013](rust-lang@a896440#diff-8780054cdf09361c4ac2540c7f544ecfdc52a9e610822aabb8bcd2964affcb1cR430), before there was a [discussion in 2014](rust-lang#15699) that clarified that references take their regions covariantly, and `'a <: 'b` is defined as `'a >= 'b`. See also Zulip thread: https://rust-lang.zulipchat.com/#narrow/channel/131828-t-compiler/topic/RegionKind.20rustc.20doc.20comment
2 parents a4eefb7 + 3eb071e commit 21789a8

2 files changed

Lines changed: 42 additions & 30 deletions

File tree

compiler/rustc_type_ir/src/region_kind.rs

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -34,26 +34,26 @@ rustc_index::newtype_index! {
3434
/// In general, the region lattice looks like
3535
///
3636
/// ```text
37-
/// static ----------+-----...------+ (greatest)
37+
/// empty(Un) -------- (smallest)
38+
/// | \
39+
/// ... \
40+
/// | \
41+
/// empty(U1) -- \
42+
/// | \ placeholder(Un)
43+
/// | \ |
44+
/// empty(root) placeholder(U1) |
3845
/// | | |
39-
/// param regions | |
4046
/// | | |
4147
/// | | |
48+
/// param regions | |
4249
/// | | |
43-
/// empty(root) placeholder(U1) |
44-
/// | / |
45-
/// | / placeholder(Un)
46-
/// empty(U1) -- /
47-
/// | /
48-
/// ... /
49-
/// | /
50-
/// empty(Un) -------- (smallest)
50+
/// static ----------+-----...------+ (greatest)
5151
/// ```
5252
///
53-
/// Early-bound/free regions are the named lifetimes in scope from the
54-
/// function declaration. They have relationships to one another
55-
/// determined based on the declared relationships from the
56-
/// function.
53+
/// Lifetimes in scope from a function declaration are represented via
54+
/// [`RegionKind::ReEarlyParam`]/[`RegionKind::ReLateParam`]. They
55+
/// have relationships to one another and `'static` based on the
56+
/// declared relationships from the function.
5757
///
5858
/// Note that inference variables and bound regions are not included
5959
/// in this diagram. In the case of inference variables, they should
@@ -62,29 +62,36 @@ rustc_index::newtype_index! {
6262
/// include -- the diagram indicates the relationship between free
6363
/// regions.
6464
///
65+
/// You can read more about the distinction between early and late bound
66+
/// parameters in the rustc dev guide: [Early vs Late bound parameters].
67+
///
68+
/// A note on subtyping: If we assume that references take their region
69+
/// covariantly, and use that to define the subtyping relationship of regions,
70+
/// it may be somewhat surprising that `'empty` is Top and `'static` is Bottom,
71+
/// and that "`'a` is a subtype of `'b`" is defined as "`'a` is bigger than
72+
/// `'b`" - good to keep in mind.
73+
///
6574
/// ## Inference variables
6675
///
6776
/// During region inference, we sometimes create inference variables,
68-
/// represented as `ReVar`. These will be inferred by the code in
69-
/// `infer::lexical_region_resolve` to some free region from the
70-
/// lattice above (the minimal region that meets the
77+
/// represented as [`RegionKind::ReVar`]. These will be inferred by
78+
/// the code in `infer::lexical_region_resolve` to some free region
79+
/// from the lattice above (the minimal region that meets the
7180
/// constraints).
7281
///
7382
/// During NLL checking, where regions are defined differently, we
74-
/// also use `ReVar` -- in that case, the index is used to index into
75-
/// the NLL region checker's data structures. The variable may in fact
76-
/// represent either a free region or an inference variable, in that
77-
/// case.
83+
/// also use [`RegionKind::ReVar`] -- in that case, the index is used
84+
/// to index into the NLL region checker's data structures. The
85+
/// variable may in fact represent either a free region or an
86+
/// inference variable, in that case.
7887
///
7988
/// ## Bound Regions
8089
///
8190
/// These are regions that are stored behind a binder and must be instantiated
82-
/// with some concrete region before being used. There are two kind of
83-
/// bound regions: early-bound, which are bound in an item's `Generics`,
84-
/// and are instantiated by an `GenericArgs`, and late-bound, which are part of
85-
/// higher-ranked types (e.g., `for<'a> fn(&'a ())`), and are instantiated by
86-
/// the likes of `liberate_late_bound_regions`. The distinction exists
87-
/// because higher-ranked lifetimes aren't supported in all places. See [1][2].
91+
/// with some concrete region before being used. A type can be wrapped in a
92+
/// `Binder`, which introduces new type/const/lifetime variables (e.g., `for<'a>
93+
/// fn(&'a ())`). These parameters are referred to via [`RegionKind::ReBound`].
94+
/// You can instantiate them by the likes of `liberate_late_bound_regions`.
8895
///
8996
/// Unlike `Param`s, bound regions are not supposed to exist "in the wild"
9097
/// outside their binder, e.g., in types passed to type inference, and
@@ -123,8 +130,7 @@ rustc_index::newtype_index! {
123130
/// happen, you can use `leak_check`. This is more clearly explained
124131
/// by the [rustc dev guide].
125132
///
126-
/// [1]: https://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/
127-
/// [2]: https://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/
133+
/// [Early vs Late bound parameters]: https://rustc-dev-guide.rust-lang.org/early-late-parameters.html
128134
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html
129135
#[derive_where(Clone, Copy, Hash, PartialEq; I: Interner)]
130136
#[derive(GenericTypeVisitable)]
@@ -160,7 +166,7 @@ pub enum RegionKind<I: Interner> {
160166
/// more info about early and late bound lifetime parameters.
161167
ReLateParam(I::LateParamRegion),
162168

163-
/// Static data that has an "infinite" lifetime. Top in the region lattice.
169+
/// Static data that has an "infinite" lifetime. Bottom in the region lattice.
164170
ReStatic,
165171

166172
/// A region variable. Should not exist outside of type inference.

src/doc/rustc-dev-guide/src/early-late-parameters.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33

44
> **NOTE**: This chapter largely talks about early/late bound as being solely relevant when discussing function item types/function definitions. This is potentially not completely true, async blocks and closures should likely be discussed somewhat in this chapter.
55
6+
See also these blog posts from when the distinction between early and late bound parameters was
7+
introduced: [Intermingled parameter lists] and [Intermingled parameter lists, take 2].
8+
9+
[Intermingled parameter lists]: https://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/
10+
[Intermingled parameter lists, take 2]: https://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/
11+
612
## What does it mean to be "early" bound or "late" bound
713

814
Every function definition has a corresponding ZST that implements the `Fn*` traits known as a [function item type][function_item_type]. This part of the chapter will talk a little bit about the "desugaring" of function item types as it is useful context for explaining the difference between early bound and late bound generic parameters.

0 commit comments

Comments
 (0)