Skip to content

Commit

Permalink
Rollup merge of rust-lang#129383 - cjgillot:opaque-noremap, r=compile…
Browse files Browse the repository at this point in the history
…r-errors,petrochenkov

Remap impl-trait lifetimes on HIR instead of AST lowering

Current AST->HIR lowering goes out of its way to remap lifetimes for opaque types. This is complicated and leaks into upstream and downstream code.

This PR stops trying to be clever during lowering, and prefers to do this remapping during the HIR->ty lowering. The remapping computation easily fits into the bound var resolution code. Its result can be used in by `generics_of` and `hir_ty_lowering::new_opaque` to add the proper parameters and arguments.

See an example on the doc for query `opaque_captured_lifetimes`.

Based on rust-lang#129244

Fixes rust-lang#125249
Fixes rust-lang#126850

cc `@compiler-errors` `@spastorino`
r? `@petrochenkov`
  • Loading branch information
workingjubilee authored Oct 30, 2024
2 parents 759e07f + 2d74d8f commit 6b60f03
Show file tree
Hide file tree
Showing 38 changed files with 512 additions and 746 deletions.
255 changes: 9 additions & 246 deletions compiler/rustc_ast_lowering/src/lib.rs

Large diffs are not rendered by default.

151 changes: 0 additions & 151 deletions compiler/rustc_ast_lowering/src/lifetime_collector.rs

This file was deleted.

2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/diagnostics/region_name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -830,7 +830,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
///
/// [`OpaqueDef`]: hir::TyKind::OpaqueDef
fn get_future_inner_return_ty(&self, hir_ty: &'tcx hir::Ty<'tcx>) -> &'tcx hir::Ty<'tcx> {
let hir::TyKind::OpaqueDef(opaque_ty, _) = hir_ty.kind else {
let hir::TyKind::OpaqueDef(opaque_ty) = hir_ty.kind else {
span_bug!(
hir_ty.span,
"lowered return type of async fn is not OpaqueDef: {:?}",
Expand Down
20 changes: 1 addition & 19 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2627,7 +2627,6 @@ impl<'hir> Ty<'hir> {
}
TyKind::Tup(tys) => tys.iter().any(Self::is_suggestable_infer_ty),
TyKind::Ptr(mut_ty) | TyKind::Ref(_, mut_ty) => mut_ty.ty.is_suggestable_infer_ty(),
TyKind::OpaqueDef(_, generic_args) => are_suggestable_generic_args(generic_args),
TyKind::Path(QPath::TypeRelative(ty, segment)) => {
ty.is_suggestable_infer_ty() || are_suggestable_generic_args(segment.args().args)
}
Expand Down Expand Up @@ -2746,19 +2745,8 @@ pub struct BareFnTy<'hir> {
pub struct OpaqueTy<'hir> {
pub hir_id: HirId,
pub def_id: LocalDefId,
pub generics: &'hir Generics<'hir>,
pub bounds: GenericBounds<'hir>,
pub origin: OpaqueTyOrigin,
/// Return-position impl traits (and async futures) must "reify" any late-bound
/// lifetimes that are captured from the function signature they originate from.
///
/// This is done by generating a new early-bound lifetime parameter local to the
/// opaque which is instantiated in the function signature with the late-bound
/// lifetime.
///
/// This mapping associated a captured lifetime (first parameter) with the new
/// early-bound lifetime that was generated for the opaque.
pub lifetime_mapping: &'hir [(&'hir Lifetime, LocalDefId)],
pub span: Span,
}

Expand Down Expand Up @@ -2861,12 +2849,7 @@ pub enum TyKind<'hir> {
/// Type parameters may be stored in each `PathSegment`.
Path(QPath<'hir>),
/// An opaque type definition itself. This is only used for `impl Trait`.
///
/// The generic argument list contains the lifetimes (and in the future
/// possibly parameters) that are actually bound on the `impl Trait`.
///
/// The last parameter specifies whether this opaque appears in a trait definition.
OpaqueDef(&'hir OpaqueTy<'hir>, &'hir [GenericArg<'hir>]),
OpaqueDef(&'hir OpaqueTy<'hir>),
/// A trait object type `Bound1 + Bound2 + Bound3`
/// where `Bound` is a trait or a lifetime.
TraitObject(&'hir [PolyTraitRef<'hir>], &'hir Lifetime, TraitObjectSyntax),
Expand Down Expand Up @@ -3991,7 +3974,6 @@ impl<'hir> Node<'hir> {
| Node::TraitItem(TraitItem { generics, .. })
| Node::ImplItem(ImplItem { generics, .. }) => Some(generics),
Node::Item(item) => item.kind.generics(),
Node::OpaqueTy(opaque) => Some(opaque.generics),
_ => None,
}
}
Expand Down
7 changes: 2 additions & 5 deletions compiler/rustc_hir/src/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -896,9 +896,8 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Resul
TyKind::Path(ref qpath) => {
try_visit!(visitor.visit_qpath(qpath, typ.hir_id, typ.span));
}
TyKind::OpaqueDef(opaque, lifetimes) => {
TyKind::OpaqueDef(opaque) => {
try_visit!(visitor.visit_opaque_ty(opaque));
walk_list!(visitor, visit_generic_arg, lifetimes);
}
TyKind::Array(ref ty, ref length) => {
try_visit!(visitor.visit_ty(ty));
Expand Down Expand Up @@ -1188,10 +1187,8 @@ pub fn walk_poly_trait_ref<'v, V: Visitor<'v>>(
}

pub fn walk_opaque_ty<'v, V: Visitor<'v>>(visitor: &mut V, opaque: &'v OpaqueTy<'v>) -> V::Result {
let &OpaqueTy { hir_id, def_id: _, generics, bounds, origin: _, lifetime_mapping: _, span: _ } =
opaque;
let &OpaqueTy { hir_id, def_id: _, bounds, origin: _, span: _ } = opaque;
try_visit!(visitor.visit_id(hir_id));
try_visit!(walk_generics(visitor, generics));
walk_list!(visitor, visit_param_bound, bounds);
V::Result::output()
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1302,7 +1302,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
}
}

#[instrument(level = "debug", skip(tcx))]
#[instrument(level = "debug", skip(tcx), ret)]
fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFnSig<'_>> {
use rustc_hir::Node::*;
use rustc_hir::*;
Expand Down
15 changes: 15 additions & 0 deletions compiler/rustc_hir_analysis/src/collect/generics_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,21 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
});
}

if let Node::OpaqueTy(&hir::OpaqueTy { .. }) = node {
assert!(own_params.is_empty());

let lifetimes = tcx.opaque_captured_lifetimes(def_id);
debug!(?lifetimes);

own_params.extend(lifetimes.iter().map(|&(_, param)| ty::GenericParamDef {
name: tcx.item_name(param.to_def_id()),
index: next_index(),
def_id: param.to_def_id(),
pure_wrt_drop: false,
kind: ty::GenericParamDefKind::Lifetime,
}))
}

let param_def_id_to_index =
own_params.iter().map(|param| (param.def_id, param.index)).collect();

Expand Down
7 changes: 0 additions & 7 deletions compiler/rustc_hir_analysis/src/collect/predicates_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,13 +329,6 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
// We create bi-directional Outlives predicates between the original
// and the duplicated parameter, to ensure that they do not get out of sync.
if let Node::OpaqueTy(..) = node {
let opaque_ty_node = tcx.parent_hir_node(hir_id);
let Node::Ty(&hir::Ty { kind: TyKind::OpaqueDef(_, lifetimes), .. }) = opaque_ty_node
else {
bug!("unexpected {opaque_ty_node:?}")
};
debug!(?lifetimes);

compute_bidirectional_outlives_predicates(tcx, &generics.own_params, &mut predicates);
debug!(?predicates);
}
Expand Down
Loading

0 comments on commit 6b60f03

Please sign in to comment.