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

Refactoring to OpaqueTyOrigin #131183

Merged
merged 4 commits into from
Oct 4, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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
2 changes: 0 additions & 2 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
parent: this.local_def_id(id),
in_assoc_ty: false,
},
fn_kind: None,
}),
},
);
Expand Down Expand Up @@ -983,7 +982,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
parent: this.local_def_id(i.id),
in_assoc_ty: true,
},
fn_kind: None,
});
hir::ImplItemKind::Type(ty)
}
Expand Down
87 changes: 41 additions & 46 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,12 +288,7 @@ enum ImplTraitContext {
/// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually
/// equivalent to a new opaque type like `type T = impl Debug; fn foo() -> T`.
///
OpaqueTy {
origin: hir::OpaqueTyOrigin,
/// Only used to change the lifetime capture rules, since
/// RPITIT captures all in scope, RPIT does not.
fn_kind: Option<FnDeclKind>,
},
OpaqueTy { origin: hir::OpaqueTyOrigin },
/// `impl Trait` is unstably accepted in this position.
FeatureGated(ImplTraitPosition, Symbol),
/// `impl Trait` is not accepted in this position.
Expand Down Expand Up @@ -1404,14 +1399,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
TyKind::ImplTrait(def_node_id, bounds) => {
let span = t.span;
match itctx {
ImplTraitContext::OpaqueTy { origin, fn_kind } => self.lower_opaque_impl_trait(
span,
origin,
*def_node_id,
bounds,
fn_kind,
itctx,
),
ImplTraitContext::OpaqueTy { origin } => {
self.lower_opaque_impl_trait(span, origin, *def_node_id, bounds, itctx)
}
ImplTraitContext::Universal => {
if let Some(span) = bounds.iter().find_map(|bound| match *bound {
ast::GenericBound::Use(_, span) => Some(span),
Expand Down Expand Up @@ -1513,7 +1503,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
origin: hir::OpaqueTyOrigin,
opaque_ty_node_id: NodeId,
bounds: &GenericBounds,
fn_kind: Option<FnDeclKind>,
itctx: ImplTraitContext,
) -> hir::TyKind<'hir> {
// Make sure we know that some funky desugaring has been going on here.
Expand Down Expand Up @@ -1555,11 +1544,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
.map(|(ident, id, _)| Lifetime { id, ident })
.collect()
}
hir::OpaqueTyOrigin::FnReturn(..) => {
if matches!(
fn_kind.expect("expected RPITs to be lowered with a FnKind"),
FnDeclKind::Impl | FnDeclKind::Trait
) || self.tcx.features().lifetime_capture_rules_2024
hir::OpaqueTyOrigin::FnReturn { in_trait_or_impl, .. } => {
if in_trait_or_impl.is_some()
|| self.tcx.features().lifetime_capture_rules_2024
|| span.at_least_rust_2024()
{
// return-position impl trait in trait was decided to capture all
Expand All @@ -1576,37 +1563,29 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
lifetime_collector::lifetimes_in_bounds(self.resolver, bounds)
}
}
hir::OpaqueTyOrigin::AsyncFn(..) => {
hir::OpaqueTyOrigin::AsyncFn { .. } => {
unreachable!("should be using `lower_async_fn_ret_ty`")
}
}
};
debug!(?captured_lifetimes_to_duplicate);

match fn_kind {
// Deny `use<>` on RPITIT in trait/trait-impl for now.
Some(FnDeclKind::Trait | FnDeclKind::Impl) => {
// Feature gate for RPITIT + use<..>
match origin {
rustc_hir::OpaqueTyOrigin::FnReturn { in_trait_or_impl: Some(_), .. } => {
if let Some(span) = bounds.iter().find_map(|bound| match *bound {
ast::GenericBound::Use(_, span) => Some(span),
_ => None,
}) {
self.tcx.dcx().emit_err(errors::NoPreciseCapturesOnRpitit { span });
}
}
None
| Some(
FnDeclKind::Fn
| FnDeclKind::Inherent
| FnDeclKind::ExternFn
| FnDeclKind::Closure
| FnDeclKind::Pointer,
) => {}
_ => {}
}

self.lower_opaque_inner(
opaque_ty_node_id,
origin,
matches!(fn_kind, Some(FnDeclKind::Trait)),
captured_lifetimes_to_duplicate,
span,
opaque_ty_span,
Expand All @@ -1618,7 +1597,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
&mut self,
opaque_ty_node_id: NodeId,
origin: hir::OpaqueTyOrigin,
in_trait: bool,
captured_lifetimes_to_duplicate: FxIndexSet<Lifetime>,
span: Span,
opaque_ty_span: Span,
Expand Down Expand Up @@ -1747,7 +1725,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
bounds,
origin,
lifetime_mapping,
in_trait,
};

// Generate an `type Foo = impl Trait;` declaration.
Expand Down Expand Up @@ -1776,7 +1753,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
hir::TyKind::OpaqueDef(
hir::ItemId { owner_id: hir::OwnerId { def_id: opaque_ty_def_id } },
generic_args,
in_trait,
)
}

Expand Down Expand Up @@ -1864,12 +1840,23 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
None => match &decl.output {
FnRetTy::Ty(ty) => {
let itctx = match kind {
FnDeclKind::Fn
| FnDeclKind::Inherent
| FnDeclKind::Trait
| FnDeclKind::Impl => ImplTraitContext::OpaqueTy {
origin: hir::OpaqueTyOrigin::FnReturn(self.local_def_id(fn_node_id)),
fn_kind: Some(kind),
FnDeclKind::Fn | FnDeclKind::Inherent => ImplTraitContext::OpaqueTy {
origin: hir::OpaqueTyOrigin::FnReturn {
parent: self.local_def_id(fn_node_id),
in_trait_or_impl: None,
},
},
FnDeclKind::Trait => ImplTraitContext::OpaqueTy {
origin: hir::OpaqueTyOrigin::FnReturn {
parent: self.local_def_id(fn_node_id),
in_trait_or_impl: Some(hir::RpitContext::Trait),
},
},
FnDeclKind::Impl => ImplTraitContext::OpaqueTy {
origin: hir::OpaqueTyOrigin::FnReturn {
parent: self.local_def_id(fn_node_id),
in_trait_or_impl: Some(hir::RpitContext::TraitImpl),
},
},
FnDeclKind::ExternFn => {
ImplTraitContext::Disallowed(ImplTraitPosition::ExternFnReturn)
Expand Down Expand Up @@ -1951,10 +1938,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
.map(|(ident, id, _)| Lifetime { id, ident })
.collect();

let in_trait_or_impl = match fn_kind {
FnDeclKind::Trait => Some(hir::RpitContext::Trait),
FnDeclKind::Impl => Some(hir::RpitContext::TraitImpl),
FnDeclKind::Fn | FnDeclKind::Inherent => None,
FnDeclKind::ExternFn | FnDeclKind::Closure | FnDeclKind::Pointer => unreachable!(),
};

let opaque_ty_ref = self.lower_opaque_inner(
opaque_ty_node_id,
hir::OpaqueTyOrigin::AsyncFn(fn_def_id),
matches!(fn_kind, FnDeclKind::Trait),
hir::OpaqueTyOrigin::AsyncFn { parent: fn_def_id, in_trait_or_impl },
captured_lifetimes,
span,
opaque_ty_span,
Expand All @@ -1964,8 +1957,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
coro,
opaque_ty_span,
ImplTraitContext::OpaqueTy {
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
fn_kind: Some(fn_kind),
origin: hir::OpaqueTyOrigin::FnReturn {
parent: fn_def_id,
in_trait_or_impl,
},
},
);
arena_vec![this; bound]
Expand Down
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 @@ -832,7 +832,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
fn get_future_inner_return_ty(&self, hir_ty: &'tcx hir::Ty<'tcx>) -> &'tcx hir::Ty<'tcx> {
let hir = self.infcx.tcx.hir();

let hir::TyKind::OpaqueDef(id, _, _) = hir_ty.kind else {
let hir::TyKind::OpaqueDef(id, _) = hir_ty.kind else {
span_bug!(
hir_ty.span,
"lowered return type of async fn is not OpaqueDef: {:?}",
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_borrowck/src/region_infer/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -503,8 +503,8 @@ impl<'tcx> LazyOpaqueTyEnv<'tcx> {
let &Self { tcx, def_id, .. } = self;
let origin = tcx.opaque_type_origin(def_id);
let parent = match origin {
hir::OpaqueTyOrigin::FnReturn(parent)
| hir::OpaqueTyOrigin::AsyncFn(parent)
hir::OpaqueTyOrigin::FnReturn { parent, .. }
| hir::OpaqueTyOrigin::AsyncFn { parent, .. }
| hir::OpaqueTyOrigin::TyAlias { parent, .. } => parent,
};
let param_env = tcx.param_env(parent);
Expand Down
28 changes: 20 additions & 8 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2632,7 +2632,7 @@ 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::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 @@ -2762,10 +2762,6 @@ pub struct OpaqueTy<'hir> {
/// 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)],
/// Whether the opaque is a return-position impl trait (or async future)
/// originating from a trait method. This makes it so that the opaque is
/// lowered as an associated type.
pub in_trait: bool,
}

#[derive(Debug, Clone, Copy, HashStable_Generic)]
Expand Down Expand Up @@ -2802,13 +2798,29 @@ pub struct PreciseCapturingNonLifetimeArg {
pub res: Res,
}

#[derive(Copy, Clone, PartialEq, Eq, Debug, HashStable_Generic)]
pub enum RpitContext {
Trait,
TraitImpl,
}

/// From whence the opaque type came.
#[derive(Copy, Clone, PartialEq, Eq, Debug, HashStable_Generic)]
pub enum OpaqueTyOrigin {
/// `-> impl Trait`
FnReturn(LocalDefId),
FnReturn {
/// The defining function.
parent: LocalDefId,
// Whether this is an RPITIT (return position impl trait in trait)
in_trait_or_impl: Option<RpitContext>,
},
/// `async fn`
AsyncFn(LocalDefId),
AsyncFn {
/// The defining function.
parent: LocalDefId,
// Whether this is an AFIT (async fn in trait)
in_trait_or_impl: Option<RpitContext>,
},
/// type aliases: `type Foo = impl Trait;`
TyAlias {
/// The type alias or associated type parent of the TAIT/ATPIT
Expand Down Expand Up @@ -2856,7 +2868,7 @@ pub enum TyKind<'hir> {
/// possibly parameters) that are actually bound on the `impl Trait`.
///
/// The last parameter specifies whether this opaque appears in a trait definition.
OpaqueDef(ItemId, &'hir [GenericArg<'hir>], bool),
OpaqueDef(ItemId, &'hir [GenericArg<'hir>]),
/// A trait object type `Bound1 + Bound2 + Bound3`
/// where `Bound` is a trait or a lifetime.
TraitObject(
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir/src/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -894,7 +894,7 @@ 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(item_id, lifetimes, _in_trait) => {
TyKind::OpaqueDef(item_id, lifetimes) => {
try_visit!(visitor.visit_nested_item(item_id));
walk_list!(visitor, visit_generic_arg, lifetimes);
}
Expand Down
16 changes: 8 additions & 8 deletions compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -336,18 +336,18 @@ fn check_opaque_meets_bounds<'tcx>(
origin: &hir::OpaqueTyOrigin,
) -> Result<(), ErrorGuaranteed> {
let defining_use_anchor = match *origin {
hir::OpaqueTyOrigin::FnReturn(did)
| hir::OpaqueTyOrigin::AsyncFn(did)
| hir::OpaqueTyOrigin::TyAlias { parent: did, .. } => did,
hir::OpaqueTyOrigin::FnReturn { parent, .. }
| hir::OpaqueTyOrigin::AsyncFn { parent, .. }
| hir::OpaqueTyOrigin::TyAlias { parent, .. } => parent,
};
let param_env = tcx.param_env(defining_use_anchor);

let infcx = tcx.infer_ctxt().with_opaque_type_inference(defining_use_anchor).build();
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);

let args = match *origin {
hir::OpaqueTyOrigin::FnReturn(parent)
| hir::OpaqueTyOrigin::AsyncFn(parent)
hir::OpaqueTyOrigin::FnReturn { parent, .. }
| hir::OpaqueTyOrigin::AsyncFn { parent, .. }
| hir::OpaqueTyOrigin::TyAlias { parent, .. } => GenericArgs::identity_for_item(
tcx, parent,
)
Expand Down Expand Up @@ -409,7 +409,7 @@ fn check_opaque_meets_bounds<'tcx>(
let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env)?;

if let hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) = origin {
if let hir::OpaqueTyOrigin::FnReturn { .. } | hir::OpaqueTyOrigin::AsyncFn { .. } = origin {
// HACK: this should also fall through to the hidden type check below, but the original
// implementation had a bug where equivalent lifetimes are not identical. This caused us
// to reject existing stable code that is otherwise completely fine. The real fix is to
Expand Down Expand Up @@ -736,8 +736,8 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
check_opaque_precise_captures(tcx, def_id);

let origin = tcx.opaque_type_origin(def_id);
if let hir::OpaqueTyOrigin::FnReturn(fn_def_id)
| hir::OpaqueTyOrigin::AsyncFn(fn_def_id) = origin
if let hir::OpaqueTyOrigin::FnReturn { parent: fn_def_id, .. }
| hir::OpaqueTyOrigin::AsyncFn { parent: fn_def_id, .. } = origin
&& let hir::Node::TraitItem(trait_item) = tcx.hir_node_by_def_id(fn_def_id)
&& let (_, hir::TraitFn::Required(..)) = trait_item.expect_fn()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
if !tcx.hir().get_if_local(impl_opaque.def_id).is_some_and(|node| {
matches!(
node.expect_item().expect_opaque_ty().origin,
hir::OpaqueTyOrigin::AsyncFn(def_id) | hir::OpaqueTyOrigin::FnReturn(def_id)
if def_id == impl_m.def_id.expect_local()
hir::OpaqueTyOrigin::AsyncFn { parent, .. } | hir::OpaqueTyOrigin::FnReturn { parent, .. }
if parent == impl_m.def_id.expect_local()
)
}) {
report_mismatched_rpitit_signature(
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_hir_analysis/src/collect/generics_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,11 +210,11 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
Node::Item(item) => match item.kind {
ItemKind::OpaqueTy(&hir::OpaqueTy {
origin:
hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id),
in_trait,
hir::OpaqueTyOrigin::FnReturn { parent: fn_def_id, in_trait_or_impl }
| hir::OpaqueTyOrigin::AsyncFn { parent: fn_def_id, in_trait_or_impl },
..
}) => {
if in_trait {
if in_trait_or_impl.is_some() {
assert_matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn);
} else {
assert_matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn | DefKind::Fn);
Expand Down
Loading
Loading