Skip to content

Commit c1287c0

Browse files
committed
Auto merge of #51220 - nikomatsakis:issue-51008-false-positive-lifetime-must-be-declared, r=cramertj
reset anonymous-lifetime-mode as we enter `()` scopes 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. Fixes #51008 r? @cramertj
2 parents e1eed38 + da69bbc commit c1287c0

File tree

4 files changed

+132
-48
lines changed

4 files changed

+132
-48
lines changed

src/librustc/hir/lowering.rs

+75-48
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
@@ -1021,17 +1033,22 @@ impl<'a> LoweringContext<'a> {
10211033
_ => None,
10221034
}),
10231035
|this| {
1024-
hir::TyBareFn(P(hir::BareFnTy {
1025-
generic_params: this.lower_generic_params(
1026-
&f.generic_params,
1027-
&NodeMap(),
1028-
ImplTraitContext::Disallowed,
1029-
),
1030-
unsafety: this.lower_unsafety(f.unsafety),
1031-
abi: f.abi,
1032-
decl: this.lower_fn_decl(&f.decl, None, false),
1033-
arg_names: this.lower_fn_args_to_names(&f.decl),
1034-
}))
1036+
this.with_anonymous_lifetime_mode(
1037+
AnonymousLifetimeMode::PassThrough,
1038+
|this| {
1039+
hir::TyBareFn(P(hir::BareFnTy {
1040+
generic_params: this.lower_generic_params(
1041+
&f.generic_params,
1042+
&NodeMap(),
1043+
ImplTraitContext::Disallowed,
1044+
),
1045+
unsafety: this.lower_unsafety(f.unsafety),
1046+
abi: f.abi,
1047+
decl: this.lower_fn_decl(&f.decl, None, false),
1048+
arg_names: this.lower_fn_args_to_names(&f.decl),
1049+
}))
1050+
},
1051+
)
10351052
},
10361053
),
10371054
TyKind::Never => hir::TyNever,
@@ -1623,44 +1640,54 @@ impl<'a> LoweringContext<'a> {
16231640
&mut self,
16241641
data: &ParenthesizedParameterData,
16251642
) -> (hir::PathParameters, bool) {
1626-
const DISALLOWED: ImplTraitContext = ImplTraitContext::Disallowed;
1627-
let &ParenthesizedParameterData {
1628-
ref inputs,
1629-
ref output,
1630-
span,
1631-
} = data;
1632-
let inputs = inputs
1633-
.iter()
1634-
.map(|ty| self.lower_ty(ty, DISALLOWED))
1635-
.collect();
1636-
let mk_tup = |this: &mut Self, tys, span| {
1637-
let LoweredNodeId { node_id, hir_id } = this.next_id();
1638-
P(hir::Ty {
1639-
node: hir::TyTup(tys),
1640-
id: node_id,
1641-
hir_id,
1642-
span,
1643-
})
1644-
};
1643+
// Switch to `PassThrough` mode for anonymous lifetimes: this
1644+
// means that we permit things like `&Ref<T>`, where `Ref` has
1645+
// a hidden lifetime parameter. This is needed for backwards
1646+
// compatibility, even in contexts like an impl header where
1647+
// we generally don't permit such things (see #51008).
1648+
self.with_anonymous_lifetime_mode(
1649+
AnonymousLifetimeMode::PassThrough,
1650+
|this| {
1651+
const DISALLOWED: ImplTraitContext = ImplTraitContext::Disallowed;
1652+
let &ParenthesizedParameterData {
1653+
ref inputs,
1654+
ref output,
1655+
span,
1656+
} = data;
1657+
let inputs = inputs
1658+
.iter()
1659+
.map(|ty| this.lower_ty(ty, DISALLOWED))
1660+
.collect();
1661+
let mk_tup = |this: &mut Self, tys, span| {
1662+
let LoweredNodeId { node_id, hir_id } = this.next_id();
1663+
P(hir::Ty {
1664+
node: hir::TyTup(tys),
1665+
id: node_id,
1666+
hir_id,
1667+
span,
1668+
})
1669+
};
16451670

1646-
(
1647-
hir::PathParameters {
1648-
lifetimes: hir::HirVec::new(),
1649-
types: hir_vec![mk_tup(self, inputs, span)],
1650-
bindings: hir_vec![
1651-
hir::TypeBinding {
1652-
id: self.next_id().node_id,
1653-
name: Symbol::intern(FN_OUTPUT_NAME),
1654-
ty: output
1655-
.as_ref()
1656-
.map(|ty| self.lower_ty(&ty, DISALLOWED))
1657-
.unwrap_or_else(|| mk_tup(self, hir::HirVec::new(), span)),
1658-
span: output.as_ref().map_or(span, |ty| ty.span),
1659-
}
1660-
],
1661-
parenthesized: true,
1662-
},
1663-
false,
1671+
(
1672+
hir::PathParameters {
1673+
lifetimes: hir::HirVec::new(),
1674+
types: hir_vec![mk_tup(this, inputs, span)],
1675+
bindings: hir_vec![
1676+
hir::TypeBinding {
1677+
id: this.next_id().node_id,
1678+
name: Symbol::intern(FN_OUTPUT_NAME),
1679+
ty: output
1680+
.as_ref()
1681+
.map(|ty| this.lower_ty(&ty, DISALLOWED))
1682+
.unwrap_or_else(|| mk_tup(this, hir::HirVec::new(), span)),
1683+
span: output.as_ref().map_or(span, |ty| ty.span),
1684+
}
1685+
],
1686+
parenthesized: true,
1687+
},
1688+
false,
1689+
)
1690+
}
16641691
)
16651692
}
16661693

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

+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: PartialEq<fn(&i32)> { }
24+
25+
fn main() {}

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)