Skip to content

Commit 9acb351

Browse files
committed
reset the "anonymous lifetime mode" for parenthesized where clauses
Background: The anonymous lifetime mode is used to prohibit elided lifetimes where they didn't used to be permitted, and instead require that `'_` be used. For example: ```rust impl Trait for Ref<T> { .. } // ^^^^^^ ERROR: should be `Ref<'_, T>` ``` When we are parsing the parts of the impl header, we enter into an alternate mode called `CreateParameter`. In this mode, we give an error for things like `Ref<T>`, but for elided lifetimes in a reference type like `&T` we make the elided lifetime into an in-band lifetime: https://github.com/rust-lang/rust/blob/4f99f37b7e213d69a489884f651adfc6d217cef5/src/librustc/hir/lowering.rs#L4017-L4035 This was not intended to change behavior because we only enter into that mode in contexts where elision was not historically permitted. However, the problem is that we fail to reset the mode when we enter into bounds like `Fn(&u32)`, where elision *was* allowed -- the same occurs for fn types like `fn(&u32`). This PR restores the original mode in those contexts.
1 parent 74d0939 commit 9acb351

File tree

3 files changed

+91
-37
lines changed

3 files changed

+91
-37
lines changed

src/librustc/hir/lowering.rs

+59-37
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,18 @@ impl<'a> LoweringContext<'a> {
594594
span.with_ctxt(SyntaxContext::empty().apply_mark(mark))
595595
}
596596

597+
fn with_anonymous_lifetime_mode<R>(
598+
&mut self,
599+
anonymous_lifetime_mode: AnonymousLifetimeMode,
600+
op: impl FnOnce(&mut Self) -> R,
601+
) -> R {
602+
let old_anonymous_lifetime_mode = self.anonymous_lifetime_mode;
603+
self.anonymous_lifetime_mode = anonymous_lifetime_mode;
604+
let result = op(self);
605+
self.anonymous_lifetime_mode = old_anonymous_lifetime_mode;
606+
result
607+
}
608+
597609
/// Creates a new hir::GenericParam for every new lifetime and
598610
/// type parameter encountered while evaluating `f`. Definitions
599611
/// are created with the parent provided. If no `parent_id` is
@@ -1620,44 +1632,54 @@ impl<'a> LoweringContext<'a> {
16201632
&mut self,
16211633
data: &ParenthesizedParameterData,
16221634
) -> (hir::PathParameters, bool) {
1623-
const DISALLOWED: ImplTraitContext = ImplTraitContext::Disallowed;
1624-
let &ParenthesizedParameterData {
1625-
ref inputs,
1626-
ref output,
1627-
span,
1628-
} = data;
1629-
let inputs = inputs
1630-
.iter()
1631-
.map(|ty| self.lower_ty(ty, DISALLOWED))
1632-
.collect();
1633-
let mk_tup = |this: &mut Self, tys, span| {
1634-
let LoweredNodeId { node_id, hir_id } = this.next_id();
1635-
P(hir::Ty {
1636-
node: hir::TyTup(tys),
1637-
id: node_id,
1638-
hir_id,
1639-
span,
1640-
})
1641-
};
1635+
// Switch to `PassThrough` mode for anonymous lifetimes: this
1636+
// means that we permit things like `&Ref<T>`, where `Ref` has
1637+
// a hidden lifetime parameter. This is needed for backwards
1638+
// compatibility, even in contexts like an impl header where
1639+
// we generally don't permit such things (see #51008).
1640+
self.with_anonymous_lifetime_mode(
1641+
AnonymousLifetimeMode::PassThrough,
1642+
|this| {
1643+
const DISALLOWED: ImplTraitContext = ImplTraitContext::Disallowed;
1644+
let &ParenthesizedParameterData {
1645+
ref inputs,
1646+
ref output,
1647+
span,
1648+
} = data;
1649+
let inputs = inputs
1650+
.iter()
1651+
.map(|ty| this.lower_ty(ty, DISALLOWED))
1652+
.collect();
1653+
let mk_tup = |this: &mut Self, tys, span| {
1654+
let LoweredNodeId { node_id, hir_id } = this.next_id();
1655+
P(hir::Ty {
1656+
node: hir::TyTup(tys),
1657+
id: node_id,
1658+
hir_id,
1659+
span,
1660+
})
1661+
};
16421662

1643-
(
1644-
hir::PathParameters {
1645-
lifetimes: hir::HirVec::new(),
1646-
types: hir_vec![mk_tup(self, inputs, span)],
1647-
bindings: hir_vec![
1648-
hir::TypeBinding {
1649-
id: self.next_id().node_id,
1650-
name: Symbol::intern(FN_OUTPUT_NAME),
1651-
ty: output
1652-
.as_ref()
1653-
.map(|ty| self.lower_ty(&ty, DISALLOWED))
1654-
.unwrap_or_else(|| mk_tup(self, hir::HirVec::new(), span)),
1655-
span: output.as_ref().map_or(span, |ty| ty.span),
1656-
}
1657-
],
1658-
parenthesized: true,
1659-
},
1660-
false,
1663+
(
1664+
hir::PathParameters {
1665+
lifetimes: hir::HirVec::new(),
1666+
types: hir_vec![mk_tup(this, inputs, span)],
1667+
bindings: hir_vec![
1668+
hir::TypeBinding {
1669+
id: this.next_id().node_id,
1670+
name: Symbol::intern(FN_OUTPUT_NAME),
1671+
ty: output
1672+
.as_ref()
1673+
.map(|ty| this.lower_ty(&ty, DISALLOWED))
1674+
.unwrap_or_else(|| mk_tup(this, hir::HirVec::new(), span)),
1675+
span: output.as_ref().map_or(span, |ty| ty.span),
1676+
}
1677+
],
1678+
parenthesized: true,
1679+
},
1680+
false,
1681+
)
1682+
}
16611683
)
16621684
}
16631685

src/librustc/middle/resolve_lifetime.rs

+7
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,13 @@ impl Region {
101101
let depth = ty::DebruijnIndex::INNERMOST;
102102
let def_id = hir_map.local_def_id(def.lifetime.id);
103103
let origin = LifetimeDefOrigin::from_is_in_band(def.in_band);
104+
debug!(
105+
"Region::late: def={:?} depth={:?} def_id={:?} origin={:?}",
106+
def,
107+
depth,
108+
def_id,
109+
origin,
110+
);
104111
(def.lifetime.name, Region::LateBound(depth, def_id, origin))
105112
}
106113

src/test/ui/rust-2018/issue-51008.rs

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Regression test for #51008 -- the anonymous lifetime in `&i32` was
12+
// being incorrectly considered part of the "elided lifetimes" from
13+
// the impl.
14+
//
15+
// run-pass
16+
17+
#![feature(rust_2018_preview)]
18+
19+
trait A {
20+
21+
}
22+
23+
impl<F> A for F where F: FnOnce(&i32) {}
24+
25+
fn main() {}

0 commit comments

Comments
 (0)