Skip to content

Commit e383845

Browse files
Rollup merge of #154918 - fmease:fix-enum-var-lt, r=jackh726
Fix elided lifetime resolution & trait object lifetime defaulting for enum variant paths Context: #129543 (comment). Fixes #108224. I consider this to be a minor bug fix that doesn't demand a (T-types) FCP. r? @lcnr or reassign
2 parents 8cfae22 + d39d91f commit e383845

5 files changed

Lines changed: 74 additions & 4 deletions

File tree

compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1693,7 +1693,9 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
16931693
// which requires object lifetime defaults.
16941694
let type_def_id = match res {
16951695
Res::Def(DefKind::AssocTy, def_id) if depth == 1 => Some(self.tcx.parent(def_id)),
1696-
Res::Def(DefKind::Variant, def_id) if depth == 0 => Some(self.tcx.parent(def_id)),
1696+
Res::Def(DefKind::Variant, def_id) if depth == 0 || depth == 1 => {
1697+
Some(self.tcx.parent(def_id))
1698+
}
16971699
Res::Def(
16981700
DefKind::Struct
16991701
| DefKind::Union

compiler/rustc_resolve/src/late.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2177,7 +2177,15 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
21772177
Res::Def(DefKind::AssocTy, def_id) if i + 2 == proj_start => {
21782178
self.r.tcx.parent(def_id)
21792179
}
2180-
Res::Def(DefKind::Variant, def_id) if i + 1 == proj_start => {
2180+
Res::Def(DefKind::Variant, def_id)
2181+
if i + 2 == proj_start && segment.has_generic_args =>
2182+
{
2183+
self.r.tcx.parent(def_id)
2184+
}
2185+
Res::Def(DefKind::Variant, def_id)
2186+
if i + 1 == proj_start
2187+
&& !i.checked_sub(1).is_some_and(|i| path[i].has_generic_args) =>
2188+
{
21812189
self.r.tcx.parent(def_id)
21822190
}
21832191
Res::Def(DefKind::Struct, def_id)

compiler/rustc_resolve/src/lib.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -353,8 +353,7 @@ enum VisResolutionError {
353353
struct Segment {
354354
ident: Ident,
355355
id: Option<NodeId>,
356-
/// Signals whether this `PathSegment` has generic arguments. Used to avoid providing
357-
/// nonsensical suggestions.
356+
/// Signals whether this `PathSegment` has generic arguments.
358357
has_generic_args: bool,
359358
/// Signals whether this `PathSegment` has lifetime arguments.
360359
has_lifetime_args: bool,
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Given an enum `Enum` with lifetime parameters, we used to lower `Enum::<…>::Variant {}` to
2+
// `Enum::<…>::Variant::<'_, …> {}`, i.e., synthesize `'_` lifetime args for enum variants
3+
// even if generic args were already passed to the enum itself.
4+
// Obviously, these conflicting generic arg lists were then rejected later on (by HIR ty lowering).
5+
//
6+
// Now we no longer do. Why do we synthesize these lifetimes for struct variant paths in the first
7+
// place while we don't do it for unit & tuple variants? Well, we later HIR-ty-lower the former in
8+
// "type mode" while we lower the latter in "value mode". In "type mode", we won't infer
9+
// elided lifetimes if the generic arg lists contains non-lifetime args which is undesirable here.
10+
//
11+
// issue: <https://github.com/rust-lang/rust/issues/108224>
12+
//@ check-pass
13+
14+
fn scope<'any>() {
15+
enum Ty0<'a> {
16+
Unit,
17+
Tuple,
18+
Struct {},
19+
20+
Carry(&'a ()),
21+
}
22+
23+
enum Ty1<'a, T: ?Sized> {
24+
Variant,
25+
26+
Carry(&'a T),
27+
}
28+
29+
let _ = Ty0::<'_>::Unit {};
30+
let _ = Ty0::<'static>::Tuple {};
31+
let _ = Ty0::<'any>::Struct {};
32+
33+
let _ = Ty1::</*'_, */()>::Variant {};
34+
let _ = Ty1::<'any, ()>::Variant {};
35+
}
36+
37+
fn main() {}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//@ check-pass
2+
3+
enum Enum<'a, T: 'a + AbideBy<'a> + ?Sized> {
4+
Variant,
5+
6+
Carry(&'a T),
7+
}
8+
9+
fn scope<'any>() {
10+
// We elaborate `dyn Trait` to `dyn Trait + 'any` due to bound `'a` on `T`.
11+
let _ = Enum::Variant::<'any, dyn Trait> {};
12+
13+
// Similarly here.
14+
let _ = Enum::<'any, dyn Trait>::Variant {};
15+
}
16+
17+
trait Trait {}
18+
19+
// We use this to test that a given trait object lifetime bound is
20+
// *exactly equal* to a given lifetime (not longer, not shorter).
21+
trait AbideBy<'a> {}
22+
impl<'a> AbideBy<'a> for dyn Trait + 'a {}
23+
24+
fn main() {}

0 commit comments

Comments
 (0)