diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index eecf01c92fb..1a987c6e2d7 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -252,11 +252,10 @@ enum ImplTraitContext { ReturnPositionOpaqueTy { /// Origin: Either OpaqueTyOrigin::FnReturn or OpaqueTyOrigin::AsyncFn, origin: hir::OpaqueTyOrigin, + in_trait: bool, }, /// Impl trait in type aliases. TypeAliasesOpaqueTy, - /// Return-position `impl Trait` in trait definition - InTrait, /// `impl Trait` is not accepted in this position. Disallowed(ImplTraitPosition), } @@ -1343,9 +1342,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { TyKind::ImplTrait(def_node_id, ref bounds) => { let span = t.span; match itctx { - ImplTraitContext::ReturnPositionOpaqueTy { origin } => { - self.lower_opaque_impl_trait(span, *origin, def_node_id, bounds, itctx) - } + ImplTraitContext::ReturnPositionOpaqueTy { origin, in_trait } => self + .lower_opaque_impl_trait( + span, + *origin, + def_node_id, + bounds, + *in_trait, + itctx, + ), ImplTraitContext::TypeAliasesOpaqueTy => { let mut nested_itctx = ImplTraitContext::TypeAliasesOpaqueTy; self.lower_opaque_impl_trait( @@ -1353,14 +1358,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::OpaqueTyOrigin::TyAlias, def_node_id, bounds, - &mut nested_itctx, + false, + nested_itctx, ) } - ImplTraitContext::InTrait => { - self.lower_impl_trait_in_trait(span, def_node_id, |lctx| { - lctx.lower_param_bounds(bounds, ImplTraitContext::InTrait) - }) - } ImplTraitContext::Universal => { let span = t.span; let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span); @@ -1430,6 +1431,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { origin: hir::OpaqueTyOrigin, opaque_ty_node_id: NodeId, bounds: &GenericBounds, + in_trait: bool, itctx: &mut ImplTraitContext, ) -> hir::TyKind<'hir> { // Make sure we know that some funky desugaring has been going on here. @@ -1518,6 +1520,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }), bounds: hir_bounds, origin, + in_trait, }; debug!(?opaque_ty_item); @@ -1544,30 +1547,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { debug!(?lifetimes); // `impl Trait` now just becomes `Foo<'a, 'b, ..>`. - hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes) - } - - #[instrument(level = "debug", skip(self, lower_bounds))] - fn lower_impl_trait_in_trait( - &mut self, - span: Span, - opaque_ty_node_id: NodeId, - lower_bounds: impl FnOnce(&mut Self) -> hir::GenericBounds<'hir>, - ) -> hir::TyKind<'hir> { - let opaque_ty_def_id = self.local_def_id(opaque_ty_node_id); - self.with_hir_id_owner(opaque_ty_node_id, |lctx| { - let hir_bounds = lower_bounds(lctx); - let rpitit_placeholder = hir::ImplTraitPlaceholder { bounds: hir_bounds }; - let rpitit_item = hir::Item { - def_id: opaque_ty_def_id, - ident: Ident::empty(), - kind: hir::ItemKind::ImplTraitPlaceholder(rpitit_placeholder), - span: lctx.lower_span(span), - vis_span: lctx.lower_span(span.shrink_to_lo()), - }; - hir::OwnerNode::Item(lctx.arena.alloc(rpitit_item)) - }); - hir::TyKind::ImplTraitInTrait(hir::ItemId { def_id: opaque_ty_def_id }) + hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes, in_trait) } /// Registers a new opaque type with the proper `NodeId`s and @@ -1728,30 +1708,28 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) .emit(); } - self.lower_async_fn_ret_ty_in_trait( + self.lower_async_fn_ret_ty( &decl.output, fn_node_id.expect("`make_ret_async` but no `fn_def_id`"), ret_id, + true, ) } _ => { if !kind.impl_trait_return_allowed(self.tcx) { - if kind == FnDeclKind::Impl { - self.tcx - .sess - .create_feature_err( - TraitFnAsync { fn_span, span }, - sym::return_position_impl_trait_in_trait, - ) - .emit(); - } else { - self.tcx.sess.emit_err(TraitFnAsync { fn_span, span }); - } + self.tcx + .sess + .create_feature_err( + TraitFnAsync { fn_span, span }, + sym::return_position_impl_trait_in_trait, + ) + .emit(); } self.lower_async_fn_ret_ty( &decl.output, fn_node_id.expect("`make_ret_async` but no `fn_def_id`"), ret_id, + false, ) } } @@ -1763,10 +1741,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let fn_def_id = self.local_def_id(fn_node_id); ImplTraitContext::ReturnPositionOpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), + in_trait: false, } } - Some(_) if kind.impl_trait_in_trait_allowed(self.tcx) => { - ImplTraitContext::InTrait + Some(fn_node_id) if kind.impl_trait_in_trait_allowed(self.tcx) => { + let fn_def_id = self.local_def_id(fn_node_id); + ImplTraitContext::ReturnPositionOpaqueTy { + origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), + in_trait: true, + } } _ => ImplTraitContext::Disallowed(match kind { FnDeclKind::Fn | FnDeclKind::Inherent => { @@ -1829,6 +1812,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { output: &FnRetTy, fn_node_id: NodeId, opaque_ty_node_id: NodeId, + in_trait: bool, ) -> hir::FnRetTy<'hir> { let span = output.span(); @@ -1960,6 +1944,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span, ImplTraitContext::ReturnPositionOpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), + in_trait, }, ); @@ -1999,6 +1984,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }), bounds: arena_vec![this; future_bound], origin: hir::OpaqueTyOrigin::AsyncFn(fn_def_id), + in_trait, }; trace!("exist ty from async fn def id: {:#?}", opaque_ty_def_id); @@ -2043,41 +2029,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Foo = impl Trait` is, internally, created as a child of the // async fn, so the *type parameters* are inherited. It's // only the lifetime parameters that we must supply. - let opaque_ty_ref = - hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, generic_args); + let opaque_ty_ref = hir::TyKind::OpaqueDef( + hir::ItemId { def_id: opaque_ty_def_id }, + generic_args, + in_trait, + ); let opaque_ty = self.ty(opaque_ty_span, opaque_ty_ref); hir::FnRetTy::Return(self.arena.alloc(opaque_ty)) } - // Transforms `-> T` for `async fn` into `-> OpaqueTy { .. }` - // combined with the following definition of `OpaqueTy`: - // - // type OpaqueTy = impl Future; - // - // `output`: unlowered output type (`T` in `-> T`) - // `fn_def_id`: `DefId` of the parent function (used to create child impl trait definition) - // `opaque_ty_node_id`: `NodeId` of the opaque `impl Trait` type that should be created - #[instrument(level = "debug", skip(self))] - fn lower_async_fn_ret_ty_in_trait( - &mut self, - output: &FnRetTy, - fn_node_id: NodeId, - opaque_ty_node_id: NodeId, - ) -> hir::FnRetTy<'hir> { - let kind = self.lower_impl_trait_in_trait(output.span(), opaque_ty_node_id, |lctx| { - let bound = lctx.lower_async_fn_output_type_to_future_bound( - output, - output.span(), - ImplTraitContext::InTrait, - ); - arena_vec![lctx; bound] - }); - - let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::Async, output.span(), None); - let opaque_ty = self.ty(opaque_ty_span, kind); - hir::FnRetTy::Return(self.arena.alloc(opaque_ty)) - } - /// Transforms `-> T` into `Future`. fn lower_async_fn_output_type_to_future_bound( &mut self, diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 75fde53b6cd..0707ff5ed02 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -772,7 +772,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: {:?}", diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 8b1ebe34cb0..a57fdc3bfb1 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2505,6 +2505,7 @@ pub struct OpaqueTy<'hir> { pub generics: &'hir Generics<'hir>, pub bounds: GenericBounds<'hir>, pub origin: OpaqueTyOrigin, + pub in_trait: bool, } /// From whence the opaque type came. @@ -2518,12 +2519,6 @@ pub enum OpaqueTyOrigin { TyAlias, } -/// Placeholder representation of an `impl Trait` in a trait. Since this never gets lowered into a `ty::Opaque` of its own, we just keep this as -#[derive(Debug, HashStable_Generic)] -pub struct ImplTraitPlaceholder<'hir> { - pub bounds: GenericBounds<'hir>, -} - /// The various kinds of types recognized by the compiler. #[derive(Debug, HashStable_Generic)] pub enum TyKind<'hir> { @@ -2550,12 +2545,9 @@ pub enum TyKind<'hir> { /// /// The generic argument list contains the lifetimes (and in the future /// possibly parameters) that are actually bound on the `impl Trait`. - OpaqueDef(ItemId, &'hir [GenericArg<'hir>]), - /// A type that represents an `impl Trait` in a trait function. This is - /// not an opaque type, since it acts more like an associated type than - /// an opaque, and since it needs no generics since it inherits those - /// from the item's parent. - ImplTraitInTrait(ItemId), + /// + /// The last parameter specifies whether this opaque appears in a trait definition. + OpaqueDef(ItemId, &'hir [GenericArg<'hir>], bool), /// A trait object type `Bound1 + Bound2 + Bound3` /// where `Bound` is a trait or a lifetime. TraitObject(&'hir [PolyTraitRef<'hir>], &'hir Lifetime, TraitObjectSyntax), @@ -3011,8 +3003,6 @@ pub enum ItemKind<'hir> { TyAlias(&'hir Ty<'hir>, &'hir Generics<'hir>), /// An opaque `impl Trait` type alias, e.g., `type Foo = impl Bar;`. OpaqueTy(OpaqueTy<'hir>), - /// An `impl Trait` in a trait - ImplTraitPlaceholder(ImplTraitPlaceholder<'hir>), /// An enum definition, e.g., `enum Foo {C, D}`. Enum(EnumDef<'hir>, &'hir Generics<'hir>), /// A struct definition, e.g., `struct Foo {x: A}`. @@ -3081,7 +3071,6 @@ impl ItemKind<'_> { ItemKind::Trait(..) => "trait", ItemKind::TraitAlias(..) => "trait alias", ItemKind::Impl(..) => "implementation", - ItemKind::ImplTraitPlaceholder(..) => "opaque type in trait", } } } diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 3e9ab10b1f7..bf4ab06638b 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -562,10 +562,6 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) { walk_generics(visitor, generics); walk_list!(visitor, visit_param_bound, bounds); } - ItemKind::ImplTraitPlaceholder(ImplTraitPlaceholder { bounds }) => { - visitor.visit_id(item.hir_id()); - walk_list!(visitor, visit_param_bound, bounds); - } ItemKind::Enum(ref enum_definition, ref generics) => { visitor.visit_generics(generics); // `visit_enum_def()` takes care of visiting the `Item`'s `HirId`. @@ -674,13 +670,10 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) { TyKind::Path(ref qpath) => { visitor.visit_qpath(qpath, typ.hir_id, typ.span); } - TyKind::OpaqueDef(item_id, lifetimes) => { + TyKind::OpaqueDef(item_id, lifetimes, _in_trait) => { visitor.visit_nested_item(item_id); walk_list!(visitor, visit_generic_arg, lifetimes); } - TyKind::ImplTraitInTrait(item_id) => { - visitor.visit_nested_item(item_id); - } TyKind::Array(ref ty, ref length) => { visitor.visit_ty(ty); visitor.visit_array_length(length) diff --git a/compiler/rustc_hir/src/target.rs b/compiler/rustc_hir/src/target.rs index 0e9b05729d2..5917d5e346e 100644 --- a/compiler/rustc_hir/src/target.rs +++ b/compiler/rustc_hir/src/target.rs @@ -80,8 +80,13 @@ impl Target { ItemKind::ForeignMod { .. } => Target::ForeignMod, ItemKind::GlobalAsm(..) => Target::GlobalAsm, ItemKind::TyAlias(..) => Target::TyAlias, - ItemKind::OpaqueTy(..) => Target::OpaqueTy, - ItemKind::ImplTraitPlaceholder(..) => Target::ImplTraitPlaceholder, + ItemKind::OpaqueTy(ref opaque) => { + if opaque.in_trait { + Target::ImplTraitPlaceholder + } else { + Target::OpaqueTy + } + } ItemKind::Enum(..) => Target::Enum, ItemKind::Struct(..) => Target::Struct, ItemKind::Union(..) => Target::Union, diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 01f445c8a52..35a58296e37 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -327,7 +327,6 @@ impl<'a> State<'a> { self.print_ty_fn(f.abi, f.unsafety, f.decl, None, f.generic_params, f.param_names); } hir::TyKind::OpaqueDef(..) => self.word("/*impl Trait*/"), - hir::TyKind::ImplTraitInTrait(..) => self.word("/*impl Trait*/"), hir::TyKind::Path(ref qpath) => self.print_qpath(qpath, false), hir::TyKind::TraitObject(bounds, ref lifetime, syntax) => { if syntax == ast::TraitObjectSyntax::Dyn { @@ -609,9 +608,6 @@ impl<'a> State<'a> { state.print_bounds("= impl", real_bounds); }); } - hir::ItemKind::ImplTraitPlaceholder(..) => { - unreachable!("FIXME(RPITIT): I don't think this ever gets called here..."); - } hir::ItemKind::Enum(ref enum_definition, params) => { self.print_enum_def(enum_definition, params, item.ident.name, item.span); } diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index f804569b074..b115ac8b3df 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -300,7 +300,7 @@ pub fn suggest_new_region_bound( continue; } match fn_return.kind { - TyKind::OpaqueDef(item_id, _) => { + TyKind::OpaqueDef(item_id, _, _) => { let item = tcx.hir().item(item_id); let ItemKind::OpaqueTy(opaque) = &item.kind else { return; diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index d45d814c3b0..f967ac9a4dc 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1500,9 +1500,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { hir::ItemKind::OpaqueTy(..) => { self.encode_explicit_item_bounds(def_id); } - hir::ItemKind::ImplTraitPlaceholder(..) => { - self.encode_explicit_item_bounds(def_id); - } hir::ItemKind::Enum(..) => { let adt_def = self.tcx.adt_def(def_id); record!(self.tables.repr_options[def_id] <- adt_def.repr()); diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 1a0bea68293..5a65ec9a476 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -212,8 +212,13 @@ impl<'hir> Map<'hir> { ItemKind::Fn(..) => DefKind::Fn, ItemKind::Macro(_, macro_kind) => DefKind::Macro(macro_kind), ItemKind::Mod(..) => DefKind::Mod, - ItemKind::OpaqueTy(..) => DefKind::OpaqueTy, - ItemKind::ImplTraitPlaceholder(..) => DefKind::ImplTraitPlaceholder, + ItemKind::OpaqueTy(ref opaque) => { + if opaque.in_trait { + DefKind::ImplTraitPlaceholder + } else { + DefKind::OpaqueTy + } + } ItemKind::TyAlias(..) => DefKind::TyAlias, ItemKind::Enum(..) => DefKind::Enum, ItemKind::Struct(..) => DefKind::Struct, @@ -1188,8 +1193,13 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { ItemKind::ForeignMod { .. } => "foreign mod", ItemKind::GlobalAsm(..) => "global asm", ItemKind::TyAlias(..) => "ty", - ItemKind::OpaqueTy(..) => "opaque type", - ItemKind::ImplTraitPlaceholder(..) => "opaque type in trait", + ItemKind::OpaqueTy(ref opaque) => { + if opaque.in_trait { + "opaque type in trait" + } else { + "opaque type" + } + } ItemKind::Enum(..) => "enum", ItemKind::Struct(..) => "struct", ItemKind::Union(..) => "union", diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index e4ad96b659b..648f5f7161f 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -408,7 +408,7 @@ impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> { ) => { self.0.push(ty); } - hir::TyKind::OpaqueDef(item_id, _) => { + hir::TyKind::OpaqueDef(item_id, _, _) => { self.0.push(ty); let item = self.1.item(item_id); hir::intravisit::walk_item(self, item); diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index a7ce0f312af..f141d7beeb9 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -447,7 +447,7 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> { } fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) { - if let TyKind::OpaqueDef(item_id, _) = ty.kind { + if let TyKind::OpaqueDef(item_id, _, _) = ty.kind { let item = self.tcx.hir().item(item_id); intravisit::walk_item(self, item); } diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index 74c5ccf9cd2..f7e3fac6b2e 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -235,7 +235,6 @@ impl<'tcx> ReachableContext<'tcx> { hir::ItemKind::ExternCrate(_) | hir::ItemKind::Use(..) | hir::ItemKind::OpaqueTy(..) - | hir::ItemKind::ImplTraitPlaceholder(..) | hir::ItemKind::TyAlias(..) | hir::ItemKind::Macro(..) | hir::ItemKind::Mod(..) diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 3657fb21340..afd423dc5fa 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -686,7 +686,6 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { } hir::ItemKind::OpaqueTy(..) - | hir::ItemKind::ImplTraitPlaceholder(..) | hir::ItemKind::Use(..) | hir::ItemKind::Static(..) | hir::ItemKind::Const(..) @@ -708,12 +707,12 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { hir::ItemKind::Use(..) => {} // The interface is empty. hir::ItemKind::GlobalAsm(..) => {} - hir::ItemKind::OpaqueTy(..) => { + hir::ItemKind::OpaqueTy(ref opaque) => { // HACK(jynelson): trying to infer the type of `impl trait` breaks `async-std` (and `pub async fn` in general) // Since rustdoc never needs to do codegen and doesn't care about link-time reachability, // mark this as unreachable. // See https://github.com/rust-lang/rust/issues/75100 - if !self.tcx.sess.opts.actually_rustdoc { + if !opaque.in_trait && !self.tcx.sess.opts.actually_rustdoc { // FIXME: This is some serious pessimization intended to workaround deficiencies // in the reachability pass (`middle/reachable.rs`). Types are marked as link-time // reachable if they are returned via `impl Trait`, even from private functions. @@ -722,9 +721,6 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { self.reach(item.def_id, exist_level).generics().predicates().ty(); } } - hir::ItemKind::ImplTraitPlaceholder(..) => { - // FIXME(RPITIT): Do we need to do anything here? - } // Visit everything. hir::ItemKind::Const(..) | hir::ItemKind::Static(..) @@ -2039,8 +2035,7 @@ fn local_visibility(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Visibility { // query failing on some items, we provide it for opaque types as well. | Node::Item(hir::Item { kind: hir::ItemKind::Use(_, hir::UseKind::ListStem) - | hir::ItemKind::OpaqueTy(..) - | hir::ItemKind::ImplTraitPlaceholder(..), + | hir::ItemKind::OpaqueTy(..), .. }) => ty::Visibility::Restricted(tcx.parent_module(hir_id)), // Visibilities of trait impl items are inherited from their traits diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index e9e4f8fc483..6ff56f9a891 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -596,10 +596,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } } } - hir::ItemKind::ImplTraitPlaceholder(..) => { - // FIXME(RPITIT): We don't need to do anything special here, right? - intravisit::walk_item(self, item); - } hir::ItemKind::TyAlias(_, ref generics) | hir::ItemKind::Enum(_, ref generics) | hir::ItemKind::Struct(_, ref generics) @@ -719,7 +715,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { }; self.with(scope, |this| this.visit_ty(&mt.ty)); } - hir::TyKind::OpaqueDef(item_id, lifetimes) => { + hir::TyKind::OpaqueDef(item_id, lifetimes, _in_trait) => { // Resolve the lifetimes in the bounds to the lifetime defs in the generics. // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to // `type MyAnonTy<'b> = impl MyTrait<'b>;` diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs index 6658892881d..94f222251d3 100644 --- a/compiler/rustc_save_analysis/src/dump_visitor.rs +++ b/compiler/rustc_save_analysis/src/dump_visitor.rs @@ -1321,7 +1321,7 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> { }), } } - hir::TyKind::OpaqueDef(item_id, _) => { + hir::TyKind::OpaqueDef(item_id, _, _) => { let item = self.tcx.hir().item(item_id); self.nest_typeck_results(item_id.def_id, |v| v.visit_item(item)); } diff --git a/compiler/rustc_save_analysis/src/sig.rs b/compiler/rustc_save_analysis/src/sig.rs index ea9c82b3597..bae1828cd18 100644 --- a/compiler/rustc_save_analysis/src/sig.rs +++ b/compiler/rustc_save_analysis/src/sig.rs @@ -316,11 +316,7 @@ impl<'hir> Sig for hir::Ty<'hir> { let text = format!("[{}; {}]", nested_ty.text, expr); Ok(replace_text(nested_ty, text)) } - hir::TyKind::OpaqueDef(item_id, _) => { - let item = scx.tcx.hir().item(item_id); - item.make(offset, Some(item_id.hir_id()), scx) - } - hir::TyKind::ImplTraitInTrait(item_id) => { + hir::TyKind::OpaqueDef(item_id, _, _) => { let item = scx.tcx.hir().item(item_id); item.make(offset, Some(item_id.hir_id()), scx) } @@ -565,8 +561,13 @@ impl<'hir> Sig for hir::Item<'hir> { hir::ItemKind::ForeignMod { .. } => Err("extern mod"), hir::ItemKind::GlobalAsm(_) => Err("global asm"), hir::ItemKind::ExternCrate(_) => Err("extern crate"), - hir::ItemKind::OpaqueTy(..) => Err("opaque type"), - hir::ItemKind::ImplTraitPlaceholder(..) => Err("opaque type in trait"), + hir::ItemKind::OpaqueTy(ref opaque) => { + if opaque.in_trait { + Err("opaque type in trait") + } else { + Err("opaque type") + } + } // FIXME should implement this (e.g., pub use). hir::ItemKind::Use(..) => Err("import"), } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 7253ab21b3a..8a65262a007 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -2165,7 +2165,7 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>( let tcx = selcx.tcx(); let mut obligations = data.nested; - let trait_fn_def_id = tcx.parent(obligation.predicate.item_def_id); + let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.item_def_id); let Ok(leaf_def) = assoc_def(selcx, data.impl_def_id, trait_fn_def_id) else { return Progress { term: tcx.ty_error().into(), obligations }; }; diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 6eec2c57639..d9789d5aaf0 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -2360,7 +2360,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let span = path.span; match path.res { - Res::Def(DefKind::OpaqueTy, did) => { + Res::Def(DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder, did) => { // Check for desugared `impl Trait`. assert!(ty::is_impl_trait_defn(tcx, did).is_none()); let item_segment = path.segments.split_last().unwrap(); @@ -2627,21 +2627,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let opt_self_ty = maybe_qself.as_ref().map(|qself| self.ast_ty_to_ty(qself)); self.res_to_ty(opt_self_ty, path, false) } - hir::TyKind::OpaqueDef(item_id, lifetimes) => { + hir::TyKind::OpaqueDef(item_id, lifetimes, in_trait) => { let opaque_ty = tcx.hir().item(item_id); let def_id = item_id.def_id.to_def_id(); match opaque_ty.kind { hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => { - self.impl_trait_ty_to_ty(def_id, lifetimes, origin) + self.impl_trait_ty_to_ty(def_id, lifetimes, origin, in_trait) } ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i), } } - hir::TyKind::ImplTraitInTrait(item_id) => { - let def_id = item_id.def_id.to_def_id(); - tcx.mk_projection(def_id, InternalSubsts::identity_for_item(tcx, def_id)) - } hir::TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => { debug!(?qself, ?segment); let ty = self.ast_ty_to_ty_inner(qself, false, true); @@ -2707,6 +2703,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { def_id: DefId, lifetimes: &[hir::GenericArg<'_>], origin: OpaqueTyOrigin, + in_trait: bool, ) -> Ty<'tcx> { debug!("impl_trait_ty_to_ty(def_id={:?}, lifetimes={:?})", def_id, lifetimes); let tcx = self.tcx(); @@ -2750,7 +2747,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }); debug!("impl_trait_ty_to_ty: substs={:?}", substs); - tcx.mk_opaque(def_id, substs) + if in_trait { tcx.mk_projection(def_id, substs) } else { tcx.mk_opaque(def_id, substs) } } pub fn ty_of_arg(&self, ty: &hir::Ty<'_>, expected_ty: Option>) -> Ty<'tcx> { diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index da45469863e..a6c8dbb2555 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -423,9 +423,28 @@ pub(super) fn compare_predicates_and_trait_impl_trait_tys<'tcx>( ); let mut collected_tys = FxHashMap::default(); - for (def_id, ty) in collector.types { + for (def_id, (ty, substs)) in collector.types { match infcx.fully_resolve(ty) { Ok(ty) => { + // `ty` contains free regions that we created earlier while liberating the + // trait fn signature. However, projection normalization expects `ty` to + // contains `def_id`'s early-bound regions. + let id_substs = InternalSubsts::identity_for_item(tcx, def_id); + debug!(?id_substs, ?substs); + let map: FxHashMap, ty::GenericArg<'tcx>> = substs + .iter() + .enumerate() + .map(|(index, arg)| (arg, id_substs[index])) + .collect(); + debug!(?map); + + let ty = tcx.fold_regions(ty, |region, _| { + if let ty::ReFree(_) = region.kind() { + map[®ion.into()].expect_region() + } else { + region + } + }); collected_tys.insert(def_id, ty); } Err(err) => { @@ -444,7 +463,7 @@ pub(super) fn compare_predicates_and_trait_impl_trait_tys<'tcx>( struct ImplTraitInTraitCollector<'a, 'tcx> { ocx: &'a ObligationCtxt<'a, 'tcx>, - types: FxHashMap>, + types: FxHashMap, ty::SubstsRef<'tcx>)>, span: Span, param_env: ty::ParamEnv<'tcx>, body_id: hir::HirId, @@ -470,7 +489,7 @@ impl<'tcx> TypeFolder<'tcx> for ImplTraitInTraitCollector<'_, 'tcx> { if let ty::Projection(proj) = ty.kind() && self.tcx().def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder { - if let Some(ty) = self.types.get(&proj.item_def_id) { + if let Some((ty, _)) = self.types.get(&proj.item_def_id) { return *ty; } //FIXME(RPITIT): Deny nested RPITIT in substs too @@ -482,7 +501,7 @@ impl<'tcx> TypeFolder<'tcx> for ImplTraitInTraitCollector<'_, 'tcx> { span: self.span, kind: TypeVariableOriginKind::MiscVariable, }); - self.types.insert(proj.item_def_id, infer_ty); + self.types.insert(proj.item_def_id, (infer_ty, proj.substs)); // Recurse into bounds for pred in self.tcx().bound_explicit_item_bounds(proj.item_def_id).transpose_iter() { let pred_span = pred.0.1; diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index e5e82a4ff6b..ceb5684fdf0 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -815,11 +815,6 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { tcx.ensure().predicates_of(def_id); tcx.ensure().explicit_item_bounds(def_id); } - hir::ItemKind::ImplTraitPlaceholder(..) => { - tcx.ensure().generics_of(def_id); - tcx.ensure().predicates_of(def_id); - tcx.ensure().explicit_item_bounds(def_id); - } hir::ItemKind::TyAlias(..) | hir::ItemKind::Static(..) | hir::ItemKind::Const(..) @@ -1590,8 +1585,16 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id), + in_trait, .. - }) => Some(fn_def_id.to_def_id()), + }) => { + if in_trait { + assert!(matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn)) + } else { + assert!(matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn | DefKind::Fn)) + } + Some(fn_def_id.to_def_id()) + } ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => { let parent_id = tcx.hir().get_parent_item(hir_id); assert_ne!(parent_id, CRATE_DEF_ID); @@ -1600,14 +1603,6 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { // inherit the generics of the item. Some(parent_id.to_def_id()) } - ItemKind::ImplTraitPlaceholder(_) => { - let parent_id = tcx.hir().get_parent_item(hir_id).to_def_id(); - assert!(matches!( - tcx.def_kind(parent_id), - DefKind::AssocFn | DefKind::ImplTraitPlaceholder - )); - Some(parent_id) - } _ => None, }, _ => None, @@ -1800,7 +1795,7 @@ fn is_suggestable_infer_ty(ty: &hir::Ty<'_>) -> bool { } Tup(tys) => tys.iter().any(is_suggestable_infer_ty), Ptr(mut_ty) | Rptr(_, mut_ty) => is_suggestable_infer_ty(mut_ty.ty), - OpaqueDef(_, generic_args) => are_suggestable_generic_args(generic_args), + OpaqueDef(_, generic_args, _) => are_suggestable_generic_args(generic_args), Path(hir::QPath::TypeRelative(ty, segment)) => { is_suggestable_infer_ty(ty) || are_suggestable_generic_args(segment.args().args) } diff --git a/compiler/rustc_typeck/src/collect/item_bounds.rs b/compiler/rustc_typeck/src/collect/item_bounds.rs index fe8d8f54f04..0d34a8bfee3 100644 --- a/compiler/rustc_typeck/src/collect/item_bounds.rs +++ b/compiler/rustc_typeck/src/collect/item_bounds.rs @@ -59,10 +59,15 @@ fn opaque_type_bounds<'tcx>( opaque_def_id: DefId, ast_bounds: &'tcx [hir::GenericBound<'tcx>], span: Span, + in_trait: bool, ) -> &'tcx [(ty::Predicate<'tcx>, Span)] { ty::print::with_no_queries!({ - let item_ty = - tcx.mk_opaque(opaque_def_id, InternalSubsts::identity_for_item(tcx, opaque_def_id)); + let substs = InternalSubsts::identity_for_item(tcx, opaque_def_id); + let item_ty = if in_trait { + tcx.mk_projection(opaque_def_id, substs) + } else { + tcx.mk_opaque(opaque_def_id, substs) + }; let icx = ItemCtxt::new(tcx, opaque_def_id); let mut bounds = >::compute_bounds(&icx, item_ty, ast_bounds); @@ -74,29 +79,6 @@ fn opaque_type_bounds<'tcx>( }) } -/// Opaque types don't inherit bounds from their parent: for return position -/// impl trait it isn't possible to write a suitable predicate on the -/// containing function and for type-alias impl trait we don't have a backwards -/// compatibility issue. -fn impl_trait_in_trait_item_bounds<'tcx>( - tcx: TyCtxt<'tcx>, - opaque_def_id: DefId, - ast_bounds: &'tcx [hir::GenericBound<'tcx>], - span: Span, -) -> &'tcx [(ty::Predicate<'tcx>, Span)] { - ty::print::with_no_queries!({ - // FIXME(RPITIT): DRY-er code please - let item_ty = - tcx.mk_projection(opaque_def_id, InternalSubsts::identity_for_item(tcx, opaque_def_id)); - - let icx = ItemCtxt::new(tcx, opaque_def_id); - let mut bounds = >::compute_bounds(&icx, item_ty, ast_bounds); - // RPITITs are implicitly sized unless a `?Sized` bound is found - >::add_implicitly_sized(&icx, &mut bounds, ast_bounds, None, span); - tcx.arena.alloc_from_iter(bounds.predicates(tcx, item_ty)) - }) -} - pub(super) fn explicit_item_bounds( tcx: TyCtxt<'_>, def_id: DefId, @@ -109,15 +91,10 @@ pub(super) fn explicit_item_bounds( .. }) => associated_type_bounds(tcx, def_id, bounds, *span), hir::Node::Item(hir::Item { - kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, .. }), + kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, in_trait, .. }), span, .. - }) => opaque_type_bounds(tcx, def_id, bounds, *span), - hir::Node::Item(hir::Item { - kind: hir::ItemKind::ImplTraitPlaceholder(hir::ImplTraitPlaceholder { bounds }), - span, - .. - }) => impl_trait_in_trait_item_bounds(tcx, def_id, bounds, *span), + }) => opaque_type_bounds(tcx, def_id, bounds, *span, *in_trait), _ => bug!("item_bounds called on {:?}", def_id), } } diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index ded2ac1308e..a26e26cb389 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -333,11 +333,12 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { find_opaque_ty_constraints_for_tait(tcx, def_id) } // Opaque types desugared from `impl Trait`. - ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(owner) | hir::OpaqueTyOrigin::AsyncFn(owner), .. }) => { - find_opaque_ty_constraints_for_rpit(tcx, def_id, owner) - } - ItemKind::ImplTraitPlaceholder(..) => { - span_bug!(item.span, "not yet implemented") + ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(owner) | hir::OpaqueTyOrigin::AsyncFn(owner), in_trait, .. }) => { + if in_trait { + span_bug!(item.span, "impl-trait in trait has no default") + } else { + find_opaque_ty_constraints_for_rpit(tcx, def_id, owner) + } } ItemKind::Trait(..) | ItemKind::TraitAlias(..) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 03752c9b6db..08b696e65eb 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1492,7 +1492,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T Array(Box::new(clean_ty(ty, cx)), length) } TyKind::Tup(tys) => Tuple(tys.iter().map(|ty| clean_ty(ty, cx)).collect()), - TyKind::OpaqueDef(item_id, _) => { + TyKind::OpaqueDef(item_id, _, _) => { let item = cx.tcx.hir().item(item_id); if let hir::ItemKind::OpaqueTy(ref ty) = item.kind { ImplTrait(ty.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect()) @@ -1500,16 +1500,6 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T unreachable!() } } - TyKind::ImplTraitInTrait(item_id) => { - let item = cx.tcx.hir().item(item_id); - if let hir::ItemKind::ImplTraitPlaceholder(hir::ImplTraitPlaceholder { bounds }) = - item.kind - { - ImplTrait(bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect()) - } else { - unreachable!() - } - } TyKind::Path(_) => clean_qpath(ty, cx), TyKind::TraitObject(bounds, ref lifetime, _) => { let bounds = bounds.iter().map(|bound| clean_poly_trait_ref(bound, cx)).collect(); diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 7fe391f420f..ca7a20bf368 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -362,7 +362,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { | hir::ItemKind::Union(..) | hir::ItemKind::TyAlias(..) | hir::ItemKind::OpaqueTy(..) - | hir::ItemKind::ImplTraitPlaceholder(..) | hir::ItemKind::Static(..) | hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) => om.items.push((item, renamed)), diff --git a/src/test/ui/impl-trait/in-trait/opaque-in-impl.rs b/src/test/ui/impl-trait/in-trait/opaque-in-impl.rs index a777cbcd529..2e06629699a 100644 --- a/src/test/ui/impl-trait/in-trait/opaque-in-impl.rs +++ b/src/test/ui/impl-trait/in-trait/opaque-in-impl.rs @@ -3,18 +3,46 @@ #![feature(return_position_impl_trait_in_trait)] #![allow(incomplete_features)] -use std::fmt::Display; +use std::fmt::Debug; trait Foo { - fn bar(&self) -> impl Display; + fn foo(&self) -> impl Debug; } impl Foo for () { - fn bar(&self) -> impl Display { + fn foo(&self) -> impl Debug { "Hello, world" } } -fn main() { - println!("{}", ().bar()); +impl Foo for std::marker::PhantomData { + fn foo(&self) -> impl Debug { + T::default() + } +} + +trait Bar { + fn bar(&self) -> impl Debug; +} + +impl Bar for () { + fn bar(&self) -> impl Debug { + format!("Hello with generic {}", std::any::type_name::()) + } +} + +trait Baz { + fn baz(&self) -> impl Debug + '_; +} + +impl Baz for String { + fn baz(&self) -> impl Debug + '_ { + (self,) + } +} + +fn main() { + println!("{:?}", ().foo()); + println!("{:?}", ().bar::()); + println!("{:?}", "hi".to_string().baz()); }