Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[crater] Properly deduce object lifetime defaults in GAT paths #129543

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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() {}
Loading