Skip to content

Commit f07ebc5

Browse files
committed
add a helper function maybe_collect_in_band_lifetime
1 parent f71807d commit f07ebc5

File tree

1 file changed

+44
-15
lines changed

1 file changed

+44
-15
lines changed

src/librustc/hir/lowering.rs

+44-15
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,29 @@ impl<'a> LoweringContext<'a> {
600600
(params, res)
601601
}
602602

603+
/// When there is a reference to some lifetime `'a`, and in-band
604+
/// lifetimes are enabled, then we want to push that lifetime into
605+
/// the vector of names to define later. In that case, it will get
606+
/// added to the appropriate generics.
607+
fn maybe_collect_in_band_lifetime(&mut self, span: Span, name: Name) {
608+
if !self.is_collecting_in_band_lifetimes {
609+
return;
610+
}
611+
612+
if self.in_scope_lifetimes.contains(&name) {
613+
return;
614+
}
615+
616+
if self.lifetimes_to_define
617+
.iter()
618+
.any(|(_, lt_name)| *lt_name == name)
619+
{
620+
return;
621+
}
622+
623+
self.lifetimes_to_define.push((span, name));
624+
}
625+
603626
// Evaluates `f` with the lifetimes in `lt_defs` in-scope.
604627
// This is used to track which lifetimes have already been defined, and
605628
// which are new in-band lifetimes that need to have a definition created
@@ -1726,15 +1749,7 @@ impl<'a> LoweringContext<'a> {
17261749
x if x == "'_" => hir::LifetimeName::Underscore,
17271750
x if x == "'static" => hir::LifetimeName::Static,
17281751
name => {
1729-
if self.is_collecting_in_band_lifetimes && !self.in_scope_lifetimes.contains(&name)
1730-
&& self.lifetimes_to_define
1731-
.iter()
1732-
.find(|&&(_, lt_name)| lt_name == name)
1733-
.is_none()
1734-
{
1735-
self.lifetimes_to_define.push((l.span, name));
1736-
}
1737-
1752+
self.maybe_collect_in_band_lifetime(l.span, name);
17381753
hir::LifetimeName::Name(name)
17391754
}
17401755
};
@@ -2132,26 +2147,40 @@ impl<'a> LoweringContext<'a> {
21322147
polarity,
21332148
defaultness,
21342149
ref ast_generics,
2135-
ref ifce,
2150+
ref trait_ref,
21362151
ref ty,
21372152
ref impl_items,
21382153
) => {
21392154
let def_id = self.resolver.definitions().local_def_id(id);
2140-
let (generics, (ifce, lowered_ty)) =
2155+
2156+
// Lower the "impl header" first. This ordering is important
2157+
// for in-band lifetimes! Consider `'a` here:
2158+
//
2159+
// impl Foo<'a> for u32 {
2160+
// fn method(&'a self) { .. }
2161+
// }
2162+
//
2163+
// Because we start by lowering the `Foo<'a> for u32`
2164+
// part, we will add `'a` to the list of generics on
2165+
// the impl. When we then encounter it later in the
2166+
// method, it will not be considered an in-band
2167+
// lifetime to be added, but rather a reference to a
2168+
// parent lifetime.
2169+
let (generics, (trait_ref, lowered_ty)) =
21412170
self.add_in_band_defs(ast_generics, def_id, |this| {
2142-
let ifce = ifce.as_ref().map(|trait_ref| {
2171+
let trait_ref = trait_ref.as_ref().map(|trait_ref| {
21432172
this.lower_trait_ref(trait_ref, ImplTraitContext::Disallowed)
21442173
});
21452174

2146-
if let Some(ref trait_ref) = ifce {
2175+
if let Some(ref trait_ref) = trait_ref {
21472176
if let Def::Trait(def_id) = trait_ref.path.def {
21482177
this.trait_impls.entry(def_id).or_insert(vec![]).push(id);
21492178
}
21502179
}
21512180

21522181
let lowered_ty = this.lower_ty(ty, ImplTraitContext::Disallowed);
21532182

2154-
(ifce, lowered_ty)
2183+
(trait_ref, lowered_ty)
21552184
});
21562185

21572186
let new_impl_items = self.with_in_scope_lifetime_defs(
@@ -2172,7 +2201,7 @@ impl<'a> LoweringContext<'a> {
21722201
self.lower_impl_polarity(polarity),
21732202
self.lower_defaultness(defaultness, true /* [1] */),
21742203
generics,
2175-
ifce,
2204+
trait_ref,
21762205
lowered_ty,
21772206
new_impl_items,
21782207
)

0 commit comments

Comments
 (0)