From 78b962a4f348c0b901d2eae9e5852cb3675b1233 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 31 Aug 2022 03:04:44 +0000 Subject: [PATCH 01/18] RPITIT placeholder items --- compiler/rustc_hir/src/def.rs | 5 +++++ compiler/rustc_hir/src/hir.rs | 11 +++++++++++ compiler/rustc_hir/src/intravisit.rs | 7 +++++++ compiler/rustc_hir/src/target.rs | 3 +++ compiler/rustc_hir_pretty/src/lib.rs | 4 ++++ compiler/rustc_metadata/src/rmeta/encoder.rs | 5 +++++ compiler/rustc_metadata/src/rmeta/table.rs | 1 + compiler/rustc_middle/src/hir/map/mod.rs | 2 ++ compiler/rustc_monomorphize/src/polymorphize.rs | 1 + compiler/rustc_passes/src/check_attr.rs | 1 + compiler/rustc_passes/src/reachable.rs | 1 + compiler/rustc_privacy/src/lib.rs | 5 +++++ compiler/rustc_resolve/src/build_reduced_graph.rs | 1 + compiler/rustc_resolve/src/late/lifetimes.rs | 3 +++ compiler/rustc_save_analysis/src/lib.rs | 1 + compiler/rustc_save_analysis/src/sig.rs | 5 +++++ compiler/rustc_ty_utils/src/implied_bounds.rs | 1 + compiler/rustc_typeck/src/astconv/mod.rs | 3 +++ compiler/rustc_typeck/src/collect.rs | 5 +++++ compiler/rustc_typeck/src/collect/type_of.rs | 3 +++ src/librustdoc/clean/utils.rs | 4 ++-- 21 files changed, 70 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index b44ee02cfe3bb..8563b588585bd 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -109,6 +109,8 @@ pub enum DefKind { InlineConst, /// Opaque type, aka `impl Trait`. OpaqueTy, + /// A return-position `impl Trait` in a trait definition + ImplTraitPlaceholder, Field, /// Lifetime parameter: the `'a` in `struct Foo<'a> { ... }` LifetimeParam, @@ -138,6 +140,7 @@ impl DefKind { panic!("impossible struct constructor") } DefKind::OpaqueTy => "opaque type", + DefKind::ImplTraitPlaceholder => "opaque type in trait", DefKind::TyAlias => "type alias", DefKind::TraitAlias => "trait alias", DefKind::AssocTy => "associated type", @@ -190,6 +193,7 @@ impl DefKind { | DefKind::Variant | DefKind::Trait | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::TyAlias | DefKind::ForeignTy | DefKind::TraitAlias @@ -254,6 +258,7 @@ impl DefKind { | DefKind::Use | DefKind::ForeignMod | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::Impl | DefKind::Field | DefKind::TyParam diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index cc5aed6cb5482..334d4fd0b042b 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2518,6 +2518,12 @@ 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> { @@ -2545,6 +2551,8 @@ 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>]), + /// The placeholder + ImplTraitInTrait(ItemId), /// A trait object type `Bound1 + Bound2 + Bound3` /// where `Bound` is a trait or a lifetime. TraitObject(&'hir [PolyTraitRef<'hir>], &'hir Lifetime, TraitObjectSyntax), @@ -3000,6 +3008,8 @@ 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}`. @@ -3068,6 +3078,7 @@ 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 20ec788463ac0..3e9ab10b1f7e3 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -562,6 +562,10 @@ 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,6 +678,9 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) { 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 78bfd7191dba9..ea23c48cc5359 100644 --- a/compiler/rustc_hir/src/target.rs +++ b/compiler/rustc_hir/src/target.rs @@ -36,6 +36,7 @@ pub enum Target { GlobalAsm, TyAlias, OpaqueTy, + ImplTraitPlaceholder, Enum, Variant, Struct, @@ -80,6 +81,7 @@ impl Target { ItemKind::GlobalAsm(..) => Target::GlobalAsm, ItemKind::TyAlias(..) => Target::TyAlias, ItemKind::OpaqueTy(..) => Target::OpaqueTy, + ItemKind::ImplTraitPlaceholder(..) => Target::ImplTraitPlaceholder, ItemKind::Enum(..) => Target::Enum, ItemKind::Struct(..) => Target::Struct, ItemKind::Union(..) => Target::Union, @@ -157,6 +159,7 @@ impl Target { Target::GlobalAsm => "global asm", Target::TyAlias => "type alias", Target::OpaqueTy => "opaque type", + Target::ImplTraitPlaceholder => "opaque type in trait", Target::Enum => "enum", Target::Variant => "enum variant", Target::Struct => "struct", diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 35a58296e370e..01f445c8a52d5 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -327,6 +327,7 @@ 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 { @@ -608,6 +609,9 @@ 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_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index b807663b10fd0..02ca34181cd0b 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -847,6 +847,7 @@ fn should_encode_visibility(def_kind: DefKind) -> bool { | DefKind::Use | DefKind::ForeignMod | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::Impl | DefKind::Field => true, DefKind::TyParam @@ -879,6 +880,7 @@ fn should_encode_stability(def_kind: DefKind) -> bool { | DefKind::ForeignMod | DefKind::TyAlias | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::Enum | DefKind::Union | DefKind::Impl @@ -967,6 +969,7 @@ fn should_encode_variances(def_kind: DefKind) -> bool { | DefKind::ForeignMod | DefKind::TyAlias | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::Impl | DefKind::Trait | DefKind::TraitAlias @@ -1003,6 +1006,7 @@ fn should_encode_generics(def_kind: DefKind) -> bool { | DefKind::AnonConst | DefKind::InlineConst | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::Impl | DefKind::Field | DefKind::TyParam @@ -1493,6 +1497,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } hir::ItemKind::OpaqueTy(..) => { self.encode_explicit_item_bounds(def_id); + EntryKind::OpaqueTy } hir::ItemKind::Enum(..) => { let adt_def = self.tcx.adt_def(def_id); diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index d5f151f0ed8e5..e7c1abd126e04 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -90,6 +90,7 @@ fixed_size_enum! { ( AnonConst ) ( InlineConst ) ( OpaqueTy ) + ( ImplTraitPlaceholder ) ( Field ) ( LifetimeParam ) ( GlobalAsm ) diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 6217bffb8f76c..1a0bea68293e7 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -213,6 +213,7 @@ impl<'hir> Map<'hir> { ItemKind::Macro(_, macro_kind) => DefKind::Macro(macro_kind), ItemKind::Mod(..) => DefKind::Mod, ItemKind::OpaqueTy(..) => DefKind::OpaqueTy, + ItemKind::ImplTraitPlaceholder(..) => DefKind::ImplTraitPlaceholder, ItemKind::TyAlias(..) => DefKind::TyAlias, ItemKind::Enum(..) => DefKind::Enum, ItemKind::Struct(..) => DefKind::Struct, @@ -1188,6 +1189,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { ItemKind::GlobalAsm(..) => "global asm", ItemKind::TyAlias(..) => "ty", ItemKind::OpaqueTy(..) => "opaque type", + ItemKind::ImplTraitPlaceholder(..) => "opaque type in trait", ItemKind::Enum(..) => "enum", ItemKind::Struct(..) => "struct", ItemKind::Union(..) => "union", diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs index af4b35db3bace..98156a94ec4b4 100644 --- a/compiler/rustc_monomorphize/src/polymorphize.rs +++ b/compiler/rustc_monomorphize/src/polymorphize.rs @@ -170,6 +170,7 @@ fn mark_used_by_default_parameters<'tcx>( | DefKind::AnonConst | DefKind::InlineConst | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::Field | DefKind::LifetimeParam | DefKind::GlobalAsm diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index d0b46aa2c4530..bb684e784c58a 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -661,6 +661,7 @@ impl CheckAttrVisitor<'_> { | Target::GlobalAsm | Target::TyAlias | Target::OpaqueTy + | Target::ImplTraitPlaceholder | Target::Enum | Target::Variant | Target::Struct diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index f7e3fac6b2e20..74c5ccf9cd205 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -235,6 +235,7 @@ 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 b2966f0d21801..309eb753553b0 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -596,6 +596,7 @@ impl<'tcx> EmbargoVisitor<'tcx> { | DefKind::ForeignTy | DefKind::Fn | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::AssocFn | DefKind::Trait | DefKind::TyParam @@ -685,6 +686,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { } hir::ItemKind::OpaqueTy(..) + | hir::ItemKind::ImplTraitPlaceholder(..) | hir::ItemKind::Use(..) | hir::ItemKind::Static(..) | hir::ItemKind::Const(..) @@ -720,6 +722,9 @@ 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(..) diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 9cb735b36856c..81b67b758f7e1 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -972,6 +972,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { | DefKind::TyAlias | DefKind::ForeignTy | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::TraitAlias | DefKind::AssocTy, _, diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 101679aa6dc93..b72b033534b98 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -596,6 +596,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } } } + hir::ItemKind::ImplTraitPlaceholder(..) => { + // FIXME(RPITIT): We don't need to do anything here, right? + } hir::ItemKind::TyAlias(_, ref generics) | hir::ItemKind::Enum(_, ref generics) | hir::ItemKind::Struct(_, ref generics) diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs index 89bca39512f52..ebe44a56449d3 100644 --- a/compiler/rustc_save_analysis/src/lib.rs +++ b/compiler/rustc_save_analysis/src/lib.rs @@ -685,6 +685,7 @@ impl<'tcx> SaveContext<'tcx> { | HirDefKind::AssocTy | HirDefKind::Trait | HirDefKind::OpaqueTy + | HirDefKind::ImplTraitPlaceholder | HirDefKind::TyParam, def_id, ) => Some(Ref { kind: RefKind::Type, span, ref_id: id_from_def_id(def_id) }), diff --git a/compiler/rustc_save_analysis/src/sig.rs b/compiler/rustc_save_analysis/src/sig.rs index d1286c9b8b0df..ea9c82b3597d0 100644 --- a/compiler/rustc_save_analysis/src/sig.rs +++ b/compiler/rustc_save_analysis/src/sig.rs @@ -320,6 +320,10 @@ impl<'hir> Sig for hir::Ty<'hir> { let item = scx.tcx.hir().item(item_id); item.make(offset, Some(item_id.hir_id()), scx) } + hir::TyKind::ImplTraitInTrait(item_id) => { + let item = scx.tcx.hir().item(item_id); + item.make(offset, Some(item_id.hir_id()), scx) + } hir::TyKind::Typeof(_) | hir::TyKind::Infer | hir::TyKind::Err => Err("Ty"), } } @@ -562,6 +566,7 @@ impl<'hir> Sig for hir::Item<'hir> { 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"), // FIXME should implement this (e.g., pub use). hir::ItemKind::Use(..) => Err("import"), } diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index a77ea440aaaea..f0d8c240ea588 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -51,6 +51,7 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx ty::List dyn AstConv<'tcx> + 'o { ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i), } } + hir::TyKind::ImplTraitInTrait(..) => { + span_bug!(ast_ty.span, "not yet implemented") + } hir::TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => { debug!(?qself, ?segment); let ty = self.ast_ty_to_ty_inner(qself, false, true); diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index e70f728d7dcce..293a32051b9f9 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -815,6 +815,11 @@ 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(..) diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index a0280ddca4bd8..ded2ac1308e54 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -336,6 +336,9 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { 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::Trait(..) | ItemKind::TraitAlias(..) | ItemKind::Macro(..) diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index a9d511ae11e8b..395f213ca87c3 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -511,8 +511,8 @@ pub(crate) fn register_res(cx: &mut DocContext<'_>, res: Res) -> DefId { | Res::Err => return res.def_id(), Res::Def( TyParam | ConstParam | Ctor(..) | ExternCrate | Use | ForeignMod | AnonConst - | InlineConst | OpaqueTy | Field | LifetimeParam | GlobalAsm | Impl | Closure - | Generator, + | InlineConst | OpaqueTy | ImplTraitPlaceholder | Field | LifetimeParam | GlobalAsm + | Impl | Closure | Generator, id, ) => return id, }; From d34cb98fb0bbaf86860b4ad5ff0c3d79b077f565 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 31 Aug 2022 04:03:24 +0000 Subject: [PATCH 02/18] Lower RPITIT to ImplTraitPlaceholder item --- compiler/rustc_ast_lowering/src/lib.rs | 47 ++++++++++++++++++- compiler/rustc_feature/src/active.rs | 2 + compiler/rustc_hir/src/target.rs | 1 + compiler/rustc_middle/src/ty/error.rs | 5 +- compiler/rustc_middle/src/ty/sty.rs | 5 +- compiler/rustc_resolve/src/late/lifetimes.rs | 3 +- compiler/rustc_span/src/symbol.rs | 1 + .../src/traits/project.rs | 5 ++ compiler/rustc_typeck/src/astconv/mod.rs | 5 +- compiler/rustc_typeck/src/collect.rs | 5 ++ .../rustc_typeck/src/collect/item_bounds.rs | 28 +++++++++++ 11 files changed, 99 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index f57c92fd70c27..2e8fcd7dca45a 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -255,6 +255,8 @@ enum ImplTraitContext { }, /// Impl trait in type aliases. TypeAliasesOpaqueTy, + /// Return-position `impl Trait` in trait definition + InTrait, /// `impl Trait` is not accepted in this position. Disallowed(ImplTraitPosition), } @@ -323,9 +325,17 @@ enum FnDeclKind { } impl FnDeclKind { - fn impl_trait_return_allowed(&self) -> bool { + fn impl_trait_return_allowed(&self, tcx: TyCtxt<'_>) -> bool { match self { FnDeclKind::Fn | FnDeclKind::Inherent => true, + FnDeclKind::Impl if tcx.features().return_position_impl_trait_in_trait => true, + _ => false, + } + } + + fn impl_trait_in_trait_allowed(&self, tcx: TyCtxt<'_>) -> bool { + match self { + FnDeclKind::Trait if tcx.features().return_position_impl_trait_in_trait => true, _ => false, } } @@ -1346,6 +1356,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut nested_itctx, ) } + ImplTraitContext::InTrait => { + // FIXME(RPITIT): Should we use def_node_id here? + self.lower_impl_trait_in_trait(span, def_node_id, bounds) + } ImplTraitContext::Universal => { let span = t.span; let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span); @@ -1532,6 +1546,32 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes) } + #[tracing::instrument(level = "debug", skip(self))] + fn lower_impl_trait_in_trait( + &mut self, + span: Span, + opaque_ty_node_id: NodeId, + bounds: &GenericBounds, + ) -> 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| { + // FIXME(RPITIT): This should be a more descriptive ImplTraitPosition, i.e. nested RPITIT + // FIXME(RPITIT): We _also_ should support this eventually + let hir_bounds = lctx + .lower_param_bounds(bounds, ImplTraitContext::Disallowed(ImplTraitPosition::Trait)); + 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 }) + } + /// Registers a new opaque type with the proper `NodeId`s and /// returns the lowered node-ID for the opaque type. fn generate_opaque_type( @@ -1690,12 +1730,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { match decl.output { FnRetTy::Ty(ref ty) => { let mut context = match fn_node_id { - Some(fn_node_id) if kind.impl_trait_return_allowed() => { + Some(fn_node_id) if kind.impl_trait_return_allowed(self.tcx) => { let fn_def_id = self.local_def_id(fn_node_id); ImplTraitContext::ReturnPositionOpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), } } + Some(_) if kind.impl_trait_in_trait_allowed(self.tcx) => { + ImplTraitContext::InTrait + } _ => ImplTraitContext::Disallowed(match kind { FnDeclKind::Fn | FnDeclKind::Inherent => { unreachable!("fn should allow in-band lifetimes") diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index f71b3d59e2c04..3b8032040e76c 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -487,6 +487,8 @@ declare_features! ( (incomplete, repr128, "1.16.0", Some(56071), None), /// Allows `repr(simd)` and importing the various simd intrinsics. (active, repr_simd, "1.4.0", Some(27731), None), + /// Allows return-position `impl Trait` in traits. + (incomplete, return_position_impl_trait_in_trait, "CURRENT_RUSTC_VERSION", Some(91611), None), /// Allows `extern "rust-cold"`. (active, rust_cold_cc, "1.63.0", Some(97544), None), /// Allows the use of SIMD types in functions declared in `extern` blocks. diff --git a/compiler/rustc_hir/src/target.rs b/compiler/rustc_hir/src/target.rs index ea23c48cc5359..0e9b05729d29e 100644 --- a/compiler/rustc_hir/src/target.rs +++ b/compiler/rustc_hir/src/target.rs @@ -105,6 +105,7 @@ impl Target { DefKind::GlobalAsm => Target::GlobalAsm, DefKind::TyAlias => Target::TyAlias, DefKind::OpaqueTy => Target::OpaqueTy, + DefKind::ImplTraitPlaceholder => Target::ImplTraitPlaceholder, DefKind::Enum => Target::Enum, DefKind::Struct => Target::Struct, DefKind::Union => Target::Union, diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index da564c66a70e1..279c8c8d6d16d 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -2,6 +2,7 @@ use crate::traits::{ObligationCause, ObligationCauseCode}; use crate::ty::diagnostics::suggest_constraining_type_param; use crate::ty::print::{FmtPrinter, Printer}; use crate::ty::{self, BoundRegionKind, Region, Ty, TyCtxt}; +use hir::def::DefKind; use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect}; use rustc_errors::{pluralize, Diagnostic, MultiSpan}; use rustc_hir as hir; @@ -538,7 +539,7 @@ impl Trait for X { diag.span_label(p_span, "this type parameter"); } } - (ty::Projection(proj_ty), _) => { + (ty::Projection(proj_ty), _) if self.def_kind(proj_ty.item_def_id) != DefKind::ImplTraitPlaceholder => { self.expected_projection( diag, proj_ty, @@ -547,7 +548,7 @@ impl Trait for X { cause.code(), ); } - (_, ty::Projection(proj_ty)) => { + (_, ty::Projection(proj_ty)) if self.def_kind(proj_ty.item_def_id) != DefKind::ImplTraitPlaceholder => { let msg = format!( "consider constraining the associated type `{}` to `{}`", values.found, values.expected, diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 9fb91b5fe8700..c5c5d3473418c 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -11,6 +11,7 @@ use crate::ty::{ TypeVisitor, }; use crate::ty::{List, ParamEnv}; +use hir::def::DefKind; use polonius_engine::Atom; use rustc_data_structures::captures::Captures; use rustc_data_structures::intern::Interned; @@ -1196,7 +1197,9 @@ pub struct ProjectionTy<'tcx> { impl<'tcx> ProjectionTy<'tcx> { pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId { - tcx.parent(self.item_def_id) + let parent = tcx.parent(self.item_def_id); + assert_eq!(tcx.def_kind(parent), DefKind::Trait); + parent } /// Extracts the underlying trait reference and own substs from this projection. diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index b72b033534b98..e9e4f8fc483c5 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -597,7 +597,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } } hir::ItemKind::ImplTraitPlaceholder(..) => { - // FIXME(RPITIT): We don't need to do anything here, right? + // 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) diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 75b1dfc856ac7..4fd9e7407ce14 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1183,6 +1183,7 @@ symbols! { require, residual, result, + return_position_impl_trait_in_trait, rhs, rintf32, rintf64, diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 8a093bf4281cb..cd6b42be5ad7e 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1465,6 +1465,11 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( obligation: &ProjectionTyObligation<'tcx>, candidate_set: &mut ProjectionCandidateSet<'tcx>, ) { + // Can't assemble candidate from impl for RPITIT + if selcx.tcx().def_kind(obligation.predicate.item_def_id) == DefKind::ImplTraitPlaceholder { + return; + } + // If we are resolving `>::Item == Type`, // start out by selecting the predicate `T as TraitRef<...>`: let poly_trait_ref = ty::Binder::dummy(obligation.predicate.trait_ref(selcx.tcx())); diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 1f43221a420a6..6eec2c57639c6 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -2638,8 +2638,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i), } } - hir::TyKind::ImplTraitInTrait(..) => { - span_bug!(ast_ty.span, "not yet implemented") + 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); diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 293a32051b9f9..5429598871d99 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -1600,6 +1600,11 @@ 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_eq!(tcx.def_kind(parent_id), DefKind::AssocFn); + Some(parent_id) + } _ => None, }, _ => None, diff --git a/compiler/rustc_typeck/src/collect/item_bounds.rs b/compiler/rustc_typeck/src/collect/item_bounds.rs index 318e8f581f7c8..fe8d8f54f0477 100644 --- a/compiler/rustc_typeck/src/collect/item_bounds.rs +++ b/compiler/rustc_typeck/src/collect/item_bounds.rs @@ -74,6 +74,29 @@ 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, @@ -90,6 +113,11 @@ pub(super) fn explicit_item_bounds( 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), _ => bug!("item_bounds called on {:?}", def_id), } } From 4265ef8cb2946496b9de8be4b697a2b94bd92229 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 31 Aug 2022 04:41:16 +0000 Subject: [PATCH 03/18] Implement projection for ImplTraitPlaceholder --- compiler/rustc_privacy/src/lib.rs | 4 +- .../src/traits/project.rs | 117 ++++++++++++++++++ 2 files changed, 120 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 309eb753553b0..3657fb2134048 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -2038,7 +2038,9 @@ fn local_visibility(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Visibility { // Visibility on them should have no effect, but to avoid the 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(..), + kind: hir::ItemKind::Use(_, hir::UseKind::ListStem) + | hir::ItemKind::OpaqueTy(..) + | hir::ItemKind::ImplTraitPlaceholder(..), .. }) => ty::Visibility::Restricted(tcx.parent_module(hir_id)), // Visibilities of trait impl items are inherited from their traits diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index cd6b42be5ad7e..6ccb91c8cab69 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -32,6 +32,7 @@ use rustc_middle::traits::select::OverflowError; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::subst::Subst; use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable}; +use rustc_middle::ty::DefIdTree; use rustc_middle::ty::{self, Term, ToPredicate, Ty, TyCtxt}; use rustc_span::symbol::sym; @@ -70,6 +71,8 @@ enum ProjectionCandidate<'tcx> { /// From an "impl" (or a "pseudo-impl" returned by select) Select(Selection<'tcx>), + + ImplTraitInTrait(ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>), } enum ProjectionCandidateSet<'tcx> { @@ -1265,6 +1268,8 @@ fn project<'cx, 'tcx>( let mut candidates = ProjectionCandidateSet::None; + assemble_candidate_for_impl_trait_in_trait(selcx, obligation, &mut candidates); + // Make sure that the following procedures are kept in order. ParamEnv // needs to be first because it has highest priority, and Select checks // the return value of push_candidate which assumes it's ran at last. @@ -1303,6 +1308,48 @@ fn project<'cx, 'tcx>( } } +/// The first thing we have to do is scan through the parameter +/// environment to see whether there are any projection predicates +/// there that can answer this question. +fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>( + selcx: &mut SelectionContext<'cx, 'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + candidate_set: &mut ProjectionCandidateSet<'tcx>, +) { + let tcx = selcx.tcx(); + if tcx.def_kind(obligation.predicate.item_def_id) == DefKind::ImplTraitPlaceholder { + let trait_fn_def_id = tcx.parent(obligation.predicate.item_def_id); + let trait_def_id = tcx.parent(trait_fn_def_id); + let trait_substs = + obligation.predicate.substs.truncate_to(tcx, tcx.generics_of(trait_def_id)); + // FIXME(named-returns): Binders + let trait_predicate = + ty::Binder::dummy(ty::TraitRef { def_id: trait_def_id, substs: trait_substs }) + .to_poly_trait_predicate(); + + let _ = + selcx.infcx().commit_if_ok(|_| match selcx.select(&obligation.with(trait_predicate)) { + Ok(Some(super::ImplSource::UserDefined(data))) => { + candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(data)); + Ok(()) + } + Ok(None) => { + candidate_set.mark_ambiguous(); + return Err(()); + } + Ok(Some(_)) => { + // Don't know enough about the impl to provide a useful signature + return Err(()); + } + Err(e) => { + debug!(error = ?e, "selection error"); + candidate_set.mark_error(e); + return Err(()); + } + }); + } +} + /// The first thing we have to do is scan through the parameter /// environment to see whether there are any projection predicates /// there that can answer this question. @@ -1745,6 +1792,9 @@ fn confirm_candidate<'cx, 'tcx>( ProjectionCandidate::Select(impl_source) => { confirm_select_candidate(selcx, obligation, impl_source) } + ProjectionCandidate::ImplTraitInTrait(data) => { + confirm_impl_trait_in_trait_candidate(selcx, obligation, data) + } }; // When checking for cycle during evaluation, we compare predicates with @@ -2107,6 +2157,73 @@ fn confirm_impl_candidate<'cx, 'tcx>( } } +fn confirm_impl_trait_in_trait_candidate<'tcx>( + selcx: &mut SelectionContext<'_, 'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + data: ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>, +) -> Progress<'tcx> { + let tcx = selcx.tcx(); + let mut obligations = data.nested; + + let trait_fn_def_id = tcx.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 }; + }; + if !leaf_def.item.defaultness(tcx).has_value() { + return Progress { term: tcx.ty_error().into(), obligations }; + } + + let impl_fn_def_id = leaf_def.item.def_id; + let impl_fn_substs = obligation.predicate.substs.rebase_onto(tcx, trait_fn_def_id, data.substs); + + let sig = tcx + .bound_fn_sig(impl_fn_def_id) + .map_bound(|fn_sig| tcx.liberate_late_bound_regions(impl_fn_def_id, fn_sig)) + .subst(tcx, impl_fn_substs); + + let cause = ObligationCause::new( + obligation.cause.span, + obligation.cause.body_id, + super::ItemObligation(impl_fn_def_id), + ); + let predicates = normalize_with_depth_to( + selcx, + obligation.param_env, + cause.clone(), + obligation.recursion_depth + 1, + tcx.predicates_of(impl_fn_def_id).instantiate(tcx, impl_fn_substs), + &mut obligations, + ); + obligations.extend(std::iter::zip(predicates.predicates, predicates.spans).map( + |(pred, span)| { + Obligation::with_depth( + ObligationCause::new( + obligation.cause.span, + obligation.cause.body_id, + if span.is_dummy() { + super::ItemObligation(impl_fn_def_id) + } else { + super::BindingObligation(impl_fn_def_id, span) + }, + ), + obligation.recursion_depth + 1, + obligation.param_env, + pred, + ) + }, + )); + + let ty = super::normalize_to( + selcx, + obligation.param_env, + cause.clone(), + sig.output(), + &mut obligations, + ); + + Progress { term: ty.into(), obligations } +} + // Get obligations corresponding to the predicates from the where-clause of the // associated type itself. // Note: `feature(generic_associated_types)` is required to write such From a4d1807d6d19a446f2f620773d42b5de2dbed757 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 31 Aug 2022 04:41:20 +0000 Subject: [PATCH 04/18] Rustdoc support --- src/librustdoc/clean/mod.rs | 10 ++++++++++ src/librustdoc/formats/item_type.rs | 1 + src/librustdoc/passes/collect_intra_doc_links.rs | 4 ++-- src/librustdoc/visit_ast.rs | 1 + 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 66f766bfbe8d2..03752c9b6dbb7 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1500,6 +1500,16 @@ 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/formats/item_type.rs b/src/librustdoc/formats/item_type.rs index 0a7ee2005915b..f21e60a64e005 100644 --- a/src/librustdoc/formats/item_type.rs +++ b/src/librustdoc/formats/item_type.rs @@ -135,6 +135,7 @@ impl From for ItemType { | DefKind::AnonConst | DefKind::InlineConst | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::Field | DefKind::LifetimeParam | DefKind::GlobalAsm diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index c27f0ce18c141..cfd6ce402c28a 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -1805,8 +1805,8 @@ fn resolution_failure( } return; } - Trait | TyAlias | ForeignTy | OpaqueTy | TraitAlias | TyParam - | Static(_) => "associated item", + Trait | TyAlias | ForeignTy | OpaqueTy | ImplTraitPlaceholder + | TraitAlias | TyParam | Static(_) => "associated item", Impl | GlobalAsm => unreachable!("not a path"), } } else { diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index ca7a20bf3688a..7fe391f420f6a 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -362,6 +362,7 @@ 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)), From e8fa74ae45024d1120a73c15a3c21f675b25f1f4 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 31 Aug 2022 05:12:40 +0000 Subject: [PATCH 05/18] Check that impl types actually satisfy RPITIT bounds --- .../rustc_typeck/src/check/compare_method.rs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index b6bc244d2b144..e55f43994b9f3 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -391,6 +391,30 @@ fn compare_predicate_entailment<'tcx>( return Err(diag.emit()); } + // Check that an impl's fn return satisfies the bounds of the + // FIXME(RPITIT): Generalize this to nested impl traits + if let ty::Projection(proj) = tcx.fn_sig(trait_m.def_id).skip_binder().output().kind() + && tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder + { + let return_span = tcx.hir().fn_decl_by_hir_id(impl_m_hir_id).unwrap().output.span(); + + for (predicate, span) in tcx + .bound_explicit_item_bounds(proj.item_def_id) + .transpose_iter() + .map(|pred| pred.map_bound(|pred| *pred).subst(tcx, trait_to_placeholder_substs)) + { + ocx.register_obligation(traits::Obligation::new( + traits::ObligationCause::new( + return_span, + impl_m_hir_id, + ObligationCauseCode::BindingObligation(proj.item_def_id, span), + ), + param_env, + predicate, + )); + } + } + // Check that all obligations are satisfied by the implementation's // version. let errors = ocx.select_all_or_error(); From 81badff860091b4af165e6736b2a094e53c322a3 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 31 Aug 2022 04:46:54 +0000 Subject: [PATCH 06/18] Add tests --- ...ate-return_position_impl_trait_in_trait.rs | 5 +++ ...return_position_impl_trait_in_trait.stderr | 9 +++++ .../ui/impl-trait/in-trait/doesnt-satisfy.rs | 13 ++++++ .../impl-trait/in-trait/doesnt-satisfy.stderr | 17 ++++++++ .../in-trait/opaque-in-impl-is-opaque.rs | 19 +++++++++ .../in-trait/opaque-in-impl-is-opaque.stderr | 17 ++++++++ .../ui/impl-trait/in-trait/opaque-in-impl.rs | 20 ++++++++++ src/test/ui/impl-trait/in-trait/success.rs | 40 +++++++++++++++++++ 8 files changed, 140 insertions(+) create mode 100644 src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs create mode 100644 src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr create mode 100644 src/test/ui/impl-trait/in-trait/doesnt-satisfy.rs create mode 100644 src/test/ui/impl-trait/in-trait/doesnt-satisfy.stderr create mode 100644 src/test/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.rs create mode 100644 src/test/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.stderr create mode 100644 src/test/ui/impl-trait/in-trait/opaque-in-impl.rs create mode 100644 src/test/ui/impl-trait/in-trait/success.rs diff --git a/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs b/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs new file mode 100644 index 0000000000000..de7966c66b057 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs @@ -0,0 +1,5 @@ +trait Foo { + fn bar() -> impl Sized; //~ ERROR `impl Trait` only allowed in function and inherent method return types, not in trait method return +} + +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr b/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr new file mode 100644 index 0000000000000..a41f5789fdbfa --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr @@ -0,0 +1,9 @@ +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return + --> $DIR/feature-gate-return_position_impl_trait_in_trait.rs:2:17 + | +LL | fn bar() -> impl Sized; + | ^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0562`. diff --git a/src/test/ui/impl-trait/in-trait/doesnt-satisfy.rs b/src/test/ui/impl-trait/in-trait/doesnt-satisfy.rs new file mode 100644 index 0000000000000..bb4e0d44f3eff --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/doesnt-satisfy.rs @@ -0,0 +1,13 @@ +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +trait Foo { + fn bar() -> impl std::fmt::Display; +} + +impl Foo for () { + fn bar() -> () {} + //~^ ERROR `()` doesn't implement `std::fmt::Display` +} + +fn main() {} diff --git a/src/test/ui/impl-trait/in-trait/doesnt-satisfy.stderr b/src/test/ui/impl-trait/in-trait/doesnt-satisfy.stderr new file mode 100644 index 0000000000000..aa5492d285ed6 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/doesnt-satisfy.stderr @@ -0,0 +1,17 @@ +error[E0277]: `()` doesn't implement `std::fmt::Display` + --> $DIR/doesnt-satisfy.rs:9:17 + | +LL | fn bar() -> () {} + | ^^ `()` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `()` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `Foo::bar::{opaque#0}` + --> $DIR/doesnt-satisfy.rs:5:22 + | +LL | fn bar() -> impl std::fmt::Display; + | ^^^^^^^^^^^^^^^^^ required by this bound in `Foo::bar::{opaque#0}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.rs b/src/test/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.rs new file mode 100644 index 0000000000000..3ac264e8ebac5 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.rs @@ -0,0 +1,19 @@ +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::fmt::Display; + +trait Foo { + fn bar(&self) -> impl Display; +} + +impl Foo for () { + fn bar(&self) -> impl Display { + "Hello, world" + } +} + +fn main() { + let x: &str = ().bar(); + //~^ ERROR mismatched types +} diff --git a/src/test/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.stderr b/src/test/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.stderr new file mode 100644 index 0000000000000..15edda4834015 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/opaque-in-impl-is-opaque.rs:17:19 + | +LL | fn bar(&self) -> impl Display { + | ------------ the found opaque type +... +LL | let x: &str = ().bar(); + | ---- ^^^^^^^^ expected `&str`, found opaque type + | | + | expected due to this + | + = note: expected reference `&str` + found opaque type `impl std::fmt::Display` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. 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 new file mode 100644 index 0000000000000..a777cbcd529a6 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/opaque-in-impl.rs @@ -0,0 +1,20 @@ +// check-pass + +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::fmt::Display; + +trait Foo { + fn bar(&self) -> impl Display; +} + +impl Foo for () { + fn bar(&self) -> impl Display { + "Hello, world" + } +} + +fn main() { + println!("{}", ().bar()); +} diff --git a/src/test/ui/impl-trait/in-trait/success.rs b/src/test/ui/impl-trait/in-trait/success.rs new file mode 100644 index 0000000000000..4cbe682b46f73 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/success.rs @@ -0,0 +1,40 @@ +// check-pass + +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::fmt::Display; + +trait Foo { + fn bar(&self) -> impl Display; +} + +impl Foo for i32 { + fn bar(&self) -> i32 { + *self + } +} + +impl Foo for &'static str { + fn bar(&self) -> &'static str { + *self + } +} + +struct Yay; + +impl Foo for Yay { + fn bar(&self) -> String { + String::from(":^)") + } +} + +fn foo_generically(t: T) { + println!("{}", t.bar()); +} + +fn main() { + println!("{}", "Hello, world.".bar()); + println!("The answer is {}!", 42.bar()); + foo_generically(Yay); +} From ed2a32f22cfb7e43a3d8c732ac8fa8007c061c5f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 31 Aug 2022 05:29:36 +0000 Subject: [PATCH 07/18] Make clippy happy --- src/tools/clippy/clippy_lints/src/dereference.rs | 2 +- src/tools/clippy/clippy_lints/src/missing_doc.rs | 3 ++- src/tools/clippy/clippy_lints/src/missing_inline.rs | 1 + src/tools/clippy/clippy_utils/src/hir_utils.rs | 3 +++ 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index d1ab7fb67962e..09a073f4234d0 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -959,7 +959,7 @@ fn binding_ty_auto_deref_stability<'tcx>( )) .is_sized(cx.tcx.at(DUMMY_SP), cx.param_env.without_caller_bounds()), ), - TyKind::OpaqueDef(..) | TyKind::Infer | TyKind::Typeof(..) | TyKind::TraitObject(..) | TyKind::Err => { + TyKind::OpaqueDef(..) | TyKind::ImplTraitInTrait(..) | TyKind::Infer | TyKind::Typeof(..) | TyKind::TraitObject(..) | TyKind::Err => { Position::ReborrowStable(precedence) }, }; diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs index 3701fdb4adbff..9f518c7aaa39f 100644 --- a/src/tools/clippy/clippy_lints/src/missing_doc.rs +++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs @@ -147,7 +147,8 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { | hir::ItemKind::TraitAlias(..) | hir::ItemKind::TyAlias(..) | hir::ItemKind::Union(..) - | hir::ItemKind::OpaqueTy(..) => {}, + | hir::ItemKind::OpaqueTy(..) + | hir::ItemKind::ImplTraitPlaceholder(..) => {}, hir::ItemKind::ExternCrate(..) | hir::ItemKind::ForeignMod { .. } | hir::ItemKind::GlobalAsm(..) diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs index 07bc2ca5d3cd2..9fd1a475d7496 100644 --- a/src/tools/clippy/clippy_lints/src/missing_inline.rs +++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs @@ -128,6 +128,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { | hir::ItemKind::TyAlias(..) | hir::ItemKind::Union(..) | hir::ItemKind::OpaqueTy(..) + | hir::ItemKind::ImplTraitPlaceholder(..) | hir::ItemKind::ExternCrate(..) | hir::ItemKind::ForeignMod { .. } | hir::ItemKind::Impl { .. } diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index ff23ed5fffa3c..9f8500d41a85f 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -990,6 +990,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { TyKind::OpaqueDef(_, arg_list) => { self.hash_generic_args(arg_list); }, + TyKind::ImplTraitInTrait(_) => { + // Do nothing + } TyKind::TraitObject(_, lifetime, _) => { self.hash_lifetime(*lifetime); }, From 5be30f9d79b2e08128704ddb29f7925e2fb3ef88 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 2 Sep 2022 15:57:31 +0000 Subject: [PATCH 08/18] Make async fn in traits work --- compiler/rustc_ast/src/ast.rs | 4 ++-- compiler/rustc_ast_lowering/src/errors.rs | 11 ++++++++++ compiler/rustc_ast_lowering/src/expr.rs | 5 +++-- compiler/rustc_ast_lowering/src/item.rs | 14 +++++++++---- compiler/rustc_ast_lowering/src/lib.rs | 21 ++++++++++++------- .../rustc_ast_passes/src/ast_validation.rs | 7 ------- compiler/rustc_ast_passes/src/errors.rs | 11 ---------- .../locales/en-US/ast_lowering.ftl | 6 ++++++ .../locales/en-US/ast_passes.ftl | 6 ------ compiler/rustc_resolve/src/late.rs | 2 +- 10 files changed, 46 insertions(+), 41 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index e38572f609b31..c07ba88ae204d 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2367,9 +2367,9 @@ impl Async { } /// In this case this is an `async` return, the `NodeId` for the generated `impl Trait` item. - pub fn opt_return_id(self) -> Option { + pub fn opt_return_id(self) -> Option<(NodeId, Span)> { match self { - Async::Yes { return_impl_trait_id, .. } => Some(return_impl_trait_id), + Async::Yes { return_impl_trait_id, span, .. } => Some((return_impl_trait_id, span)), Async::No => None, } } diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index 4adeaef9bbfa8..c87d0ca96570e 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -334,3 +334,14 @@ pub struct InclusiveRangeWithNoEnd { #[primary_span] pub span: Span, } + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::trait_fn_async, code = "E0706")] +#[note] +#[note(ast_lowering::note2)] +pub struct TraitFnAsync { + #[primary_span] + pub fn_span: Span, + #[label] + pub span: Span, +} diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 5346f1ced8294..f929549d70448 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -851,7 +851,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_lifetime_binder(closure_id, generic_params, |lctx, bound_generic_params| { // Lower outside new scope to preserve `is_in_loop_condition`. - let fn_decl = lctx.lower_fn_decl(decl, None, FnDeclKind::Closure, None); + let fn_decl = lctx.lower_fn_decl(decl, None, fn_decl_span, FnDeclKind::Closure, None); let c = lctx.arena.alloc(hir::Closure { binder: binder_clause, @@ -955,7 +955,8 @@ impl<'hir> LoweringContext<'_, 'hir> { // We need to lower the declaration outside the new scope, because we // have to conserve the state of being inside a loop condition for the // closure argument types. - let fn_decl = lctx.lower_fn_decl(&outer_decl, None, FnDeclKind::Closure, None); + let fn_decl = + lctx.lower_fn_decl(&outer_decl, None, fn_decl_span, FnDeclKind::Closure, None); let c = lctx.arena.alloc(hir::Closure { binder: binder_clause, diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 9e05fbbdc1976..96e281ca5c844 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -269,7 +269,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let mut itctx = ImplTraitContext::Universal; let (generics, decl) = this.lower_generics(generics, id, &mut itctx, |this| { let ret_id = asyncness.opt_return_id(); - this.lower_fn_decl(&decl, Some(id), FnDeclKind::Fn, ret_id) + this.lower_fn_decl(&decl, Some(id), fn_sig_span, FnDeclKind::Fn, ret_id) }); let sig = hir::FnSig { decl, @@ -661,7 +661,13 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_generics(generics, i.id, &mut itctx, |this| { ( // Disallow `impl Trait` in foreign items. - this.lower_fn_decl(fdec, None, FnDeclKind::ExternFn, None), + this.lower_fn_decl( + fdec, + None, + sig.span, + FnDeclKind::ExternFn, + None, + ), this.lower_fn_params_to_names(fdec), ) }); @@ -1240,12 +1246,12 @@ impl<'hir> LoweringContext<'_, 'hir> { sig: &FnSig, id: NodeId, kind: FnDeclKind, - is_async: Option, + is_async: Option<(NodeId, Span)>, ) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) { let header = self.lower_fn_header(sig.header); let mut itctx = ImplTraitContext::Universal; let (generics, decl) = self.lower_generics(generics, id, &mut itctx, |this| { - this.lower_fn_decl(&sig.decl, Some(id), kind, is_async) + this.lower_fn_decl(&sig.decl, Some(id), sig.span, kind, is_async) }); (generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) }) } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 2e8fcd7dca45a..de7e64351b948 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -42,7 +42,7 @@ #[macro_use] extern crate tracing; -use crate::errors::{AssocTyParentheses, AssocTyParenthesesSub, MisplacedImplTrait}; +use crate::errors::{AssocTyParentheses, AssocTyParenthesesSub, MisplacedImplTrait, TraitFnAsync}; use rustc_arena::declare_arena; use rustc_ast::ptr::P; @@ -1274,7 +1274,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { generic_params, unsafety: lctx.lower_unsafety(f.unsafety), abi: lctx.lower_extern(f.ext), - decl: lctx.lower_fn_decl(&f.decl, None, FnDeclKind::Pointer, None), + decl: lctx.lower_fn_decl(&f.decl, None, t.span, FnDeclKind::Pointer, None), param_names: lctx.lower_fn_params_to_names(&f.decl), })) }) @@ -1677,19 +1677,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // `fn_def_id`: if `Some`, impl Trait arguments are lowered into generic parameters on the // given DefId, otherwise impl Trait is disallowed. Must be `Some` if // `make_ret_async` is also `Some`. - // `impl_trait_return_allow`: determines whether `impl Trait` can be used in return position. - // This guards against trait declarations and implementations where `impl Trait` is - // disallowed. // `make_ret_async`: if `Some`, converts `-> T` into `-> impl Future` in the // return type. This is used for `async fn` declarations. The `NodeId` is the ID of the - // return type `impl Trait` item. + // return type `impl Trait` item, and the `Span` points to the `async` keyword. #[instrument(level = "debug", skip(self))] fn lower_fn_decl( &mut self, decl: &FnDecl, fn_node_id: Option, + fn_span: Span, kind: FnDeclKind, - make_ret_async: Option, + make_ret_async: Option<(NodeId, Span)>, ) -> &'hir hir::FnDecl<'hir> { let c_variadic = decl.c_variadic(); @@ -1720,7 +1718,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } })); - let output = if let Some(ret_id) = make_ret_async { + let output = if let Some((ret_id, span)) = make_ret_async { + if !self.tcx.features().return_position_impl_trait_in_trait { + self.tcx.sess.emit_feature_err( + TraitFnAsync { fn_span, span }, + sym::return_position_impl_trait_in_trait, + ); + } + self.lower_async_fn_ret_ty( &decl.output, fn_node_id.expect("`make_ret_async` but no `fn_def_id`"), diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index d6d8881a53a14..6c754f38d144b 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -290,12 +290,6 @@ impl<'a> AstValidator<'a> { } } - fn check_trait_fn_not_async(&self, fn_span: Span, asyncness: Async) { - if let Async::Yes { span, .. } = asyncness { - self.session.emit_err(TraitFnAsync { fn_span, span }); - } - } - fn check_trait_fn_not_const(&self, constness: Const) { if let Const::Yes(span) = constness { self.session.emit_err(TraitFnConst { span }); @@ -1596,7 +1590,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.invalid_visibility(&item.vis, None); if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind { self.check_trait_fn_not_const(sig.header.constness); - self.check_trait_fn_not_async(item.span, sig.header.asyncness); } } diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 21467e5765198..4f3b09c587113 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -79,17 +79,6 @@ pub enum InvalidVisibilityNote { IndividualForeignItems, } -#[derive(SessionDiagnostic)] -#[diag(ast_passes::trait_fn_async, code = "E0706")] -#[note] -#[note(ast_passes::note2)] -pub struct TraitFnAsync { - #[primary_span] - pub fn_span: Span, - #[label] - pub span: Span, -} - #[derive(SessionDiagnostic)] #[diag(ast_passes::trait_fn_const, code = "E0379")] pub struct TraitFnConst { diff --git a/compiler/rustc_error_messages/locales/en-US/ast_lowering.ftl b/compiler/rustc_error_messages/locales/en-US/ast_lowering.ftl index f2790531aba44..c45e045b4dba0 100644 --- a/compiler/rustc_error_messages/locales/en-US/ast_lowering.ftl +++ b/compiler/rustc_error_messages/locales/en-US/ast_lowering.ftl @@ -131,3 +131,9 @@ ast_lowering_arbitrary_expression_in_pattern = arbitrary expressions aren't allowed in patterns ast_lowering_inclusive_range_with_no_end = inclusive range with no end + +ast_lowering_trait_fn_async = + functions in traits cannot be declared `async` + .label = `async` because of this + .note = `async` trait functions are not currently supported + .note2 = consider using the `async-trait` crate: https://crates.io/crates/async-trait diff --git a/compiler/rustc_error_messages/locales/en-US/ast_passes.ftl b/compiler/rustc_error_messages/locales/en-US/ast_passes.ftl index d7108e1e2de35..e5cd1142b20c8 100644 --- a/compiler/rustc_error_messages/locales/en-US/ast_passes.ftl +++ b/compiler/rustc_error_messages/locales/en-US/ast_passes.ftl @@ -26,12 +26,6 @@ ast_passes_invalid_visibility = .individual_impl_items = place qualifiers on individual impl items instead .individual_foreign_items = place qualifiers on individual foreign items instead -ast_passes_trait_fn_async = - functions in traits cannot be declared `async` - .label = `async` because of this - .note = `async` trait functions are not currently supported - .note2 = consider using the `async-trait` crate: https://crates.io/crates/async-trait - ast_passes_trait_fn_const = functions in traits cannot be declared const .label = functions in traits cannot be const diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index b37feb15890ba..2d6e76c451bfa 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -851,7 +851,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { // We include all lifetime parameters, either named or "Fresh". // The order of those parameters does not matter, as long as it is // deterministic. - if let Some(async_node_id) = async_node_id { + if let Some((async_node_id, _)) = async_node_id { let mut extra_lifetime_params = this .r .extra_lifetime_params_map From 249ede4195a40147c45411f1fa27e376d40f4f95 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 2 Sep 2022 16:45:30 +0000 Subject: [PATCH 09/18] Address rebase issues, make async fn in trait work --- compiler/rustc_ast_lowering/src/item.rs | 10 ++- compiler/rustc_ast_lowering/src/lib.rs | 92 ++++++++++++++++---- compiler/rustc_metadata/src/rmeta/encoder.rs | 6 +- 3 files changed, 89 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 96e281ca5c844..52273778dcc00 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -777,9 +777,15 @@ impl<'hir> LoweringContext<'_, 'hir> { (hir::Generics::empty(), hir::TraitItemKind::Const(ty, body), body.is_some()) } AssocItemKind::Fn(box Fn { ref sig, ref generics, body: None, .. }) => { + let asyncness = sig.header.asyncness; let names = self.lower_fn_params_to_names(&sig.decl); - let (generics, sig) = - self.lower_method_sig(generics, sig, i.id, FnDeclKind::Trait, None); + let (generics, sig) = self.lower_method_sig( + generics, + sig, + i.id, + FnDeclKind::Trait, + asyncness.opt_return_id(), + ); (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false) } AssocItemKind::Fn(box Fn { ref sig, ref generics, body: Some(ref body), .. }) => { diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index de7e64351b948..8814d184c5589 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1358,7 +1358,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } ImplTraitContext::InTrait => { // FIXME(RPITIT): Should we use def_node_id here? - self.lower_impl_trait_in_trait(span, def_node_id, bounds) + self.lower_impl_trait_in_trait(span, def_node_id, |lctx| { + lctx.lower_param_bounds( + bounds, + ImplTraitContext::Disallowed(ImplTraitPosition::Trait), + ) + }) } ImplTraitContext::Universal => { let span = t.span; @@ -1546,19 +1551,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes) } - #[tracing::instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self, lower_bounds))] fn lower_impl_trait_in_trait( &mut self, span: Span, opaque_ty_node_id: NodeId, - bounds: &GenericBounds, + 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| { // FIXME(RPITIT): This should be a more descriptive ImplTraitPosition, i.e. nested RPITIT // FIXME(RPITIT): We _also_ should support this eventually - let hir_bounds = lctx - .lower_param_bounds(bounds, ImplTraitContext::Disallowed(ImplTraitPosition::Trait)); + 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, @@ -1719,18 +1723,44 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { })); let output = if let Some((ret_id, span)) = make_ret_async { - if !self.tcx.features().return_position_impl_trait_in_trait { - self.tcx.sess.emit_feature_err( - TraitFnAsync { fn_span, span }, - sym::return_position_impl_trait_in_trait, - ); + match kind { + FnDeclKind::Trait => { + if !kind.impl_trait_in_trait_allowed(self.tcx) { + self.tcx + .sess + .create_feature_err( + TraitFnAsync { fn_span, span }, + sym::return_position_impl_trait_in_trait, + ) + .emit(); + } + self.lower_async_fn_ret_ty_in_trait( + &decl.output, + fn_node_id.expect("`make_ret_async` but no `fn_def_id`"), + ret_id, + ) + } + _ => { + 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.lower_async_fn_ret_ty( + &decl.output, + fn_node_id.expect("`make_ret_async` but no `fn_def_id`"), + ret_id, + ) + } } - - self.lower_async_fn_ret_ty( - &decl.output, - fn_node_id.expect("`make_ret_async` but no `fn_def_id`"), - ret_id, - ) } else { match decl.output { FnRetTy::Ty(ref ty) => { @@ -2020,6 +2050,36 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { 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 span = output.span(); + + let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::Async, span, None); + + let fn_def_id = self.local_def_id(fn_node_id); + + 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, fn_def_id, output.span()); + arena_vec![lctx; bound] + }); + 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_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 02ca34181cd0b..d45d814c3b0f0 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1036,6 +1036,7 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) -> | DefKind::Static(..) | DefKind::TyAlias | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::ForeignTy | DefKind::Impl | DefKind::AssocFn @@ -1085,6 +1086,7 @@ fn should_encode_const(def_kind: DefKind) -> bool { | DefKind::Static(..) | DefKind::TyAlias | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::ForeignTy | DefKind::Impl | DefKind::AssocFn @@ -1497,7 +1499,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } hir::ItemKind::OpaqueTy(..) => { self.encode_explicit_item_bounds(def_id); - EntryKind::OpaqueTy + } + hir::ItemKind::ImplTraitPlaceholder(..) => { + self.encode_explicit_item_bounds(def_id); } hir::ItemKind::Enum(..) => { let adt_def = self.tcx.adt_def(def_id); From 70775304cd83bf01bf91d5cf206923064fca68ef Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 2 Sep 2022 16:55:24 +0000 Subject: [PATCH 10/18] Address nits --- compiler/rustc_ast_lowering/src/lib.rs | 1 - compiler/rustc_hir/src/def.rs | 4 ++-- compiler/rustc_hir/src/hir.rs | 5 ++++- compiler/rustc_trait_selection/src/traits/project.rs | 6 +++--- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 8814d184c5589..8fa2c593193e5 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1357,7 +1357,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) } ImplTraitContext::InTrait => { - // FIXME(RPITIT): Should we use def_node_id here? self.lower_impl_trait_in_trait(span, def_node_id, |lctx| { lctx.lower_param_bounds( bounds, diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 8563b588585bd..e7c26bd726fbf 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -193,7 +193,6 @@ impl DefKind { | DefKind::Variant | DefKind::Trait | DefKind::OpaqueTy - | DefKind::ImplTraitPlaceholder | DefKind::TyAlias | DefKind::ForeignTy | DefKind::TraitAlias @@ -221,7 +220,8 @@ impl DefKind { | DefKind::Use | DefKind::ForeignMod | DefKind::GlobalAsm - | DefKind::Impl => None, + | DefKind::Impl + | DefKind::ImplTraitPlaceholder => None, } } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 334d4fd0b042b..8b1ebe34cb00f 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2551,7 +2551,10 @@ 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>]), - /// The placeholder + /// 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), /// A trait object type `Bound1 + Bound2 + Bound3` /// where `Bound` is a trait or a lifetime. diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 6ccb91c8cab69..6c9efea8ca87f 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1308,9 +1308,9 @@ fn project<'cx, 'tcx>( } } -/// The first thing we have to do is scan through the parameter -/// environment to see whether there are any projection predicates -/// there that can answer this question. +/// If the predicate's item is an `ImplTraitPlaceholder`, we do a select on the +/// corresponding trait ref. If this yields an `impl`, then we're able to project +/// to a concrete type, since we have an `impl`'s method to provide the RPITIT. fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, From 1f03edeabe7a2ba1eed35cd7beb93c1bc0364bc5 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 2 Sep 2022 17:54:58 +0000 Subject: [PATCH 11/18] Bless tests, fix ICE with ImplTraitPlaceholder --- compiler/rustc_ast_lowering/src/lib.rs | 31 +-- compiler/rustc_typeck/src/check/closure.rs | 12 +- src/test/ui/async-await/async-trait-fn.rs | 3 + src/test/ui/async-await/async-trait-fn.stderr | 75 +++++-- .../edition-deny-async-fns-2015.rs | 3 +- .../edition-deny-async-fns-2015.stderr | 30 ++- .../ui/async-await/issues/issue-95307.stderr | 2 + src/test/ui/parser/fn-header-semantic-fail.rs | 2 - .../ui/parser/fn-header-semantic-fail.stderr | 184 ++++++++---------- ...ue-70736-async-fn-no-body-def-collector.rs | 1 - ...0736-async-fn-no-body-def-collector.stderr | 43 ++-- ...021-incompatible-closure-captures-93117.rs | 5 +- ...incompatible-closure-captures-93117.stderr | 46 +++-- 13 files changed, 245 insertions(+), 192 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 8fa2c593193e5..e8201c0ddcaeb 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1960,8 +1960,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // // Then, we will create `fn foo(..) -> Foo<'_, '_>`, and // hence the elision takes place at the fn site. - let future_bound = - this.lower_async_fn_output_type_to_future_bound(output, fn_def_id, span); + let future_bound = this.lower_async_fn_output_type_to_future_bound( + output, + span, + ImplTraitContext::ReturnPositionOpaqueTy { + origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), + }, + ); let generic_params = this.arena.alloc_from_iter(collected_lifetimes.iter().map( |&(new_node_id, lifetime, _)| { @@ -2064,17 +2069,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn_node_id: NodeId, opaque_ty_node_id: NodeId, ) -> hir::FnRetTy<'hir> { - let span = output.span(); - - let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::Async, span, None); - - let fn_def_id = self.local_def_id(fn_node_id); - 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, fn_def_id, output.span()); + let bound = lctx.lower_async_fn_output_type_to_future_bound( + output, + output.span(), + ImplTraitContext::Disallowed(ImplTraitPosition::TraitReturn), + ); 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)) } @@ -2083,8 +2087,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_async_fn_output_type_to_future_bound( &mut self, output: &FnRetTy, - fn_def_id: LocalDefId, span: Span, + mut nested_impl_trait_context: ImplTraitContext, ) -> hir::GenericBound<'hir> { // Compute the `T` in `Future` from the return type. let output_ty = match output { @@ -2092,10 +2096,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Not `OpaqueTyOrigin::AsyncFn`: that's only used for the // `impl Future` opaque type that `async fn` implicitly // generates. - let mut context = ImplTraitContext::ReturnPositionOpaqueTy { - origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), - }; - self.lower_ty(ty, &mut context) + self.lower_ty(ty, &mut nested_impl_trait_context) } FnRetTy::Default(ret_ty_span) => self.arena.alloc(self.ty_tup(*ret_ty_span, &[])), }; diff --git a/compiler/rustc_typeck/src/check/closure.rs b/compiler/rustc_typeck/src/check/closure.rs index bc3fec6e7d66a..55cbaf71e7cfd 100644 --- a/compiler/rustc_typeck/src/check/closure.rs +++ b/compiler/rustc_typeck/src/check/closure.rs @@ -4,6 +4,7 @@ use super::{check_fn, Expectation, FnCtxt, GeneratorTypes}; use crate::astconv::AstConv; use crate::rustc_middle::ty::subst::Subst; +use hir::def::DefKind; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; @@ -680,9 +681,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .map(|e| e.map_bound(|e| *e).transpose_tuple2()) .find_map(|(p, s)| get_future_output(p.subst(self.tcx, substs), s.0))?, ty::Error(_) => return None, + ty::Projection(proj) + if self.tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder => + { + self.tcx + .bound_explicit_item_bounds(proj.item_def_id) + .transpose_iter() + .map(|e| e.map_bound(|e| *e).transpose_tuple2()) + .find_map(|(p, s)| get_future_output(p.subst(self.tcx, proj.substs), s.0))? + } _ => span_bug!( self.tcx.def_span(expr_def_id), - "async fn generator return type not an inference variable" + "async fn generator return type not an inference variable: {ret_ty}" ), }; diff --git a/src/test/ui/async-await/async-trait-fn.rs b/src/test/ui/async-await/async-trait-fn.rs index e2062e82725c0..0ea685986db40 100644 --- a/src/test/ui/async-await/async-trait-fn.rs +++ b/src/test/ui/async-await/async-trait-fn.rs @@ -1,8 +1,11 @@ // edition:2018 trait T { async fn foo() {} //~ ERROR functions in traits cannot be declared `async` + //~^ ERROR mismatched types async fn bar(&self) {} //~ ERROR functions in traits cannot be declared `async` + //~^ ERROR mismatched types async fn baz() { //~ ERROR functions in traits cannot be declared `async` + //~^ ERROR mismatched types // Nested item must not ICE. fn a() {} } diff --git a/src/test/ui/async-await/async-trait-fn.stderr b/src/test/ui/async-await/async-trait-fn.stderr index 1eb8969a80d20..e30dfb1e1a705 100644 --- a/src/test/ui/async-await/async-trait-fn.stderr +++ b/src/test/ui/async-await/async-trait-fn.stderr @@ -2,40 +2,89 @@ error[E0706]: functions in traits cannot be declared `async` --> $DIR/async-trait-fn.rs:3:5 | LL | async fn foo() {} - | -----^^^^^^^^^^^^ + | -----^^^^^^^^^ | | | `async` because of this | = note: `async` trait functions are not currently supported = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable error[E0706]: functions in traits cannot be declared `async` - --> $DIR/async-trait-fn.rs:4:5 + --> $DIR/async-trait-fn.rs:5:5 | LL | async fn bar(&self) {} - | -----^^^^^^^^^^^^^^^^^ + | -----^^^^^^^^^^^^^^ | | | `async` because of this | = note: `async` trait functions are not currently supported = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable error[E0706]: functions in traits cannot be declared `async` - --> $DIR/async-trait-fn.rs:5:5 + --> $DIR/async-trait-fn.rs:7:5 + | +LL | async fn baz() { + | -----^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + +error[E0308]: mismatched types + --> $DIR/async-trait-fn.rs:3:20 + | +LL | async fn foo() {} + | ^^ expected associated type, found opaque type + | + ::: $SRC_DIR/core/src/future/mod.rs:LL:COL + | +LL | pub const fn from_generator(gen: T) -> impl Future + | ------------------------------- the found opaque type + | + = note: expected associated type `::foo::{opaque#0}` + found opaque type `impl Future` + +error[E0308]: mismatched types + --> $DIR/async-trait-fn.rs:5:25 + | +LL | async fn bar(&self) {} + | ^^ expected associated type, found opaque type + | + ::: $SRC_DIR/core/src/future/mod.rs:LL:COL + | +LL | pub const fn from_generator(gen: T) -> impl Future + | ------------------------------- the found opaque type + | + = note: expected associated type `::bar::{opaque#0}` + found opaque type `impl Future` + +error[E0308]: mismatched types + --> $DIR/async-trait-fn.rs:7:20 | LL | async fn baz() { - | ^---- - | | - | _____`async` because of this - | | + | ____________________^ +LL | | LL | | // Nested item must not ICE. LL | | fn a() {} LL | | } - | |_____^ + | |_____^ expected associated type, found opaque type | - = note: `async` trait functions are not currently supported - = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + ::: $SRC_DIR/core/src/future/mod.rs:LL:COL + | +LL | pub const fn from_generator(gen: T) -> impl Future + | ------------------------------- the found opaque type + | + = note: expected associated type `::baz::{opaque#0}` + found opaque type `impl Future` -error: aborting due to 3 previous errors +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0706`. +Some errors have detailed explanations: E0308, E0706. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/async-await/edition-deny-async-fns-2015.rs b/src/test/ui/async-await/edition-deny-async-fns-2015.rs index e5dc9c8a5fee8..22a61dcd25f98 100644 --- a/src/test/ui/async-await/edition-deny-async-fns-2015.rs +++ b/src/test/ui/async-await/edition-deny-async-fns-2015.rs @@ -16,7 +16,8 @@ impl Foo { trait Bar { async fn foo() {} //~ ERROR `async fn` is not permitted in Rust 2015 - //~^ ERROR functions in traits cannot be declared `async` + //~^ ERROR functions in traits cannot be declared `async` + //~| ERROR mismatched types } fn main() { diff --git a/src/test/ui/async-await/edition-deny-async-fns-2015.stderr b/src/test/ui/async-await/edition-deny-async-fns-2015.stderr index 35f9c581c7b21..2f40ef1ccbb14 100644 --- a/src/test/ui/async-await/edition-deny-async-fns-2015.stderr +++ b/src/test/ui/async-await/edition-deny-async-fns-2015.stderr @@ -53,7 +53,7 @@ LL | async fn foo() {} = note: for more on editions, read https://doc.rust-lang.org/edition-guide error[E0670]: `async fn` is not permitted in Rust 2015 - --> $DIR/edition-deny-async-fns-2015.rs:36:9 + --> $DIR/edition-deny-async-fns-2015.rs:37:9 | LL | async fn bar() {} | ^^^^^ to use `async fn`, switch to Rust 2018 or later @@ -62,7 +62,7 @@ LL | async fn bar() {} = note: for more on editions, read https://doc.rust-lang.org/edition-guide error[E0670]: `async fn` is not permitted in Rust 2015 - --> $DIR/edition-deny-async-fns-2015.rs:26:9 + --> $DIR/edition-deny-async-fns-2015.rs:27:9 | LL | async fn foo() {} | ^^^^^ to use `async fn`, switch to Rust 2018 or later @@ -71,7 +71,7 @@ LL | async fn foo() {} = note: for more on editions, read https://doc.rust-lang.org/edition-guide error[E0670]: `async fn` is not permitted in Rust 2015 - --> $DIR/edition-deny-async-fns-2015.rs:31:13 + --> $DIR/edition-deny-async-fns-2015.rs:32:13 | LL | async fn bar() {} | ^^^^^ to use `async fn`, switch to Rust 2018 or later @@ -83,14 +83,30 @@ error[E0706]: functions in traits cannot be declared `async` --> $DIR/edition-deny-async-fns-2015.rs:18:5 | LL | async fn foo() {} - | -----^^^^^^^^^^^^ + | -----^^^^^^^^^ | | | `async` because of this | = note: `async` trait functions are not currently supported = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable -error: aborting due to 10 previous errors +error[E0308]: mismatched types + --> $DIR/edition-deny-async-fns-2015.rs:18:20 + | +LL | async fn foo() {} + | ^^ expected associated type, found opaque type + | + ::: $SRC_DIR/core/src/future/mod.rs:LL:COL + | +LL | pub const fn from_generator(gen: T) -> impl Future + | ------------------------------- the found opaque type + | + = note: expected associated type `::foo::{opaque#0}` + found opaque type `impl Future` + +error: aborting due to 11 previous errors -Some errors have detailed explanations: E0670, E0706. -For more information about an error, try `rustc --explain E0670`. +Some errors have detailed explanations: E0308, E0670, E0706. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/async-await/issues/issue-95307.stderr b/src/test/ui/async-await/issues/issue-95307.stderr index 29aebb719d66f..1c12f1e4862e8 100644 --- a/src/test/ui/async-await/issues/issue-95307.stderr +++ b/src/test/ui/async-await/issues/issue-95307.stderr @@ -8,6 +8,8 @@ LL | async fn new() -> [u8; _]; | = note: `async` trait functions are not currently supported = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable error: in expressions, `_` can only be used on the left-hand side of an assignment --> $DIR/issue-95307.rs:7:28 diff --git a/src/test/ui/parser/fn-header-semantic-fail.rs b/src/test/ui/parser/fn-header-semantic-fail.rs index 8ff14fb1f304a..cf5d3dab4aada 100644 --- a/src/test/ui/parser/fn-header-semantic-fail.rs +++ b/src/test/ui/parser/fn-header-semantic-fail.rs @@ -27,7 +27,6 @@ fn main() { struct Y; impl X for Y { async fn ft1() {} //~ ERROR functions in traits cannot be declared `async` - //~^ ERROR has an incompatible type for trait unsafe fn ft2() {} // OK. const fn ft3() {} //~ ERROR functions in traits cannot be declared const extern "C" fn ft4() {} @@ -36,7 +35,6 @@ fn main() { //~| ERROR functions in traits cannot be declared const //~| ERROR functions cannot be both `const` and `async` //~| ERROR cycle detected - //~| ERROR has an incompatible type for trait } impl Y { diff --git a/src/test/ui/parser/fn-header-semantic-fail.stderr b/src/test/ui/parser/fn-header-semantic-fail.stderr index bc51ba8b8c5c5..36304779df36f 100644 --- a/src/test/ui/parser/fn-header-semantic-fail.stderr +++ b/src/test/ui/parser/fn-header-semantic-fail.stderr @@ -7,17 +7,6 @@ LL | const async unsafe extern "C" fn ff5() {} | | `async` because of this | `const` because of this -error[E0706]: functions in traits cannot be declared `async` - --> $DIR/fn-header-semantic-fail.rs:17:9 - | -LL | async fn ft1(); - | -----^^^^^^^^^^ - | | - | `async` because of this - | - = note: `async` trait functions are not currently supported - = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait - error[E0379]: functions in traits cannot be declared const --> $DIR/fn-header-semantic-fail.rs:19:9 | @@ -30,17 +19,6 @@ error[E0379]: functions in traits cannot be declared const LL | const async unsafe extern "C" fn ft5(); | ^^^^^ functions in traits cannot be const -error[E0706]: functions in traits cannot be declared `async` - --> $DIR/fn-header-semantic-fail.rs:21:9 - | -LL | const async unsafe extern "C" fn ft5(); - | ^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | `async` because of this - | - = note: `async` trait functions are not currently supported - = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait - error: functions cannot be both `const` and `async` --> $DIR/fn-header-semantic-fail.rs:21:9 | @@ -50,42 +28,20 @@ LL | const async unsafe extern "C" fn ft5(); | | `async` because of this | `const` because of this -error[E0706]: functions in traits cannot be declared `async` - --> $DIR/fn-header-semantic-fail.rs:29:9 - | -LL | async fn ft1() {} - | -----^^^^^^^^^^^^ - | | - | `async` because of this - | - = note: `async` trait functions are not currently supported - = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait - error[E0379]: functions in traits cannot be declared const - --> $DIR/fn-header-semantic-fail.rs:32:9 + --> $DIR/fn-header-semantic-fail.rs:31:9 | LL | const fn ft3() {} | ^^^^^ functions in traits cannot be const error[E0379]: functions in traits cannot be declared const - --> $DIR/fn-header-semantic-fail.rs:34:9 + --> $DIR/fn-header-semantic-fail.rs:33:9 | LL | const async unsafe extern "C" fn ft5() {} | ^^^^^ functions in traits cannot be const -error[E0706]: functions in traits cannot be declared `async` - --> $DIR/fn-header-semantic-fail.rs:34:9 - | -LL | const async unsafe extern "C" fn ft5() {} - | ^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | `async` because of this - | - = note: `async` trait functions are not currently supported - = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait - error: functions cannot be both `const` and `async` - --> $DIR/fn-header-semantic-fail.rs:34:9 + --> $DIR/fn-header-semantic-fail.rs:33:9 | LL | const async unsafe extern "C" fn ft5() {} | ^^^^^-^^^^^------------------------------ @@ -94,7 +50,7 @@ LL | const async unsafe extern "C" fn ft5() {} | `const` because of this error: functions cannot be both `const` and `async` - --> $DIR/fn-header-semantic-fail.rs:47:9 + --> $DIR/fn-header-semantic-fail.rs:45:9 | LL | const async unsafe extern "C" fn fi5() {} | ^^^^^-^^^^^------------------------------ @@ -103,7 +59,7 @@ LL | const async unsafe extern "C" fn fi5() {} | `const` because of this error: functions in `extern` blocks cannot have qualifiers - --> $DIR/fn-header-semantic-fail.rs:53:18 + --> $DIR/fn-header-semantic-fail.rs:51:18 | LL | extern "C" { | ---------- in this `extern` block @@ -116,7 +72,7 @@ LL | fn fe1(); | ~~ error: functions in `extern` blocks cannot have qualifiers - --> $DIR/fn-header-semantic-fail.rs:54:19 + --> $DIR/fn-header-semantic-fail.rs:52:19 | LL | extern "C" { | ---------- in this `extern` block @@ -130,7 +86,7 @@ LL | fn fe2(); | ~~ error: functions in `extern` blocks cannot have qualifiers - --> $DIR/fn-header-semantic-fail.rs:55:18 + --> $DIR/fn-header-semantic-fail.rs:53:18 | LL | extern "C" { | ---------- in this `extern` block @@ -144,7 +100,7 @@ LL | fn fe3(); | ~~ error: functions in `extern` blocks cannot have qualifiers - --> $DIR/fn-header-semantic-fail.rs:56:23 + --> $DIR/fn-header-semantic-fail.rs:54:23 | LL | extern "C" { | ---------- in this `extern` block @@ -158,7 +114,7 @@ LL | fn fe4(); | ~~ error: functions in `extern` blocks cannot have qualifiers - --> $DIR/fn-header-semantic-fail.rs:57:42 + --> $DIR/fn-header-semantic-fail.rs:55:42 | LL | extern "C" { | ---------- in this `extern` block @@ -172,7 +128,7 @@ LL | fn fe5(); | ~~ error: functions cannot be both `const` and `async` - --> $DIR/fn-header-semantic-fail.rs:57:9 + --> $DIR/fn-header-semantic-fail.rs:55:9 | LL | const async unsafe extern "C" fn fe5(); | ^^^^^-^^^^^---------------------------- @@ -180,6 +136,58 @@ LL | const async unsafe extern "C" fn fe5(); | | `async` because of this | `const` because of this +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/fn-header-semantic-fail.rs:17:9 + | +LL | async fn ft1(); + | -----^^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/fn-header-semantic-fail.rs:21:9 + | +LL | const async unsafe extern "C" fn ft5(); + | ^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/fn-header-semantic-fail.rs:29:9 + | +LL | async fn ft1() {} + | -----^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/fn-header-semantic-fail.rs:33:9 + | +LL | const async unsafe extern "C" fn ft5() {} + | ^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + error[E0391]: cycle detected when computing type of `main::ff5::{opaque#0}` --> $DIR/fn-header-semantic-fail.rs:12:44 | @@ -216,60 +224,24 @@ LL | | } LL | | } | |_^ -error[E0053]: method `ft1` has an incompatible type for trait - --> $DIR/fn-header-semantic-fail.rs:29:24 - | -LL | async fn ft1() {} - | ^ - | | - | checked the `Output` of this `async fn`, found opaque type - | expected `()`, found opaque type - | - = note: while checking the return type of the `async fn` -note: type in trait - --> $DIR/fn-header-semantic-fail.rs:17:23 - | -LL | async fn ft1(); - | ^ - = note: expected fn pointer `fn()` - found fn pointer `fn() -> impl Future` - -error[E0053]: method `ft5` has an incompatible type for trait - --> $DIR/fn-header-semantic-fail.rs:34:48 - | -LL | const async unsafe extern "C" fn ft5() {} - | ^ - | | - | checked the `Output` of this `async fn`, found opaque type - | expected `()`, found opaque type - | - = note: while checking the return type of the `async fn` -note: type in trait - --> $DIR/fn-header-semantic-fail.rs:21:47 - | -LL | const async unsafe extern "C" fn ft5(); - | ^ - = note: expected fn pointer `unsafe extern "C" fn()` - found fn pointer `unsafe extern "C" fn() -> impl Future` - error[E0391]: cycle detected when computing type of `main::::ft5::{opaque#0}` - --> $DIR/fn-header-semantic-fail.rs:34:48 + --> $DIR/fn-header-semantic-fail.rs:33:48 | LL | const async unsafe extern "C" fn ft5() {} | ^ | note: ...which requires borrow-checking `main::::ft5`... - --> $DIR/fn-header-semantic-fail.rs:34:9 + --> $DIR/fn-header-semantic-fail.rs:33:9 | LL | const async unsafe extern "C" fn ft5() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires processing `main::::ft5`... - --> $DIR/fn-header-semantic-fail.rs:34:9 + --> $DIR/fn-header-semantic-fail.rs:33:9 | LL | const async unsafe extern "C" fn ft5() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires const checking `main::::ft5`... - --> $DIR/fn-header-semantic-fail.rs:34:9 + --> $DIR/fn-header-semantic-fail.rs:33:9 | LL | const async unsafe extern "C" fn ft5() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -288,30 +260,30 @@ LL | | } LL | | } | |_^ -error[E0391]: cycle detected when computing type of `main::::fi5::{opaque#0}` - --> $DIR/fn-header-semantic-fail.rs:47:48 +error[E0391]: cycle detected when computing type of `main::::fi5::{opaque#0}` + --> $DIR/fn-header-semantic-fail.rs:45:48 | LL | const async unsafe extern "C" fn fi5() {} | ^ | -note: ...which requires borrow-checking `main::::fi5`... - --> $DIR/fn-header-semantic-fail.rs:47:9 +note: ...which requires borrow-checking `main::::fi5`... + --> $DIR/fn-header-semantic-fail.rs:45:9 | LL | const async unsafe extern "C" fn fi5() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires processing `main::::fi5`... - --> $DIR/fn-header-semantic-fail.rs:47:9 +note: ...which requires processing `main::::fi5`... + --> $DIR/fn-header-semantic-fail.rs:45:9 | LL | const async unsafe extern "C" fn fi5() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires const checking `main::::fi5`... - --> $DIR/fn-header-semantic-fail.rs:47:9 +note: ...which requires const checking `main::::fi5`... + --> $DIR/fn-header-semantic-fail.rs:45:9 | LL | const async unsafe extern "C" fn fi5() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which requires computing whether `impl core::future::future::Future` is freeze... = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future: core::marker::Freeze`... - = note: ...which again requires computing type of `main::::fi5::{opaque#0}`, completing the cycle + = note: ...which again requires computing type of `main::::fi5::{opaque#0}`, completing the cycle note: cycle used when checking item types in top-level module --> $DIR/fn-header-semantic-fail.rs:5:1 | @@ -324,7 +296,7 @@ LL | | } LL | | } | |_^ -error: aborting due to 23 previous errors +error: aborting due to 21 previous errors -Some errors have detailed explanations: E0053, E0379, E0391, E0706. -For more information about an error, try `rustc --explain E0053`. +Some errors have detailed explanations: E0379, E0391, E0706. +For more information about an error, try `rustc --explain E0379`. diff --git a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs index aaf0f7eaef0dc..49462f52fb4c2 100644 --- a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs +++ b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs @@ -14,7 +14,6 @@ trait B { impl B for A { async fn associated(); //~ ERROR without body //~^ ERROR cannot be declared `async` - //~| ERROR has an incompatible type for trait } fn main() {} diff --git a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr index d3214458eac13..55c3b66f1363d 100644 --- a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr +++ b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr @@ -14,17 +14,6 @@ LL | async fn inherent(); | | | help: provide a definition for the function: `{ }` -error[E0706]: functions in traits cannot be declared `async` - --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:11:5 - | -LL | async fn associated(); - | -----^^^^^^^^^^^^^^^^^ - | | - | `async` because of this - | - = note: `async` trait functions are not currently supported - = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait - error: associated function in `impl` without body --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:15:5 | @@ -34,7 +23,7 @@ LL | async fn associated(); | help: provide a definition for the function: `{ }` error[E0706]: functions in traits cannot be declared `async` - --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:15:5 + --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:11:5 | LL | async fn associated(); | -----^^^^^^^^^^^^^^^^^ @@ -43,26 +32,22 @@ LL | async fn associated(); | = note: `async` trait functions are not currently supported = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable -error[E0053]: method `associated` has an incompatible type for trait - --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:15:26 +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:15:5 | LL | async fn associated(); - | ^ - | | - | checked the `Output` of this `async fn`, found opaque type - | expected `()`, found opaque type - | - = note: while checking the return type of the `async fn` -note: type in trait - --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:11:26 + | -----^^^^^^^^^^^^^^^^^ + | | + | `async` because of this | -LL | async fn associated(); - | ^ - = note: expected fn pointer `fn()` - found fn pointer `fn() -> impl Future` + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0053, E0706. -For more information about an error, try `rustc --explain E0053`. +For more information about this error, try `rustc --explain E0706`. diff --git a/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs index b280c8ab6e2b2..94f578af209a8 100644 --- a/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs +++ b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs @@ -12,7 +12,8 @@ impl A { trait C{async fn new(val: T) {} //~ ERROR `async fn` is not permitted in Rust 2015 //~^ ERROR functions in traits cannot be declared `async` -//~^^ ERROR cannot find type `T` in this scope -//~^^^ WARN changes to closure capture in Rust 2021 will affect drop order [rust_2021_incompatible_closure_captures] +//~| ERROR mismatched types +//~| ERROR cannot find type `T` in this scope +//~| WARN changes to closure capture in Rust 2021 will affect drop order [rust_2021_incompatible_closure_captures] //~ ERROR this file contains an unclosed delimiter diff --git a/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr index 50de2322907ed..9819f65013786 100644 --- a/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr +++ b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr @@ -1,5 +1,5 @@ error: this file contains an unclosed delimiter - --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:18:53 + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:19:53 | LL | trait C{async fn new(val: T) {} | - unclosed delimiter @@ -25,17 +25,6 @@ LL | trait C{async fn new(val: T) {} = help: pass `--edition 2021` to `rustc` = note: for more on editions, read https://doc.rust-lang.org/edition-guide -error[E0706]: functions in traits cannot be declared `async` - --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:9 - | -LL | trait C{async fn new(val: T) {} - | -----^^^^^^^^^^^^^^^^^^ - | | - | `async` because of this - | - = note: `async` trait functions are not currently supported - = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait - error[E0423]: expected function, found module `crate` --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:9:5 | @@ -51,6 +40,19 @@ LL | pub struct A {} LL | trait C{async fn new(val: T) {} | ^ help: a struct with a similar name exists: `A` +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:9 + | +LL | trait C{async fn new(val: T) {} + | -----^^^^^^^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + warning: changes to closure capture in Rust 2021 will affect drop order --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:6:57 | @@ -72,6 +74,20 @@ help: add a dummy let to cause `path` to be fully captured LL | async fn create(path: impl AsRef) { let _ = &path; | ++++++++++++++ +error[E0308]: mismatched types + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:30 + | +LL | trait C{async fn new(val: T) {} + | ^^ expected associated type, found opaque type + | + ::: $SRC_DIR/core/src/future/mod.rs:LL:COL + | +LL | pub const fn from_generator(gen: T) -> impl Future + | ------------------------------- the found opaque type + | + = note: expected associated type `::new::{opaque#0}` + found opaque type `impl Future` + warning: changes to closure capture in Rust 2021 will affect drop order --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:30 | @@ -87,7 +103,7 @@ help: add a dummy let to cause `val` to be fully captured LL | trait C{async fn new(val: T) { let _ = &val;} | +++++++++++++ -error: aborting due to 6 previous errors; 2 warnings emitted +error: aborting due to 7 previous errors; 2 warnings emitted -Some errors have detailed explanations: E0412, E0423, E0670, E0706. -For more information about an error, try `rustc --explain E0412`. +Some errors have detailed explanations: E0308, E0412, E0423, E0670, E0706. +For more information about an error, try `rustc --explain E0308`. From cdf78073c5d24cdc4c89a515b05f9d8e09321711 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 2 Sep 2022 21:02:59 +0000 Subject: [PATCH 12/18] Deeply check that method signatures match, and allow for nested RPITITs --- compiler/rustc_ast_lowering/src/lib.rs | 9 +- compiler/rustc_middle/src/arena.rs | 2 + compiler/rustc_middle/src/query/mod.rs | 7 + compiler/rustc_middle/src/ty/mod.rs | 8 + compiler/rustc_middle/src/ty/util.rs | 7 + .../src/traits/project.rs | 13 +- .../rustc_typeck/src/check/compare_method.rs | 147 +++++++++++++----- compiler/rustc_typeck/src/check/mod.rs | 2 + compiler/rustc_typeck/src/collect.rs | 5 +- .../impl-trait/in-trait/deep-match-works.rs | 16 ++ src/test/ui/impl-trait/in-trait/deep-match.rs | 15 ++ .../ui/impl-trait/in-trait/deep-match.stderr | 20 +++ .../ui/impl-trait/in-trait/nested-rpitit.rs | 32 ++++ 13 files changed, 231 insertions(+), 52 deletions(-) create mode 100644 src/test/ui/impl-trait/in-trait/deep-match-works.rs create mode 100644 src/test/ui/impl-trait/in-trait/deep-match.rs create mode 100644 src/test/ui/impl-trait/in-trait/deep-match.stderr create mode 100644 src/test/ui/impl-trait/in-trait/nested-rpitit.rs diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index e8201c0ddcaeb..eecf01c92fbd5 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1358,10 +1358,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } ImplTraitContext::InTrait => { self.lower_impl_trait_in_trait(span, def_node_id, |lctx| { - lctx.lower_param_bounds( - bounds, - ImplTraitContext::Disallowed(ImplTraitPosition::Trait), - ) + lctx.lower_param_bounds(bounds, ImplTraitContext::InTrait) }) } ImplTraitContext::Universal => { @@ -1559,8 +1556,6 @@ impl<'a, 'hir> LoweringContext<'a, '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| { - // FIXME(RPITIT): This should be a more descriptive ImplTraitPosition, i.e. nested RPITIT - // FIXME(RPITIT): We _also_ should support this eventually let hir_bounds = lower_bounds(lctx); let rpitit_placeholder = hir::ImplTraitPlaceholder { bounds: hir_bounds }; let rpitit_item = hir::Item { @@ -2073,7 +2068,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let bound = lctx.lower_async_fn_output_type_to_future_bound( output, output.span(), - ImplTraitContext::Disallowed(ImplTraitPosition::TraitReturn), + ImplTraitContext::InTrait, ); arena_vec![lctx; bound] }); diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 65d5f755f7248..9b1fedd0b533c 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -101,6 +101,8 @@ macro_rules! arena_types { [decode] impl_source: rustc_middle::traits::ImplSource<'tcx, ()>, [] dep_kind: rustc_middle::dep_graph::DepKindStruct<'tcx>, + + [] trait_impl_trait_tys: rustc_data_structures::fx::FxHashMap>, ]); ) } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 4478b45cf1437..adf479c423604 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -161,6 +161,13 @@ rustc_queries! { separate_provide_extern } + query compare_predicates_and_trait_impl_trait_tys(key: DefId) + -> Result<&'tcx FxHashMap>, ErrorGuaranteed> + { + desc { "better description please" } + separate_provide_extern + } + query analysis(key: ()) -> Result<(), ErrorGuaranteed> { eval_always desc { "running analysis passes on this crate" } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 4635a9d5575d4..df72260597f9f 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2484,6 +2484,14 @@ impl<'tcx> TyCtxt<'tcx> { pub fn is_const_default_method(self, def_id: DefId) -> bool { matches!(self.trait_of_item(def_id), Some(trait_id) if self.has_attr(trait_id, sym::const_trait)) } + + pub fn impl_trait_in_trait_parent(self, mut def_id: DefId) -> DefId { + while let def_kind = self.def_kind(def_id) && def_kind != DefKind::AssocFn { + debug_assert_eq!(def_kind, DefKind::ImplTraitPlaceholder); + def_id = self.parent(def_id); + } + def_id + } } /// Yields the parent function's `LocalDefId` if `def_id` is an `impl Trait` definition. diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index a3837512bce26..0c73ae54bc31a 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -651,6 +651,13 @@ impl<'tcx> TyCtxt<'tcx> { ty::EarlyBinder(self.type_of(def_id)) } + pub fn bound_trait_impl_trait_tys( + self, + def_id: DefId, + ) -> ty::EarlyBinder>, ErrorGuaranteed>> { + ty::EarlyBinder(self.compare_predicates_and_trait_impl_trait_tys(def_id)) + } + pub fn bound_fn_sig(self, def_id: DefId) -> ty::EarlyBinder> { ty::EarlyBinder(self.fn_sig(def_id)) } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 6c9efea8ca87f..7253ab21b3a09 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1318,7 +1318,7 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>( ) { let tcx = selcx.tcx(); if tcx.def_kind(obligation.predicate.item_def_id) == DefKind::ImplTraitPlaceholder { - 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 trait_def_id = tcx.parent(trait_fn_def_id); let trait_substs = obligation.predicate.substs.truncate_to(tcx, tcx.generics_of(trait_def_id)); @@ -2176,11 +2176,6 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>( let impl_fn_def_id = leaf_def.item.def_id; let impl_fn_substs = obligation.predicate.substs.rebase_onto(tcx, trait_fn_def_id, data.substs); - let sig = tcx - .bound_fn_sig(impl_fn_def_id) - .map_bound(|fn_sig| tcx.liberate_late_bound_regions(impl_fn_def_id, fn_sig)) - .subst(tcx, impl_fn_substs); - let cause = ObligationCause::new( obligation.cause.span, obligation.cause.body_id, @@ -2217,7 +2212,11 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>( selcx, obligation.param_env, cause.clone(), - sig.output(), + tcx.bound_trait_impl_trait_tys(impl_fn_def_id) + .map_bound(|tys| { + tys.map_or_else(|_| tcx.ty_error(), |tys| tys[&obligation.predicate.item_def_id]) + }) + .subst(tcx, impl_fn_substs), &mut obligations, ); diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index e55f43994b9f3..da45469863e48 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -1,18 +1,22 @@ use super::potentially_plural_count; use crate::errors::LifetimesOrBoundsMismatchOnTrait; -use rustc_data_structures::fx::FxHashSet; +use hir::def_id::DefId; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit; use rustc_hir::{GenericParamKind, ImplItemKind, TraitItemKind}; use rustc_infer::infer::outlives::env::OutlivesEnvironment; +use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{self, TyCtxtInferExt}; use rustc_infer::traits::util; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::subst::{InternalSubsts, Subst}; use rustc_middle::ty::util::ExplicitSelf; -use rustc_middle::ty::{self, DefIdTree}; +use rustc_middle::ty::{ + self, DefIdTree, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable, +}; use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt}; use rustc_span::Span; use rustc_trait_selection::traits::error_reporting::InferCtxtExt; @@ -64,10 +68,7 @@ pub(crate) fn compare_impl_method<'tcx>( return; } - if let Err(_) = compare_predicate_entailment(tcx, impl_m, impl_m_span, trait_m, impl_trait_ref) - { - return; - } + tcx.ensure().compare_predicates_and_trait_impl_trait_tys(impl_m.def_id); } /// This function is best explained by example. Consider a trait: @@ -136,13 +137,15 @@ pub(crate) fn compare_impl_method<'tcx>( /// /// Finally we register each of these predicates as an obligation and check that /// they hold. -fn compare_predicate_entailment<'tcx>( +pub(super) fn compare_predicates_and_trait_impl_trait_tys<'tcx>( tcx: TyCtxt<'tcx>, - impl_m: &ty::AssocItem, - impl_m_span: Span, - trait_m: &ty::AssocItem, - impl_trait_ref: ty::TraitRef<'tcx>, -) -> Result<(), ErrorGuaranteed> { + def_id: DefId, +) -> Result<&'tcx FxHashMap>, ErrorGuaranteed> { + let impl_m = tcx.opt_associated_item(def_id).unwrap(); + let impl_m_span = tcx.def_span(def_id); + let trait_m = tcx.opt_associated_item(impl_m.trait_item_def_id.unwrap()).unwrap(); + let impl_trait_ref = tcx.impl_trait_ref(impl_m.impl_container(tcx).unwrap()).unwrap(); + let trait_to_impl_substs = impl_trait_ref.substs; // This node-id should be used for the `body_id` field on each @@ -161,6 +164,7 @@ fn compare_predicate_entailment<'tcx>( kind: impl_m.kind, }, ); + let return_span = tcx.hir().fn_decl_by_hir_id(impl_m_hir_id).unwrap().output.span(); // Create mapping from impl to placeholder. let impl_to_placeholder_substs = InternalSubsts::identity_for_item(tcx, impl_m.def_id); @@ -266,6 +270,13 @@ fn compare_predicate_entailment<'tcx>( let trait_sig = tcx.bound_fn_sig(trait_m.def_id).subst(tcx, trait_to_placeholder_substs); let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, trait_sig); + let mut collector = + ImplTraitInTraitCollector::new(&ocx, return_span, param_env, impl_m_hir_id); + // FIXME(RPITIT): This should only be needed on the output type, but + // RPITIT placeholders shouldn't show up anywhere except for there, + // so I think this is fine. + let trait_sig = trait_sig.fold_with(&mut collector); + // Next, add all inputs and output as well-formed tys. Importantly, // we have to do this before normalization, since the normalized ty may // not contain the input parameters. See issue #87748. @@ -391,30 +402,6 @@ fn compare_predicate_entailment<'tcx>( return Err(diag.emit()); } - // Check that an impl's fn return satisfies the bounds of the - // FIXME(RPITIT): Generalize this to nested impl traits - if let ty::Projection(proj) = tcx.fn_sig(trait_m.def_id).skip_binder().output().kind() - && tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder - { - let return_span = tcx.hir().fn_decl_by_hir_id(impl_m_hir_id).unwrap().output.span(); - - for (predicate, span) in tcx - .bound_explicit_item_bounds(proj.item_def_id) - .transpose_iter() - .map(|pred| pred.map_bound(|pred| *pred).subst(tcx, trait_to_placeholder_substs)) - { - ocx.register_obligation(traits::Obligation::new( - traits::ObligationCause::new( - return_span, - impl_m_hir_id, - ObligationCauseCode::BindingObligation(proj.item_def_id, span), - ), - param_env, - predicate, - )); - } - } - // Check that all obligations are satisfied by the implementation's // version. let errors = ocx.select_all_or_error(); @@ -435,10 +422,96 @@ fn compare_predicate_entailment<'tcx>( &outlives_environment, ); - Ok(()) + let mut collected_tys = FxHashMap::default(); + for (def_id, ty) in collector.types { + match infcx.fully_resolve(ty) { + Ok(ty) => { + collected_tys.insert(def_id, ty); + } + Err(err) => { + tcx.sess.delay_span_bug( + return_span, + format!("could not fully resolve: {ty} => {err:?}"), + ); + collected_tys.insert(def_id, tcx.ty_error()); + } + } + } + + Ok(&*tcx.arena.alloc(collected_tys)) }) } +struct ImplTraitInTraitCollector<'a, 'tcx> { + ocx: &'a ObligationCtxt<'a, 'tcx>, + types: FxHashMap>, + span: Span, + param_env: ty::ParamEnv<'tcx>, + body_id: hir::HirId, +} + +impl<'a, 'tcx> ImplTraitInTraitCollector<'a, 'tcx> { + fn new( + ocx: &'a ObligationCtxt<'a, 'tcx>, + span: Span, + param_env: ty::ParamEnv<'tcx>, + body_id: hir::HirId, + ) -> Self { + ImplTraitInTraitCollector { ocx, types: FxHashMap::default(), span, param_env, body_id } + } +} + +impl<'tcx> TypeFolder<'tcx> for ImplTraitInTraitCollector<'_, 'tcx> { + fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { + self.ocx.infcx.tcx + } + + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'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) { + return *ty; + } + //FIXME(RPITIT): Deny nested RPITIT in substs too + if proj.substs.has_escaping_bound_vars() { + bug!("FIXME(RPITIT): error here"); + } + // Replace with infer var + let infer_ty = self.ocx.infcx.next_ty_var(TypeVariableOrigin { + span: self.span, + kind: TypeVariableOriginKind::MiscVariable, + }); + self.types.insert(proj.item_def_id, infer_ty); + // Recurse into bounds + for pred in self.tcx().bound_explicit_item_bounds(proj.item_def_id).transpose_iter() { + let pred_span = pred.0.1; + + let pred = pred.map_bound(|(pred, _)| *pred).subst(self.tcx(), proj.substs); + let pred = pred.fold_with(self); + let pred = self.ocx.normalize( + ObligationCause::misc(self.span, self.body_id), + self.param_env, + pred, + ); + + self.ocx.register_obligation(traits::Obligation::new( + ObligationCause::new( + self.span, + self.body_id, + ObligationCauseCode::BindingObligation(proj.item_def_id, pred_span), + ), + self.param_env, + pred, + )); + } + infer_ty + } else { + ty.super_fold_with(self) + } + } +} + fn check_region_bounds_on_impl_item<'tcx>( tcx: TyCtxt<'tcx>, impl_m: &ty::AssocItem, diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index 69eb34b5f802d..8811b38fc555a 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -132,6 +132,7 @@ use crate::require_c_abi_if_c_variadic; use crate::util::common::indenter; use self::coercion::DynamicCoerceMany; +use self::compare_method::compare_predicates_and_trait_impl_trait_tys; use self::region::region_scope_tree; pub use self::Expectation::*; @@ -249,6 +250,7 @@ pub fn provide(providers: &mut Providers) { used_trait_imports, check_mod_item_types, region_scope_tree, + compare_predicates_and_trait_impl_trait_tys, ..*providers }; } diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 5429598871d99..e5e82a4ff6b01 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -1602,7 +1602,10 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { } ItemKind::ImplTraitPlaceholder(_) => { let parent_id = tcx.hir().get_parent_item(hir_id).to_def_id(); - assert_eq!(tcx.def_kind(parent_id), DefKind::AssocFn); + assert!(matches!( + tcx.def_kind(parent_id), + DefKind::AssocFn | DefKind::ImplTraitPlaceholder + )); Some(parent_id) } _ => None, diff --git a/src/test/ui/impl-trait/in-trait/deep-match-works.rs b/src/test/ui/impl-trait/in-trait/deep-match-works.rs new file mode 100644 index 0000000000000..772da845ee1f7 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/deep-match-works.rs @@ -0,0 +1,16 @@ +// check-pass + +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +struct Wrapper(T); + +trait Foo { + fn bar() -> Wrapper; +} + +impl Foo for () { + fn bar() -> Wrapper { Wrapper(0) } +} + +fn main() {} diff --git a/src/test/ui/impl-trait/in-trait/deep-match.rs b/src/test/ui/impl-trait/in-trait/deep-match.rs new file mode 100644 index 0000000000000..5a220bc3f198a --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/deep-match.rs @@ -0,0 +1,15 @@ +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +struct Wrapper(T); + +trait Foo { + fn bar() -> Wrapper; +} + +impl Foo for () { + fn bar() -> i32 { 0 } + //~^ ERROR method `bar` has an incompatible type for trait +} + +fn main() {} diff --git a/src/test/ui/impl-trait/in-trait/deep-match.stderr b/src/test/ui/impl-trait/in-trait/deep-match.stderr new file mode 100644 index 0000000000000..af449869cb356 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/deep-match.stderr @@ -0,0 +1,20 @@ +error[E0053]: method `bar` has an incompatible type for trait + --> $DIR/deep-match.rs:11:17 + | +LL | fn bar() -> i32 { 0 } + | ^^^ + | | + | expected struct `Wrapper`, found `i32` + | help: change the output type to match the trait: `Wrapper<_>` + | +note: type in trait + --> $DIR/deep-match.rs:7:17 + | +LL | fn bar() -> Wrapper; + | ^^^^^^^^^^^^^^^^^^^ + = note: expected fn pointer `fn() -> Wrapper<_>` + found fn pointer `fn() -> i32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0053`. diff --git a/src/test/ui/impl-trait/in-trait/nested-rpitit.rs b/src/test/ui/impl-trait/in-trait/nested-rpitit.rs new file mode 100644 index 0000000000000..65285e3a3ccaf --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/nested-rpitit.rs @@ -0,0 +1,32 @@ +// check-pass + +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::fmt::Display; +use std::ops::Deref; + +trait Foo { + fn bar(self) -> impl Deref; +} + +struct A; + +impl Foo for A { + fn bar(self) -> &'static str { + "Hello, world" + } +} + +struct B; + +impl Foo for B { + fn bar(self) -> Box { + Box::new(42) + } +} + +fn main() { + println!("Message for you: {:?}", &*A.bar()); + println!("Another for you: {:?}", &*B.bar()); +} From 05812df603ab5940c1dffe6514b25c665dccfcf1 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 6 Sep 2022 17:37:00 +0200 Subject: [PATCH 13/18] Handle generic parameters. --- compiler/rustc_ast_lowering/src/lib.rs | 120 ++++++------------ .../src/diagnostics/region_name.rs | 2 +- compiler/rustc_hir/src/hir.rs | 19 +-- compiler/rustc_hir/src/intravisit.rs | 9 +- compiler/rustc_hir/src/target.rs | 9 +- compiler/rustc_hir_pretty/src/lib.rs | 4 - .../nice_region_error/static_impl_trait.rs | 2 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 3 - compiler/rustc_middle/src/hir/map/mod.rs | 18 ++- compiler/rustc_middle/src/ty/diagnostics.rs | 2 +- compiler/rustc_passes/src/dead.rs | 2 +- compiler/rustc_passes/src/reachable.rs | 1 - compiler/rustc_privacy/src/lib.rs | 11 +- compiler/rustc_resolve/src/late/lifetimes.rs | 6 +- .../rustc_save_analysis/src/dump_visitor.rs | 2 +- compiler/rustc_save_analysis/src/sig.rs | 15 ++- .../src/traits/project.rs | 2 +- compiler/rustc_typeck/src/astconv/mod.rs | 13 +- .../rustc_typeck/src/check/compare_method.rs | 27 +++- compiler/rustc_typeck/src/collect.rs | 25 ++-- .../rustc_typeck/src/collect/item_bounds.rs | 41 ++---- compiler/rustc_typeck/src/collect/type_of.rs | 11 +- src/librustdoc/clean/mod.rs | 12 +- src/librustdoc/visit_ast.rs | 1 - .../ui/impl-trait/in-trait/opaque-in-impl.rs | 36 +++++- 25 files changed, 170 insertions(+), 223 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index eecf01c92fbd5..1a987c6e2d791 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 75fde53b6cdec..0707ff5ed02a0 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 8b1ebe34cb00f..a57fdc3bfb125 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 3e9ab10b1f7e3..bf4ab06638bb1 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 0e9b05729d29e..5917d5e346e37 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 01f445c8a52d5..35a58296e370e 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 f804569b0747e..b115ac8b3df95 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 d45d814c3b0f0..f967ac9a4dc3e 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 1a0bea68293e7..5a65ec9a4765a 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 e4ad96b659b08..648f5f7161fa6 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 a7ce0f312af80..f141d7beeb921 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 74c5ccf9cd205..f7e3fac6b2e20 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 3657fb2134048..afd423dc5fa1a 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 e9e4f8fc483c5..6ff56f9a89114 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 6658892881d4b..94f222251d3dc 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 ea9c82b3597d0..bae1828cd182d 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 7253ab21b3a09..8a65262a00723 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 6eec2c57639c6..d9789d5aaf031 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 da45469863e48..a6c8dbb2555dd 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 e5e82a4ff6b01..ceb5684fdf0a8 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 fe8d8f54f0477..0d34a8bfee333 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, .. }), - span, - .. - }) => opaque_type_bounds(tcx, def_id, bounds, *span), - hir::Node::Item(hir::Item { - kind: hir::ItemKind::ImplTraitPlaceholder(hir::ImplTraitPlaceholder { bounds }), + kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, in_trait, .. }), 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 ded2ac1308e54..a26e26cb38996 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 03752c9b6dbb7..08b696e65eb3b 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 7fe391f420f6a..ca7a20bf3688a 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 a777cbcd529a6..2e06629699aad 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" } } +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!("{}", ().bar()); + println!("{:?}", ().foo()); + println!("{:?}", ().bar::()); + println!("{:?}", "hi".to_string().baz()); } From 55df9201fe5d8d67102ea8a8b70415d0312ab813 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 6 Sep 2022 17:16:08 +0000 Subject: [PATCH 14/18] Tweak feature error, add test --- compiler/rustc_ast_lowering/src/lib.rs | 32 ++++++++++++++----- src/test/ui/async-await/async-trait-fn.stderr | 2 +- ...return_position_impl_trait_in_trait.stderr | 3 ++ src/test/ui/impl-trait/in-trait/reveal.rs | 18 +++++++++++ src/test/ui/impl-trait/where-allowed.stderr | 6 ++++ 5 files changed, 52 insertions(+), 9 deletions(-) create mode 100644 src/test/ui/impl-trait/in-trait/reveal.rs diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 1a987c6e2d791..9b4ee9b5a6572 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -312,7 +312,7 @@ impl std::fmt::Display for ImplTraitPosition { } } -#[derive(Debug)] +#[derive(Debug, PartialEq, Eq)] enum FnDeclKind { Fn, Inherent, @@ -1373,6 +1373,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } path } + ImplTraitContext::Disallowed( + position @ (ImplTraitPosition::TraitReturn | ImplTraitPosition::ImplReturn), + ) => { + self.tcx.sess.create_feature_err( + MisplacedImplTrait { + span: t.span, + position: DiagnosticArgFromDisplay(&position), + }, + sym::return_position_impl_trait_in_trait, + ).emit(); + hir::TyKind::Err + } ImplTraitContext::Disallowed(position) => { self.tcx.sess.emit_err(MisplacedImplTrait { span: t.span, @@ -1717,13 +1729,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } _ => { if !kind.impl_trait_return_allowed(self.tcx) { - self.tcx - .sess - .create_feature_err( - TraitFnAsync { fn_span, span }, - sym::return_position_impl_trait_in_trait, - ) - .emit(); + 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.lower_async_fn_ret_ty( &decl.output, diff --git a/src/test/ui/async-await/async-trait-fn.stderr b/src/test/ui/async-await/async-trait-fn.stderr index e30dfb1e1a705..6c17077d90b95 100644 --- a/src/test/ui/async-await/async-trait-fn.stderr +++ b/src/test/ui/async-await/async-trait-fn.stderr @@ -62,7 +62,7 @@ LL | async fn bar(&self) {} LL | pub const fn from_generator(gen: T) -> impl Future | ------------------------------- the found opaque type | - = note: expected associated type `::bar::{opaque#0}` + = note: expected associated type `::bar::{opaque#0}<'_>` found opaque type `impl Future` error[E0308]: mismatched types diff --git a/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr b/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr index a41f5789fdbfa..36177bbe15830 100644 --- a/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr +++ b/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr @@ -3,6 +3,9 @@ error[E0562]: `impl Trait` only allowed in function and inherent method return t | LL | fn bar() -> impl Sized; | ^^^^^^^^^^ + | + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable error: aborting due to previous error diff --git a/src/test/ui/impl-trait/in-trait/reveal.rs b/src/test/ui/impl-trait/in-trait/reveal.rs new file mode 100644 index 0000000000000..d6ede1cc495c6 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/reveal.rs @@ -0,0 +1,18 @@ +// check-pass + +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +trait Foo { + fn f() -> Box; +} + +impl Foo for () { + fn f() -> Box { + Box::new(String::new()) + } +} + +fn main() { + let x: Box = <() as Foo>::f(); +} diff --git a/src/test/ui/impl-trait/where-allowed.stderr b/src/test/ui/impl-trait/where-allowed.stderr index 58a2f79efb4c6..9b346387d6106 100644 --- a/src/test/ui/impl-trait/where-allowed.stderr +++ b/src/test/ui/impl-trait/where-allowed.stderr @@ -162,12 +162,18 @@ error[E0562]: `impl Trait` only allowed in function and inherent method return t | LL | fn in_return() -> impl Debug; | ^^^^^^^^^^ + | + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `impl` method return --> $DIR/where-allowed.rs:125:34 | LL | fn in_trait_impl_return() -> impl Debug { () } | ^^^^^^^^^^ + | + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `extern fn` param --> $DIR/where-allowed.rs:138:33 From 526511e86b597c0b5c6b5e1676320a6d53117068 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 6 Sep 2022 17:27:47 +0000 Subject: [PATCH 15/18] Appease clippy again --- compiler/rustc_ast_lowering/src/lib.rs | 17 ++++++++++------- .../clippy/clippy_lints/src/dereference.rs | 2 +- src/tools/clippy/clippy_lints/src/lifetimes.rs | 2 +- .../clippy/clippy_lints/src/manual_async_fn.rs | 2 +- .../clippy/clippy_lints/src/missing_doc.rs | 3 +-- .../clippy/clippy_lints/src/missing_inline.rs | 1 - src/tools/clippy/clippy_utils/src/hir_utils.rs | 6 ++---- 7 files changed, 16 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 9b4ee9b5a6572..6b636288137a5 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1376,13 +1376,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ImplTraitContext::Disallowed( position @ (ImplTraitPosition::TraitReturn | ImplTraitPosition::ImplReturn), ) => { - self.tcx.sess.create_feature_err( - MisplacedImplTrait { - span: t.span, - position: DiagnosticArgFromDisplay(&position), - }, - sym::return_position_impl_trait_in_trait, - ).emit(); + self.tcx + .sess + .create_feature_err( + MisplacedImplTrait { + span: t.span, + position: DiagnosticArgFromDisplay(&position), + }, + sym::return_position_impl_trait_in_trait, + ) + .emit(); hir::TyKind::Err } ImplTraitContext::Disallowed(position) => { diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index 09a073f4234d0..d1ab7fb67962e 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -959,7 +959,7 @@ fn binding_ty_auto_deref_stability<'tcx>( )) .is_sized(cx.tcx.at(DUMMY_SP), cx.param_env.without_caller_bounds()), ), - TyKind::OpaqueDef(..) | TyKind::ImplTraitInTrait(..) | TyKind::Infer | TyKind::Typeof(..) | TyKind::TraitObject(..) | TyKind::Err => { + TyKind::OpaqueDef(..) | TyKind::Infer | TyKind::Typeof(..) | TyKind::TraitObject(..) | TyKind::Err => { Position::ReborrowStable(precedence) }, }; diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs index 573a7c016b8e8..5995675bd969c 100644 --- a/src/tools/clippy/clippy_lints/src/lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs @@ -441,7 +441,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> { fn visit_ty(&mut self, ty: &'tcx Ty<'_>) { match ty.kind { - TyKind::OpaqueDef(item, bounds) => { + TyKind::OpaqueDef(item, bounds, _) => { let map = self.cx.tcx.hir(); let item = map.item(item); let len = self.lts.len(); diff --git a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs index 2502c8f880ddc..754b0e78a148c 100644 --- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs +++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs @@ -103,7 +103,7 @@ fn future_trait_ref<'tcx>( ty: &'tcx Ty<'tcx>, ) -> Option<(&'tcx TraitRef<'tcx>, Vec)> { if_chain! { - if let TyKind::OpaqueDef(item_id, bounds) = ty.kind; + if let TyKind::OpaqueDef(item_id, bounds, false) = ty.kind; let item = cx.tcx.hir().item(item_id); if let ItemKind::OpaqueTy(opaque) = &item.kind; if let Some(trait_ref) = opaque.bounds.iter().find_map(|bound| { diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs index 9f518c7aaa39f..3701fdb4adbff 100644 --- a/src/tools/clippy/clippy_lints/src/missing_doc.rs +++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs @@ -147,8 +147,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { | hir::ItemKind::TraitAlias(..) | hir::ItemKind::TyAlias(..) | hir::ItemKind::Union(..) - | hir::ItemKind::OpaqueTy(..) - | hir::ItemKind::ImplTraitPlaceholder(..) => {}, + | hir::ItemKind::OpaqueTy(..) => {}, hir::ItemKind::ExternCrate(..) | hir::ItemKind::ForeignMod { .. } | hir::ItemKind::GlobalAsm(..) diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs index 9fd1a475d7496..07bc2ca5d3cd2 100644 --- a/src/tools/clippy/clippy_lints/src/missing_inline.rs +++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs @@ -128,7 +128,6 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { | hir::ItemKind::TyAlias(..) | hir::ItemKind::Union(..) | hir::ItemKind::OpaqueTy(..) - | hir::ItemKind::ImplTraitPlaceholder(..) | hir::ItemKind::ExternCrate(..) | hir::ItemKind::ForeignMod { .. } | hir::ItemKind::Impl { .. } diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 9f8500d41a85f..f45cec9f0b430 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -987,12 +987,10 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } }, TyKind::Path(ref qpath) => self.hash_qpath(qpath), - TyKind::OpaqueDef(_, arg_list) => { + TyKind::OpaqueDef(_, arg_list, in_trait) => { self.hash_generic_args(arg_list); + in_trait.hash(&mut self.s); }, - TyKind::ImplTraitInTrait(_) => { - // Do nothing - } TyKind::TraitObject(_, lifetime, _) => { self.hash_lifetime(*lifetime); }, From ec170bef0d8c6ec91c35b89c38da9a0ed10e00fd Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 8 Sep 2022 00:26:01 +0000 Subject: [PATCH 16/18] Rebase fallout --- compiler/rustc_ast_lowering/src/lib.rs | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 6b636288137a5..0720f23ed756d 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1351,17 +1351,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { *in_trait, itctx, ), - ImplTraitContext::TypeAliasesOpaqueTy => { - let mut nested_itctx = ImplTraitContext::TypeAliasesOpaqueTy; - self.lower_opaque_impl_trait( - span, - hir::OpaqueTyOrigin::TyAlias, - def_node_id, - bounds, - false, - nested_itctx, - ) - } + ImplTraitContext::TypeAliasesOpaqueTy => self.lower_opaque_impl_trait( + span, + hir::OpaqueTyOrigin::TyAlias, + def_node_id, + bounds, + false, + &mut ImplTraitContext::TypeAliasesOpaqueTy, + ), ImplTraitContext::Universal => { let span = t.span; let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span); From 270b776ef9da03b85edc7ddff89a7c6ac188dc4a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 8 Sep 2022 00:45:09 +0000 Subject: [PATCH 17/18] Adjust pretty printing of RPITITs --- .../rustc_infer/src/infer/error_reporting/mod.rs | 14 ++++++++++++++ compiler/rustc_middle/src/ty/print/pretty.rs | 8 +++++++- src/test/ui/async-await/async-trait-fn.stderr | 12 ++++++------ .../async-await/edition-deny-async-fns-2015.stderr | 4 ++-- ...2021-incompatible-closure-captures-93117.stderr | 4 ++-- 5 files changed, 31 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 0196bd262179e..95a36dd8a56a5 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -61,6 +61,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed, IntoDiagnosticArg}; use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString, MultiSpan}; use rustc_hir as hir; +use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::lang_items::LangItem; use rustc_hir::Node; @@ -1682,6 +1683,19 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pos.col.to_usize() + 1, ) } + (true, ty::Projection(proj)) + if self.tcx.def_kind(proj.item_def_id) + == DefKind::ImplTraitPlaceholder => + { + let sm = self.tcx.sess.source_map(); + let pos = sm.lookup_char_pos(self.tcx.def_span(proj.item_def_id).lo()); + format!( + " (trait associated opaque type at <{}:{}:{}>)", + sm.filename_for_diagnostics(&pos.file.name), + pos.line, + pos.col.to_usize() + 1, + ) + } (true, _) => format!(" ({})", ty.sort_string(self.tcx)), (false, _) => "".to_string(), }; diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 1ae3063dae4e7..f134e2cd1bc65 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -632,7 +632,13 @@ pub trait PrettyPrinter<'tcx>: ty::Foreign(def_id) => { p!(print_def_path(def_id, &[])); } - ty::Projection(ref data) => p!(print(data)), + ty::Projection(ref data) => { + if self.tcx().def_kind(data.item_def_id) == DefKind::ImplTraitPlaceholder { + return self.pretty_print_opaque_impl_type(data.item_def_id, data.substs); + } else { + p!(print(data)) + } + } ty::Placeholder(placeholder) => p!(write("Placeholder({:?})", placeholder)), ty::Opaque(def_id, substs) => { // FIXME(eddyb) print this with `print_def_path`. diff --git a/src/test/ui/async-await/async-trait-fn.stderr b/src/test/ui/async-await/async-trait-fn.stderr index 6c17077d90b95..e5c584e31e815 100644 --- a/src/test/ui/async-await/async-trait-fn.stderr +++ b/src/test/ui/async-await/async-trait-fn.stderr @@ -48,8 +48,8 @@ LL | async fn foo() {} LL | pub const fn from_generator(gen: T) -> impl Future | ------------------------------- the found opaque type | - = note: expected associated type `::foo::{opaque#0}` - found opaque type `impl Future` + = note: expected associated type `impl Future` (trait associated opaque type at <$DIR/async-trait-fn.rs:3:20>) + found opaque type `impl Future` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>) error[E0308]: mismatched types --> $DIR/async-trait-fn.rs:5:25 @@ -62,8 +62,8 @@ LL | async fn bar(&self) {} LL | pub const fn from_generator(gen: T) -> impl Future | ------------------------------- the found opaque type | - = note: expected associated type `::bar::{opaque#0}<'_>` - found opaque type `impl Future` + = note: expected associated type `impl Future` (trait associated opaque type at <$DIR/async-trait-fn.rs:5:25>) + found opaque type `impl Future` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>) error[E0308]: mismatched types --> $DIR/async-trait-fn.rs:7:20 @@ -81,8 +81,8 @@ LL | | } LL | pub const fn from_generator(gen: T) -> impl Future | ------------------------------- the found opaque type | - = note: expected associated type `::baz::{opaque#0}` - found opaque type `impl Future` + = note: expected associated type `impl Future` (trait associated opaque type at <$DIR/async-trait-fn.rs:7:20>) + found opaque type `impl Future` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>) error: aborting due to 6 previous errors diff --git a/src/test/ui/async-await/edition-deny-async-fns-2015.stderr b/src/test/ui/async-await/edition-deny-async-fns-2015.stderr index 2f40ef1ccbb14..8c2902d9b00d1 100644 --- a/src/test/ui/async-await/edition-deny-async-fns-2015.stderr +++ b/src/test/ui/async-await/edition-deny-async-fns-2015.stderr @@ -103,8 +103,8 @@ LL | async fn foo() {} LL | pub const fn from_generator(gen: T) -> impl Future | ------------------------------- the found opaque type | - = note: expected associated type `::foo::{opaque#0}` - found opaque type `impl Future` + = note: expected associated type `impl Future` (trait associated opaque type at <$DIR/edition-deny-async-fns-2015.rs:18:20>) + found opaque type `impl Future` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>) error: aborting due to 11 previous errors diff --git a/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr index 9819f65013786..3814c568e72c1 100644 --- a/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr +++ b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr @@ -85,8 +85,8 @@ LL | trait C{async fn new(val: T) {} LL | pub const fn from_generator(gen: T) -> impl Future | ------------------------------- the found opaque type | - = note: expected associated type `::new::{opaque#0}` - found opaque type `impl Future` + = note: expected associated type `impl Future` (trait associated opaque type at <$DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:30>) + found opaque type `impl Future` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>) warning: changes to closure capture in Rust 2021 will affect drop order --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:30 From 6876c94d800433ad7f2ea72da64d963eb2269589 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 9 Sep 2022 01:31:36 +0000 Subject: [PATCH 18/18] Fix documentation lint failures --- compiler/rustc_infer/src/infer/error_reporting/mod.rs | 2 +- compiler/rustc_typeck/src/check/compare_method.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 95a36dd8a56a5..08460463998fd 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -1772,7 +1772,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // In some (most?) cases cause.body_id points to actual body, but in some cases // it's an actual definition. According to the comments (e.g. in - // librustc_typeck/check/compare_method.rs:compare_predicate_entailment) the latter + // librustc_typeck/check/compare_method.rs:compare_predicates_and_trait_impl_trait_tys) the latter // is relied upon by some other code. This might (or might not) need cleanup. let body_owner_def_id = self.tcx.hir().opt_local_def_id(cause.body_id).unwrap_or_else(|| { diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index a6c8dbb2555dd..1152a2477a2a8 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -1307,7 +1307,7 @@ pub(crate) fn compare_ty_impl<'tcx>( })(); } -/// The equivalent of [compare_predicate_entailment], but for associated types +/// The equivalent of [compare_predicates_and_trait_impl_trait_tys], but for associated types /// instead of associated functions. fn compare_type_predicate_entailment<'tcx>( tcx: TyCtxt<'tcx>,