-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Closed
Labels
A-trait-systemArea: Trait systemArea: Trait systemC-cleanupCategory: PRs that clean code up or issues documenting cleanup.Category: PRs that clean code up or issues documenting cleanup.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.WG-traits[RETIRED] Working group: Traits[RETIRED] Working group: Traits
Description
Part of #49810:
The DebruijnIndex type -- for some reason I no longer recall -- is 1-based:
Lines 897 to 941 in 4b9b70c
/// A [De Bruijn index][dbi] is a standard means of representing | |
/// regions (and perhaps later types) in a higher-ranked setting. In | |
/// particular, imagine a type like this: | |
/// | |
/// for<'a> fn(for<'b> fn(&'b isize, &'a isize), &'a char) | |
/// ^ ^ | | | | |
/// | | | | | | |
/// | +------------+ 1 | | | |
/// | | | | |
/// +--------------------------------+ 2 | | |
/// | | | |
/// +------------------------------------------+ 1 | |
/// | |
/// In this type, there are two binders (the outer fn and the inner | |
/// fn). We need to be able to determine, for any given region, which | |
/// fn type it is bound by, the inner or the outer one. There are | |
/// various ways you can do this, but a De Bruijn index is one of the | |
/// more convenient and has some nice properties. The basic idea is to | |
/// count the number of binders, inside out. Some examples should help | |
/// clarify what I mean. | |
/// | |
/// Let's start with the reference type `&'b isize` that is the first | |
/// argument to the inner function. This region `'b` is assigned a De | |
/// Bruijn index of 1, meaning "the innermost binder" (in this case, a | |
/// fn). The region `'a` that appears in the second argument type (`&'a | |
/// isize`) would then be assigned a De Bruijn index of 2, meaning "the | |
/// second-innermost binder". (These indices are written on the arrays | |
/// in the diagram). | |
/// | |
/// What is interesting is that De Bruijn index attached to a particular | |
/// variable will vary depending on where it appears. For example, | |
/// the final type `&'a char` also refers to the region `'a` declared on | |
/// the outermost fn. But this time, this reference is not nested within | |
/// any other binders (i.e., it is not an argument to the inner fn, but | |
/// rather the outer one). Therefore, in this case, it is assigned a | |
/// De Bruijn index of 1, because the innermost binder in that location | |
/// is the outer fn. | |
/// | |
/// [dbi]: http://en.wikipedia.org/wiki/De_Bruijn_index | |
#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug, Copy, PartialOrd, Ord)] | |
pub struct DebruijnIndex { | |
/// We maintain the invariant that this is never 0. So 1 indicates | |
/// the innermost binder. To ensure this, create with `DebruijnIndex::new`. | |
pub depth: u32, | |
} |
This seems a bit confusing and unnecessary. If we are going to unify it with CanonicalVar
, it'd be nicer if it were 0-based. Also, maybe we should make the internal field private and use an accessor (e.g., to_depth() -> usize
or something).
I guess that the first step to doing this refactor is to remove the assertion from new
:
Lines 1158 to 1160 in 4b9b70c
pub fn new(depth: u32) -> DebruijnIndex { | |
assert!(depth > 0); | |
DebruijnIndex { depth: depth } |
A quick ripgrep reveals that DebruijnIndex::new
is often invoked with a hard-coded 1 or 2, which can .. presumably be just adjusted to 0 and 1, respectively:
/home/nmatsakis/.cargo/bin/rg --no-heading --color never 'DebruijnIndex::new'
src/librustc_driver/test.rs:330: let r = self.re_late_bound_with_debruijn(id, ty::DebruijnIndex::new(1));
src/librustc_driver/test.rs:487: let t_ptr_bound2 = env.t_rptr_late_bound_with_debruijn(1, ty::DebruijnIndex::new(2));
src/librustc_driver/test.rs:524: let t_rptr_bound2 = env.t_rptr_late_bound_with_debruijn(1, ty::DebruijnIndex::new(2));
src/librustc_driver/test.rs:552: let t_rptr_bound1 = env.t_rptr_late_bound_with_debruijn(1, ty::DebruijnIndex::new(1));
src/librustc_driver/test.rs:555: let t_rptr_bound2 = env.t_rptr_late_bound_with_debruijn(1, ty::DebruijnIndex::new(2));
src/librustc_driver/test.rs:571: let re_bound1 = env.re_late_bound_with_debruijn(1, ty::DebruijnIndex::new(1));
src/librustc_driver/test.rs:586: let t_rptr_bound2 = env.t_rptr_late_bound_with_debruijn(1, ty::DebruijnIndex::new(2));
src/librustc_trans/common.rs:428: let env_region = ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrEnv);
src/librustc/util/ppaux.rs:500: tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1), br))
src/librustc/ty/sty.rs:939: /// the innermost binder. To ensure this, create with `DebruijnIndex::new`.
src/librustc/ty/fold.rs:390: self.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(current_depth), br))
src/librustc/ty/fold.rs:451: self.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrAnon(counter)))
src/librustc/ty/util.rs:592: let env_region = ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrEnv);
src/librustc/middle/resolve_lifetime.rs:101: let depth = ty::DebruijnIndex::new(1);
src/librustc/middle/resolve_lifetime.rs:110: let depth = ty::DebruijnIndex::new(1);
src/librustc_typeck/check/intrinsic.rs:122: tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1),
src/librustc_typeck/check/intrinsic.rs:301: tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1),
src/librustc_typeck/check/generator_interior.rs:128: fcx.tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(current_depth),
src/librustc/infer/higher_ranked/mod.rs:420: return infcx.tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1), *a_br));
src/librustc/infer/higher_ranked/mod.rs:476: fldr(region, ty::DebruijnIndex::new(current_depth))
src/librustc/infer/higher_ranked/mod.rs:754: ty::DebruijnIndex::new(current_depth - 1), br.clone()))
Metadata
Metadata
Assignees
Labels
A-trait-systemArea: Trait systemArea: Trait systemC-cleanupCategory: PRs that clean code up or issues documenting cleanup.Category: PRs that clean code up or issues documenting cleanup.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.WG-traits[RETIRED] Working group: Traits[RETIRED] Working group: Traits