Skip to content

Commit

Permalink
Properly deduce the object lifetime default in GAT paths
Browse files Browse the repository at this point in the history
  • Loading branch information
fmease committed Aug 25, 2024
1 parent c416a6f commit 8bfcd86
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 21 deletions.
31 changes: 16 additions & 15 deletions compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1482,17 +1482,21 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {

// Figure out if this is a type/trait segment,
// which requires object lifetime defaults.
let type_def_id = match res {
Res::Def(DefKind::AssocTy, def_id) if depth == 1 => Some(self.tcx.parent(def_id)),
Res::Def(DefKind::Variant, def_id) if depth == 0 => Some(self.tcx.parent(def_id)),
Res::Def(
DefKind::Struct
| DefKind::Union
| DefKind::Enum
| DefKind::TyAlias
| DefKind::Trait,
def_id,
) if depth == 0 => Some(def_id),
let type_def_id = match (res, depth) {
(Res::Def(DefKind::AssocTy, def_id), 1) => Some(self.tcx.parent(def_id)),
(Res::Def(DefKind::Variant, def_id), 0) => Some(self.tcx.parent(def_id)),
(
Res::Def(
DefKind::Struct
| DefKind::Union
| DefKind::Enum
| DefKind::TyAlias
| DefKind::Trait
| DefKind::AssocTy,
def_id,
),
0,
) => Some(def_id),
_ => None,
};

Expand Down Expand Up @@ -1536,9 +1540,6 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
let map = &self.map;
let generics = self.tcx.generics_of(def_id);

// `type_def_id` points to an item, so there is nothing to inherit generics from.
debug_assert_eq!(generics.parent_count, 0);

let set_to_region = |set: ObjectLifetimeDefault| match set {
ObjectLifetimeDefault::Empty => {
if in_body {
Expand All @@ -1549,8 +1550,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
}
ObjectLifetimeDefault::Static => Some(ResolvedArg::StaticLifetime),
ObjectLifetimeDefault::Param(param_def_id) => {
// This index can be used with `generic_args` since `parent_count == 0`.
let index = generics.param_def_id_to_index[&param_def_id] as usize;
let index = index - generics.parent_count;
generic_args.args.get(index).and_then(|arg| match arg {
GenericArg::Lifetime(lt) => map.defs.get(&lt.hir_id).copied(),
_ => None,
Expand Down
11 changes: 5 additions & 6 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1995,22 +1995,21 @@ impl<'tcx> ContainerTy<'_, 'tcx> {
| DefKind::Union
| DefKind::Enum
| DefKind::TyAlias
| DefKind::Trait) = tcx.def_kind(container)
| DefKind::Trait
| DefKind::AssocTy) = tcx.def_kind(container)
else {
return ObjectLifetimeDefault::Empty;
};

let generics = tcx.generics_of(container);
debug_assert_eq!(generics.parent_count, 0);

let param = generics.own_params[index].def_id;
let default = tcx.object_lifetime_default(param);
match default {
rbv::ObjectLifetimeDefault::Param(lifetime) => {
// The index is relative to the parent generics but since we don't have any,
// we don't need to translate it.
let index = generics.param_def_id_to_index[&lifetime];
let arg = args.skip_binder()[index as usize].expect_region();
let index = generics.param_def_id_to_index[&lifetime] as usize;
let index = index - generics.parent_count;
let arg = args.skip_binder()[index].expect_region();
ObjectLifetimeDefault::Arg(arg)
}
rbv::ObjectLifetimeDefault::Empty => ObjectLifetimeDefault::Empty,
Expand Down
16 changes: 16 additions & 0 deletions tests/ui/object-lifetime/object-lifetime-default-gat.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Properly deduce the object lifetime default in generic associated type (GAT) *paths*.
// issue: rust-lang/rust#115379
//@ check-pass

trait Outer {
type Ty<'a, T: ?Sized + 'a>;
}
impl Outer for () {
type Ty<'a, T: ?Sized + 'a> = &'a T;
}
trait Inner {}

fn f<'r>(x: <() as Outer>::Ty<'r, dyn Inner + 'r>) { g(x) }
fn g<'r>(_: <() as Outer>::Ty<'r, dyn Inner>) {}

fn main() {}

0 comments on commit 8bfcd86

Please sign in to comment.