From 7bbe7b625b14850da4937893953bfa154184b965 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 11 May 2022 11:40:53 -0300 Subject: [PATCH 01/53] Set up new approach for impl trait in return position Adds a feature flag to use the new code only in certain tests to be able to make progress step by step. --- compiler/rustc_ast_lowering/src/lib.rs | 165 +++++++++++++++++- compiler/rustc_feature/src/active.rs | 2 + compiler/rustc_span/src/symbol.rs | 1 + .../ui/impl-trait/v2/simple-definition.rs | 13 ++ 4 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/impl-trait/v2/simple-definition.rs diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 9a960356a85f4..cef213791b185 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1311,7 +1311,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let span = t.span; match itctx { ImplTraitContext::ReturnPositionOpaqueTy { origin } => { - self.lower_opaque_impl_trait(span, origin, def_node_id, bounds, itctx) + if self.tcx.sess.features_untracked().return_position_impl_trait_v2 { + self.lower_opaque_impl_trait_v2( + span, + origin, + def_node_id, + bounds, + itctx, + ) + } else { + self.lower_opaque_impl_trait(span, origin, def_node_id, bounds, itctx) + } } ImplTraitContext::TypeAliasesOpaqueTy => { let nested_itctx = ImplTraitContext::TypeAliasesOpaqueTy; @@ -1509,6 +1519,159 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes) } + /// Lowers a `ReturnPositionOpaqueTy` (`-> impl Trait`) or a `TypeAliasesOpaqueTy` (`type F = + /// impl Trait`): this creates the associated Opaque Type (TAIT) definition and then returns a + /// HIR type that references the TAIT. + /// + /// Given a function definition like: + /// + /// ```rust + /// fn test<'a, T: Debug>(x: &'a T) -> impl Debug + 'a { + /// x + /// } + /// ``` + /// + /// we will create a TAIT definition in the HIR like + /// + /// ``` + /// type TestReturn<'a, T, 'x> = impl Debug + 'x + /// ``` + /// + /// and return a type like `TestReturn<'static, T, 'a>`, so that the function looks like: + /// + /// ```rust + /// fn test<'a, T: Debug>(x: &'a T) -> TestReturn<'static, T, 'a> + /// ``` + /// + /// Note the subtlety around type parameters! The new TAIT, `TestReturn`, inherits all the + /// type parameters from the function `test` (this is implemented in the query layer, they aren't + /// added explicitly in the HIR). But this includes all the lifetimes, and we only want to + /// capture the lifetimes that are referenced in the bounds. Therefore, we add *extra* lifetime parameters + /// for the lifetimes that get captured (`'x`, in our example above) and reference those. + #[tracing::instrument(level = "debug", skip(self))] + fn lower_opaque_impl_trait_v2( + &mut self, + span: Span, + origin: hir::OpaqueTyOrigin, + opaque_ty_node_id: NodeId, + bounds: &GenericBounds, + itctx: ImplTraitContext, + ) -> hir::TyKind<'hir> { + // Make sure we know that some funky desugaring has been going on here. + // This is a first: there is code in other places like for loop + // desugaring that explicitly states that we don't want to track that. + // Not tracking it makes lints in rustc and clippy very fragile, as + // frequently opened issues show. + let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None); + + let opaque_ty_def_id = self.local_def_id(opaque_ty_node_id); + debug!(?opaque_ty_def_id); + + // Contains the new lifetime definitions created for the TAIT (if any). + let mut collected_lifetimes = Vec::new(); + + // If this came from a TAIT (as opposed to a function that returns an RPIT), we only want + // to capture the lifetimes that appear in the bounds. So visit the bounds to find out + // exactly which ones those are. + let lifetimes_to_remap = if origin == hir::OpaqueTyOrigin::TyAlias { + // in a TAIT like `type Foo<'a> = impl Foo<'a>`, we don't keep all the lifetime parameters + Vec::new() + } else { + // in fn return position, like the `fn test<'a>() -> impl Debug + 'a` example, + // we only keep the lifetimes that appear in the `impl Debug` itself: + lifetime_collector::lifetimes_in_bounds(&self.resolver, bounds) + }; + debug!(?lifetimes_to_remap); + + self.with_hir_id_owner(opaque_ty_node_id, |lctx| { + let mut new_remapping = FxHashMap::default(); + + // If this opaque type is only capturing a subset of the lifetimes (those that appear + // in bounds), then create the new lifetime parameters required and create a mapping + // from the old `'a` (on the function) to the new `'a` (on the opaque type). + collected_lifetimes = lctx.create_lifetime_defs( + opaque_ty_def_id, + &lifetimes_to_remap, + &mut new_remapping, + ); + debug!(?collected_lifetimes); + debug!(?new_remapping); + + // Install the remapping from old to new (if any): + lctx.with_remapping(new_remapping, |lctx| { + // This creates HIR lifetime definitions as `hir::GenericParam`, in the given + // example `type TestReturn<'a, T, 'x> = impl Debug + 'x`, it creates a collection + // containing `&['x]`. + let lifetime_defs = lctx.arena.alloc_from_iter(collected_lifetimes.iter().map( + |&(new_node_id, lifetime)| { + let hir_id = lctx.lower_node_id(new_node_id); + debug_assert_ne!(lctx.opt_local_def_id(new_node_id), None); + + let (name, kind) = if lifetime.ident.name == kw::UnderscoreLifetime { + (hir::ParamName::Fresh, hir::LifetimeParamKind::Elided) + } else { + ( + hir::ParamName::Plain(lifetime.ident), + hir::LifetimeParamKind::Explicit, + ) + }; + + hir::GenericParam { + hir_id, + name, + span: lifetime.ident.span, + pure_wrt_drop: false, + kind: hir::GenericParamKind::Lifetime { kind }, + colon_span: None, + } + }, + )); + debug!(?lifetime_defs); + + // Then when we lower the param bounds, references to 'a are remapped to 'a1, so we + // get back Debug + 'a1, which is suitable for use on the TAIT. + let hir_bounds = lctx.lower_param_bounds(bounds, itctx); + debug!(?hir_bounds); + + let opaque_ty_item = hir::OpaqueTy { + generics: self.arena.alloc(hir::Generics { + params: lifetime_defs, + predicates: &[], + has_where_clause_predicates: false, + where_clause_span: lctx.lower_span(span), + span: lctx.lower_span(span), + }), + bounds: hir_bounds, + origin, + }; + debug!(?opaque_ty_item); + + lctx.generate_opaque_type(opaque_ty_def_id, opaque_ty_item, span, opaque_ty_span) + }) + }); + + // This creates HIR lifetime arguments as `hir::GenericArg`, in the given example `type + // TestReturn<'a, T, 'x> = impl Debug + 'x`, it creates a collection containing `&['x]`. + let lifetimes = + self.arena.alloc_from_iter(collected_lifetimes.into_iter().map(|(_, lifetime)| { + let id = self.next_node_id(); + let span = lifetime.ident.span; + + let ident = if lifetime.ident.name == kw::UnderscoreLifetime { + Ident::with_dummy_span(kw::UnderscoreLifetime) + } else { + lifetime.ident + }; + + let l = self.new_named_lifetime(lifetime.id, id, span, ident); + hir::GenericArg::Lifetime(l) + })); + debug!(?lifetimes); + + // `impl Trait` now just becomes `Foo<'a, 'b, ..>`. + hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes) + } + /// Registers a new opaque type with the proper `NodeId`s and /// returns the lowered node-ID for the opaque type. fn generate_opaque_type( diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index e09c3ccbc75ab..dbc9b61b455a9 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -178,6 +178,8 @@ declare_features! ( /// Use for stable + negative coherence and strict coherence depending on trait's /// rustc_strict_coherence value. (active, with_negative_coherence, "1.60.0", None, None), + /// Added for testing impl trait in return position using a "sibling" type + (active, return_position_impl_trait_v2, "1.62.0", None, None), // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! // Features are listed in alphabetical order. Tidy will fail if you don't keep it this way. // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 6eca7dc52b26a..9e492e016326a 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1178,6 +1178,7 @@ symbols! { require, residual, result, + return_position_impl_trait_v2, rhs, rintf32, rintf64, diff --git a/src/test/ui/impl-trait/v2/simple-definition.rs b/src/test/ui/impl-trait/v2/simple-definition.rs new file mode 100644 index 0000000000000..79f609ba4ce9f --- /dev/null +++ b/src/test/ui/impl-trait/v2/simple-definition.rs @@ -0,0 +1,13 @@ +// check-pass + +#![feature(return_position_impl_trait_v2)] + +use std::fmt::Debug; + +fn foo() -> impl Debug { + 22 +} + +fn main() { + assert_eq!("22", format!("{:?}", foo())); +} From b3cc702adc009e6897317f93eeaccc602f0de72b Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 11 May 2022 16:43:42 -0300 Subject: [PATCH 02/53] Make RPIT not inherit generics from its function --- compiler/rustc_typeck/src/collect.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 6236ad370df60..268796d54d69e 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -1583,8 +1583,13 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { } Node::Item(item) => match item.kind { ItemKind::OpaqueTy(hir::OpaqueTy { - origin: - hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id), + origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), + .. + }) if !tcx.sess.features_untracked().return_position_impl_trait_v2 => { + Some(fn_def_id.to_def_id()) + } + ItemKind::OpaqueTy(hir::OpaqueTy { + origin: hir::OpaqueTyOrigin::AsyncFn(fn_def_id), .. }) => Some(fn_def_id.to_def_id()), ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => { From bae1deb8971a3fd28294856de14e2956b9eba715 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 20 May 2022 11:59:17 -0300 Subject: [PATCH 03/53] Call mk_param_from_def for all params --- compiler/rustc_typeck/src/astconv/mod.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index ef927058df4ee..e2912d08da382 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -2710,6 +2710,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { debug!("impl_trait_ty_to_ty: generics={:?}", generics); let substs = InternalSubsts::for_item(tcx, def_id, |param, _| { + if tcx.sess.features_untracked().return_position_impl_trait_v2 { + return tcx.mk_param_from_def(param); + } if let Some(i) = (param.index as usize).checked_sub(generics.parent_count) { // Our own parameters are the resolved lifetimes. if let GenericParamDefKind::Lifetime = param.kind { From a5f8780521e936dd884c9f68631963d850f6ff1c Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 17 May 2022 14:33:18 -0300 Subject: [PATCH 04/53] Copy generic parameters from function to impl trait opaque type --- compiler/rustc_ast_lowering/src/expr.rs | 4 +- compiler/rustc_ast_lowering/src/item.rs | 24 ++- compiler/rustc_ast_lowering/src/lib.rs | 141 ++++++++++++++---- compiler/rustc_ast_lowering/src/path.rs | 18 ++- src/test/ui/impl-trait/v2/generics-unbound.rs | 21 +++ 5 files changed, 161 insertions(+), 47 deletions(-) create mode 100644 src/test/ui/impl-trait/v2/generics-unbound.rs diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 7df3520422c18..caf09dfd9ee3a 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -849,7 +849,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params); // Lower outside new scope to preserve `is_in_loop_condition`. - let fn_decl = self.lower_fn_decl(decl, None, FnDeclKind::Closure, None); + let fn_decl = self.lower_fn_decl(decl, None, FnDeclKind::Closure, &[], None); let c = self.arena.alloc(hir::Closure { binder: binder_clause, @@ -953,7 +953,7 @@ 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 = self.lower_fn_decl(&outer_decl, None, FnDeclKind::Closure, None); + let fn_decl = self.lower_fn_decl(&outer_decl, None, FnDeclKind::Closure, &[], None); let c = self.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 fd338ffc0c5e8..b892c1bc84f2f 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -262,7 +262,13 @@ impl<'hir> LoweringContext<'_, 'hir> { let itctx = ImplTraitContext::Universal; let (generics, decl) = this.lower_generics(generics, id, 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), + FnDeclKind::Fn, + &generics.params, + ret_id, + ) }); let sig = hir::FnSig { decl, @@ -652,7 +658,13 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_generics(generics, i.id, itctx, |this| { ( // Disallow `impl Trait` in foreign items. - this.lower_fn_decl(fdec, None, FnDeclKind::ExternFn, None), + this.lower_fn_decl( + fdec, + None, + FnDeclKind::ExternFn, + &generics.params, + None, + ), this.lower_fn_params_to_names(fdec), ) }); @@ -1230,7 +1242,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let header = self.lower_fn_header(sig.header); let itctx = ImplTraitContext::Universal; let (generics, decl) = self.lower_generics(generics, id, itctx, |this| { - this.lower_fn_decl(&sig.decl, Some(id), kind, is_async) + this.lower_fn_decl(&sig.decl, Some(id), kind, &generics.params, is_async) }); (generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) }) } @@ -1295,7 +1307,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &mut self, generics: &Generics, parent_node_id: NodeId, - itctx: ImplTraitContext, + mut itctx: ImplTraitContext<'_>, f: impl FnOnce(&mut Self) -> T, ) -> (&'hir hir::Generics<'hir>, T) { debug_assert!(self.impl_trait_defs.is_empty()); @@ -1351,7 +1363,7 @@ impl<'hir> LoweringContext<'_, 'hir> { param.id, ¶m.kind, ¶m.bounds, - itctx, + itctx.reborrow(), PredicateOrigin::GenericParam, ) })); @@ -1400,7 +1412,7 @@ impl<'hir> LoweringContext<'_, 'hir> { id: NodeId, kind: &GenericParamKind, bounds: &[GenericBound], - itctx: ImplTraitContext, + itctx: ImplTraitContext<'_>, origin: PredicateOrigin, ) -> Option> { // Do not create a clause if we do not have anything inside it. diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index cef213791b185..557865c0e5913 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -254,8 +254,8 @@ impl ResolverAstLoweringExt for ResolverAstLowering { /// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree, /// and if so, what meaning it has. -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -enum ImplTraitContext { +#[derive(Debug)] +enum ImplTraitContext<'a> { /// Treat `impl Trait` as shorthand for a new universal generic parameter. /// Example: `fn foo(x: impl Debug)`, where `impl Debug` is conceptually /// equivalent to a fresh universal parameter like `fn foo(x: T)`. @@ -270,6 +270,8 @@ enum ImplTraitContext { ReturnPositionOpaqueTy { /// Origin: Either OpaqueTyOrigin::FnReturn or OpaqueTyOrigin::AsyncFn, origin: hir::OpaqueTyOrigin, + /// In scope generic types and consts from AST + generic_params: &'a [GenericParam], }, /// Impl trait in type aliases. TypeAliasesOpaqueTy, @@ -301,6 +303,20 @@ enum ImplTraitPosition { ImplReturn, } +impl ImplTraitContext<'_> { + fn reborrow(&mut self) -> ImplTraitContext<'_> { + use self::ImplTraitContext::*; + match self { + Universal => Universal, + ReturnPositionOpaqueTy { origin, generic_params } => { + ReturnPositionOpaqueTy { origin: *origin, generic_params: *generic_params } + } + TypeAliasesOpaqueTy => TypeAliasesOpaqueTy, + Disallowed(pos) => Disallowed(*pos), + } + } +} + impl std::fmt::Display for ImplTraitPosition { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let name = match self { @@ -810,6 +826,29 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }) } + /// Collect a "to be lowered" copy of each type and const generic parameter, skipping + /// lifetimes. + #[instrument(level = "debug", skip(self))] + fn create_generic_defs( + &mut self, + parent_def_id: LocalDefId, + generics: &[GenericParam], + remapping: &mut FxHashMap, + ) { + for param in generics { + if matches!(param.kind, GenericParamKind::Const { .. } | GenericParamKind::Type { .. }) + { + let old_def_id = self.local_def_id(param.id); + let node_id = self.next_node_id(); + + // Add a definition for the generic param def. + let new_def_id = self.create_def(parent_def_id, node_id, DefPathData::ImplTrait); + + remapping.insert(old_def_id, new_def_id); + } + } + } + /// Lowers a lifetime binder that defines `generic_params`, returning the corresponding HIR /// nodes. The returned list includes any "extra" lifetime parameters that were added by the /// name resolver owing to lifetime elision; this also populates the resolver's node-id->def-id @@ -960,21 +999,26 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_assoc_ty_constraint( &mut self, constraint: &AssocConstraint, - itctx: ImplTraitContext, + mut itctx: ImplTraitContext<'_>, ) -> hir::TypeBinding<'hir> { debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", constraint, itctx); // lower generic arguments of identifier in constraint let gen_args = if let Some(ref gen_args) = constraint.gen_args { let gen_args_ctor = match gen_args { GenericArgs::AngleBracketed(ref data) => { - self.lower_angle_bracketed_parameter_data(data, ParamMode::Explicit, itctx).0 + self.lower_angle_bracketed_parameter_data( + data, + ParamMode::Explicit, + itctx.reborrow(), + ) + .0 } GenericArgs::Parenthesized(ref data) => { self.emit_bad_parenthesized_trait_in_assoc_ty(data); self.lower_angle_bracketed_parameter_data( &data.as_angle_bracketed_args(), ParamMode::Explicit, - itctx, + itctx.reborrow(), ) .0 } @@ -1003,7 +1047,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // // fn foo() -> impl Iterator ImplTraitContext::ReturnPositionOpaqueTy { .. } - | ImplTraitContext::TypeAliasesOpaqueTy { .. } => (true, itctx), + | ImplTraitContext::TypeAliasesOpaqueTy { .. } => (true, itctx.reborrow()), // We are in the argument position, but within a dyn type: // @@ -1012,7 +1056,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // so desugar to // // fn foo(x: dyn Iterator) - ImplTraitContext::Universal if self.is_in_dyn_type => (true, itctx), + ImplTraitContext::Universal if self.is_in_dyn_type => (true, itctx.reborrow()), // In `type Foo = dyn Iterator` we desugar to // `type Foo = dyn Iterator` but we have to override the @@ -1103,7 +1147,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_generic_arg( &mut self, arg: &ast::GenericArg, - itctx: ImplTraitContext, + itctx: ImplTraitContext<'_>, ) -> hir::GenericArg<'hir> { match arg { ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(<)), @@ -1165,7 +1209,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } #[instrument(level = "debug", skip(self))] - fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> &'hir hir::Ty<'hir> { + fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext<'_>) -> &'hir hir::Ty<'hir> { self.arena.alloc(self.lower_ty_direct(t, itctx)) } @@ -1175,7 +1219,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself: &Option, path: &Path, param_mode: ParamMode, - itctx: ImplTraitContext, + itctx: ImplTraitContext<'_>, ) -> hir::Ty<'hir> { // Check whether we should interpret this as a bare trait object. // This check mirrors the one in late resolution. We only introduce this special case in @@ -1217,7 +1261,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.ty(span, hir::TyKind::Tup(tys)) } - fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'hir> { + fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_>) -> hir::Ty<'hir> { let kind = match t.kind { TyKind::Infer => hir::TyKind::Infer, TyKind::Err => hir::TyKind::Err, @@ -1245,14 +1289,22 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { generic_params, unsafety: self.lower_unsafety(f.unsafety), abi: self.lower_extern(f.ext), - decl: self.lower_fn_decl(&f.decl, None, FnDeclKind::Pointer, None), + decl: self.lower_fn_decl( + &f.decl, + None, + FnDeclKind::Pointer, + &f.generic_params, + None, + ), param_names: self.lower_fn_params_to_names(&f.decl), })) } TyKind::Never => hir::TyKind::Never, - TyKind::Tup(ref tys) => hir::TyKind::Tup( - self.arena.alloc_from_iter(tys.iter().map(|ty| self.lower_ty_direct(ty, itctx))), - ), + TyKind::Tup(ref tys) => { + hir::TyKind::Tup(self.arena.alloc_from_iter( + tys.iter().map(|ty| self.lower_ty_direct(ty, itctx.reborrow())), + )) + } TyKind::Paren(ref ty) => { return self.lower_ty_direct(ty, itctx); } @@ -1286,7 +1338,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { GenericBound::Trait( ref ty, TraitBoundModifier::None | TraitBoundModifier::MaybeConst, - ) => Some(this.lower_poly_trait_ref(ty, itctx)), + ) => Some(this.lower_poly_trait_ref(ty, itctx.reborrow())), // `~const ?Bound` will cause an error during AST validation // anyways, so treat it like `?Bound` as compilation proceeds. GenericBound::Trait( @@ -1310,12 +1362,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { TyKind::ImplTrait(def_node_id, ref bounds) => { let span = t.span; match itctx { - ImplTraitContext::ReturnPositionOpaqueTy { origin } => { + ImplTraitContext::ReturnPositionOpaqueTy { origin, generic_params } => { if self.tcx.sess.features_untracked().return_position_impl_trait_v2 { self.lower_opaque_impl_trait_v2( span, origin, def_node_id, + generic_params, bounds, itctx, ) @@ -1402,7 +1455,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { origin: hir::OpaqueTyOrigin, opaque_ty_node_id: NodeId, bounds: &GenericBounds, - itctx: ImplTraitContext, + itctx: ImplTraitContext<'_>, ) -> hir::TyKind<'hir> { // Make sure we know that some funky desugaring has been going on here. // This is a first: there is code in other places like for loop @@ -1554,8 +1607,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: Span, origin: hir::OpaqueTyOrigin, opaque_ty_node_id: NodeId, + ast_generic_params: &[GenericParam], bounds: &GenericBounds, - itctx: ImplTraitContext, + itctx: ImplTraitContext<'_>, ) -> hir::TyKind<'hir> { // Make sure we know that some funky desugaring has been going on here. // This is a first: there is code in other places like for loop @@ -1597,13 +1651,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { debug!(?collected_lifetimes); debug!(?new_remapping); + lctx.create_generic_defs(opaque_ty_def_id, ast_generic_params, &mut new_remapping); + debug!(?new_remapping); + // Install the remapping from old to new (if any): lctx.with_remapping(new_remapping, |lctx| { // This creates HIR lifetime definitions as `hir::GenericParam`, in the given // example `type TestReturn<'a, T, 'x> = impl Debug + 'x`, it creates a collection // containing `&['x]`. - let lifetime_defs = lctx.arena.alloc_from_iter(collected_lifetimes.iter().map( - |&(new_node_id, lifetime)| { + let lifetime_defs: Vec<_> = collected_lifetimes + .iter() + .map(|&(new_node_id, lifetime)| { let hir_id = lctx.lower_node_id(new_node_id); debug_assert_ne!(lctx.opt_local_def_id(new_node_id), None); @@ -1624,18 +1682,32 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { kind: hir::GenericParamKind::Lifetime { kind }, colon_span: None, } - }, - )); + }) + .collect(); debug!(?lifetime_defs); + let type_const_defs: Vec<_> = ast_generic_params + .iter() + .filter(|param| { + matches!( + param.kind, + GenericParamKind::Const { .. } | GenericParamKind::Type { .. } + ) + }) + .map(|param| lctx.lower_generic_param(¶m)) + .collect(); + debug!(?type_const_defs); + // Then when we lower the param bounds, references to 'a are remapped to 'a1, so we // get back Debug + 'a1, which is suitable for use on the TAIT. let hir_bounds = lctx.lower_param_bounds(bounds, itctx); debug!(?hir_bounds); + let generic_defs = lifetime_defs.into_iter().chain(type_const_defs.into_iter()); + let opaque_ty_item = hir::OpaqueTy { generics: self.arena.alloc(hir::Generics { - params: lifetime_defs, + params: self.arena.alloc_from_iter(generic_defs), predicates: &[], has_where_clause_predicates: false, where_clause_span: lctx.lower_span(span), @@ -1790,6 +1862,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { decl: &FnDecl, fn_node_id: Option, kind: FnDeclKind, + generics: &[GenericParam], make_ret_async: Option, ) -> &'hir hir::FnDecl<'hir> { let c_variadic = decl.c_variadic(); @@ -1835,6 +1908,7 @@ 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), + generic_params: generics, } } _ => ImplTraitContext::Disallowed(match kind { @@ -2130,6 +2204,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // generates. let context = ImplTraitContext::ReturnPositionOpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), + generic_params: &[], }; self.lower_ty(ty, context) } @@ -2157,7 +2232,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_param_bound( &mut self, tpb: &GenericBound, - itctx: ImplTraitContext, + itctx: ImplTraitContext<'_>, ) -> hir::GenericBound<'hir> { match tpb { GenericBound::Trait(p, modifier) => hir::GenericBound::Trait( @@ -2287,7 +2362,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } - fn lower_trait_ref(&mut self, p: &TraitRef, itctx: ImplTraitContext) -> hir::TraitRef<'hir> { + fn lower_trait_ref( + &mut self, + p: &TraitRef, + itctx: ImplTraitContext<'_>, + ) -> hir::TraitRef<'hir> { let path = match self.lower_qpath(p.ref_id, &None, &p.path, ParamMode::Explicit, itctx) { hir::QPath::Resolved(None, path) => path, qpath => panic!("lower_trait_ref: unexpected QPath `{:?}`", qpath), @@ -2299,7 +2378,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_poly_trait_ref( &mut self, p: &PolyTraitRef, - itctx: ImplTraitContext, + itctx: ImplTraitContext<'_>, ) -> hir::PolyTraitRef<'hir> { let bound_generic_params = self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params); @@ -2307,14 +2386,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) } } - fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext) -> hir::MutTy<'hir> { + fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext<'_>) -> hir::MutTy<'hir> { hir::MutTy { ty: self.lower_ty(&mt.ty, itctx), mutbl: mt.mutbl } } fn lower_param_bounds( &mut self, bounds: &[GenericBound], - itctx: ImplTraitContext, + itctx: ImplTraitContext<'_>, ) -> hir::GenericBounds<'hir> { self.arena.alloc_from_iter(self.lower_param_bounds_mut(bounds, itctx)) } @@ -2322,9 +2401,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_param_bounds_mut<'s>( &'s mut self, bounds: &'s [GenericBound], - itctx: ImplTraitContext, + mut itctx: ImplTraitContext<'s>, ) -> impl Iterator> + Captures<'s> + Captures<'a> { - bounds.iter().map(move |bound| self.lower_param_bound(bound, itctx)) + bounds.iter().map(move |bound| self.lower_param_bound(bound, itctx.reborrow())) } fn lower_generic_and_bounds( diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 897c7215805e0..e5c18001b65c9 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -22,10 +22,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself: &Option, p: &Path, param_mode: ParamMode, - itctx: ImplTraitContext, + mut itctx: ImplTraitContext<'_>, ) -> hir::QPath<'hir> { let qself_position = qself.as_ref().map(|q| q.position); - let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx)); + let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx.reborrow())); let partial_res = self.resolver.get_partial_res(id).unwrap_or_else(|| PartialRes::new(Res::Err)); @@ -70,7 +70,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { segment, param_mode, parenthesized_generic_args, - itctx, + itctx.reborrow(), ) }, )), @@ -116,7 +116,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { segment, param_mode, ParenthesizedGenericArgs::Err, - itctx, + itctx.reborrow(), )); let qpath = hir::QPath::TypeRelative(ty, hir_segment); @@ -180,7 +180,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { segment: &PathSegment, param_mode: ParamMode, parenthesized_generic_args: ParenthesizedGenericArgs, - itctx: ImplTraitContext, + itctx: ImplTraitContext<'_>, ) -> hir::PathSegment<'hir> { debug!("path_span: {:?}, lower_path_segment(segment: {:?})", path_span, segment,); let (mut generic_args, infer_args) = if let Some(ref generic_args) = segment.args { @@ -316,7 +316,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, data: &AngleBracketedArgs, param_mode: ParamMode, - itctx: ImplTraitContext, + mut itctx: ImplTraitContext<'_>, ) -> (GenericArgsCtor<'hir>, bool) { let has_non_lt_args = data.args.iter().any(|arg| match arg { AngleBracketedArg::Arg(ast::GenericArg::Lifetime(_)) @@ -327,12 +327,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .args .iter() .filter_map(|arg| match arg { - AngleBracketedArg::Arg(arg) => Some(self.lower_generic_arg(arg, itctx)), + AngleBracketedArg::Arg(arg) => Some(self.lower_generic_arg(arg, itctx.reborrow())), AngleBracketedArg::Constraint(_) => None, }) .collect(); let bindings = self.arena.alloc_from_iter(data.args.iter().filter_map(|arg| match arg { - AngleBracketedArg::Constraint(c) => Some(self.lower_assoc_ty_constraint(c, itctx)), + AngleBracketedArg::Constraint(c) => { + Some(self.lower_assoc_ty_constraint(c, itctx.reborrow())) + } AngleBracketedArg::Arg(_) => None, })); let ctor = GenericArgsCtor { args, bindings, parenthesized: false, span: data.span }; diff --git a/src/test/ui/impl-trait/v2/generics-unbound.rs b/src/test/ui/impl-trait/v2/generics-unbound.rs new file mode 100644 index 0000000000000..a49850811fcb2 --- /dev/null +++ b/src/test/ui/impl-trait/v2/generics-unbound.rs @@ -0,0 +1,21 @@ +// check-pass + +#![feature(return_position_impl_trait_v2)] + +trait MyTrait { + fn get_inner(self) -> T; +} + +impl MyTrait for T { + fn get_inner(self) -> Self { + self + } +} + +fn ident_as_my_trait(t: T) -> impl MyTrait { + t +} + +fn main() { + assert_eq!(22, ident_as_my_trait(22).get_inner()); +} From c1f8fbdd775da75fa3e7638f7e7a5cb401e358f8 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 19 May 2022 18:43:35 -0300 Subject: [PATCH 05/53] Test nested impl trait in return position --- src/test/ui/impl-trait/v2/nested-return-type.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/test/ui/impl-trait/v2/nested-return-type.rs diff --git a/src/test/ui/impl-trait/v2/nested-return-type.rs b/src/test/ui/impl-trait/v2/nested-return-type.rs new file mode 100644 index 0000000000000..ac073f8df5fb0 --- /dev/null +++ b/src/test/ui/impl-trait/v2/nested-return-type.rs @@ -0,0 +1,10 @@ +// Check that nested impl Trait items work in functions with generic parameters. +// check-pass + +#![feature(return_position_impl_trait_v2)] + +fn nested_assoc_type<'a, T>() -> impl Iterator { + [1].iter() +} + +fn main() {} From 2cccbc4fe095debbfeba538eb19264571a983a8e Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 19 May 2022 17:55:39 -0300 Subject: [PATCH 06/53] Add generic type and const args to OpaqueDef --- compiler/rustc_ast_lowering/src/lib.rs | 90 ++++++++++++++++++++++++-- 1 file changed, 86 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 557865c0e5913..b7e1f8d137058 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -849,6 +849,81 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } + /// Collect a "to be lowered" copy of each type and const argument, skipping lifetimes. + #[instrument(level = "debug", skip(self))] + fn collect_type_const_args(&mut self, params: &[GenericParam]) -> Vec> { + params + .iter() + .filter(|param| { + matches!(param.kind, GenericParamKind::Const { .. } | GenericParamKind::Type { .. }) + }) + .map(|param| { + let span = param.span(); + let local_def_id = self.local_def_id(param.id); + let def_id = local_def_id.to_def_id(); + + match param.kind { + GenericParamKind::Lifetime => { + unreachable!("Lifetimes should have been filtered at this point.") + } + GenericParamKind::Type { .. } => hir::GenericArg::Type(hir::Ty { + hir_id: self.next_id(), + span, + kind: hir::TyKind::Path(hir::QPath::Resolved( + None, + self.arena.alloc(hir::Path { + res: Res::Def( + DefKind::TyParam, + def_id, + ), + span, + segments: arena_vec![self; hir::PathSegment::from_ident(self.lower_ident(param.ident))], + }), + )), + }), + GenericParamKind::Const { .. } => { + let parent_def_id = self.current_hir_id_owner; + let node_id = self.next_node_id(); + + self.create_def( + parent_def_id, + node_id, + DefPathData::AnonConst, + ); + let hir_id = self.lower_node_id(node_id); + + let span = self.lower_span(span); + let ct = hir::AnonConst { + hir_id, + body: self.lower_body(|this| { + ( + &[], + hir::Expr { + hir_id: this.next_id(), + kind: hir::ExprKind::Path(hir::QPath::Resolved( + None, + this.arena.alloc(hir::Path { + res: Res::Def( + DefKind::ConstParam, + def_id, + ), + span, + segments: arena_vec![this; hir::PathSegment::from_ident(this.lower_ident(param.ident))], + }), + )), + span, + }, + ) + }), + }; + + hir::GenericArg::Const(hir::ConstArg { value: ct, span }) + } + } + }) + .collect() + } + /// Lowers a lifetime binder that defines `generic_params`, returning the corresponding HIR /// nodes. The returned list includes any "extra" lifetime parameters that were added by the /// name resolver owing to lifetime elision; this also populates the resolver's node-id->def-id @@ -1724,8 +1799,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // This creates HIR lifetime arguments as `hir::GenericArg`, in the given example `type // TestReturn<'a, T, 'x> = impl Debug + 'x`, it creates a collection containing `&['x]`. - let lifetimes = - self.arena.alloc_from_iter(collected_lifetimes.into_iter().map(|(_, lifetime)| { + let lifetimes: Vec<_> = collected_lifetimes + .into_iter() + .map(|(_, lifetime)| { let id = self.next_node_id(); let span = lifetime.ident.span; @@ -1737,11 +1813,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let l = self.new_named_lifetime(lifetime.id, id, span, ident); hir::GenericArg::Lifetime(l) - })); + }) + .collect(); debug!(?lifetimes); + let type_const_args = self.collect_type_const_args(ast_generic_params); + + let generic_args = + self.arena.alloc_from_iter(lifetimes.into_iter().chain(type_const_args.into_iter())); + // `impl Trait` now just becomes `Foo<'a, 'b, ..>`. - hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes) + hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, generic_args) } /// Registers a new opaque type with the proper `NodeId`s and From bb2871129ebb1d721d361a1f58ce89e3a6dcae47 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 20 May 2022 15:20:44 -0300 Subject: [PATCH 07/53] Handle all kind of generic args when converting to ty --- compiler/rustc_typeck/src/astconv/mod.rs | 44 ++++++++++++++++++++---- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index e2912d08da382..3ac24af712570 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -2697,26 +2697,58 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { result_ty } + #[tracing::instrument(level = "debug", skip(self))] fn impl_trait_ty_to_ty( &self, def_id: DefId, - lifetimes: &[hir::GenericArg<'_>], + generic_args: &[hir::GenericArg<'_>], origin: OpaqueTyOrigin, ) -> Ty<'tcx> { - debug!("impl_trait_ty_to_ty(def_id={:?}, lifetimes={:?})", def_id, lifetimes); let tcx = self.tcx(); + match origin { + hir::OpaqueTyOrigin::FnReturn(..) + if tcx.sess.features_untracked().return_position_impl_trait_v2 => + { + let params = &self.tcx().generics_of(def_id).params; + assert_eq!(params.len(), generic_args.len()); + let substs: Vec<_> = generic_args + .iter() + .zip(params) + .map(|(generic_arg, param)| match generic_arg { + GenericArg::Lifetime(lt) => self.ast_region_to_region(lt, None).into(), + GenericArg::Type(ty) => self.ast_ty_to_ty(ty).into(), + GenericArg::Const(ct) => ty::Const::from_opt_const_arg_anon_const( + tcx, + ty::WithOptConstParam { + did: tcx.hir().local_def_id(ct.value.hir_id), + const_param_did: Some(param.def_id), + }, + ) + .into(), + _ => { + bug!( + "Generic argument {:?} should have been inferred already", + generic_arg + ) + } + }) + .collect(); + let ty = tcx.mk_opaque(def_id, tcx.intern_substs(&substs)); + debug!(?ty); + return ty; + } + _ => {} + } + let generics = tcx.generics_of(def_id); debug!("impl_trait_ty_to_ty: generics={:?}", generics); let substs = InternalSubsts::for_item(tcx, def_id, |param, _| { - if tcx.sess.features_untracked().return_position_impl_trait_v2 { - return tcx.mk_param_from_def(param); - } if let Some(i) = (param.index as usize).checked_sub(generics.parent_count) { // Our own parameters are the resolved lifetimes. if let GenericParamDefKind::Lifetime = param.kind { - if let hir::GenericArg::Lifetime(lifetime) = &lifetimes[i] { + if let hir::GenericArg::Lifetime(lifetime) = &generic_args[i] { self.ast_region_to_region(lifetime, None).into() } else { bug!() From f60f609c2af0e831ef0ae49fd4bb7c11765c0b05 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 20 May 2022 15:22:38 -0300 Subject: [PATCH 08/53] param_env def_id is the one of the opaque type for RPIT --- compiler/rustc_typeck/src/check/check.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 29a128f27b840..e8b15faffa805 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -725,11 +725,18 @@ fn check_opaque_meets_bounds<'tcx>( let hidden_type = tcx.bound_type_of(def_id.to_def_id()).subst(tcx, substs); let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let defining_use_anchor = match *origin { - hir::OpaqueTyOrigin::FnReturn(did) | hir::OpaqueTyOrigin::AsyncFn(did) => did, - hir::OpaqueTyOrigin::TyAlias => def_id, + let (param_env_did, defining_use_anchor) = match *origin { + hir::OpaqueTyOrigin::FnReturn(did) => { + if tcx.sess.features_untracked().return_position_impl_trait_v2 { + (def_id, did) + } else { + (did, did) + } + } + hir::OpaqueTyOrigin::AsyncFn(did) => (did, did), + hir::OpaqueTyOrigin::TyAlias => (def_id, def_id), }; - let param_env = tcx.param_env(defining_use_anchor); + let param_env = tcx.param_env(param_env_did); tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(defining_use_anchor)).enter( move |infcx| { From a71699d0551beec8a9aa2c06fa1f21bdc2bd7751 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 20 May 2022 15:24:29 -0300 Subject: [PATCH 09/53] Properly gather explicit predicates of opaque type --- compiler/rustc_typeck/src/collect.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 268796d54d69e..531ff9de0cfd4 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -2157,6 +2157,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP *generics } ItemKind::OpaqueTy(OpaqueTy { + ref generics, origin: hir::OpaqueTyOrigin::AsyncFn(..) | hir::OpaqueTyOrigin::FnReturn(..), .. }) => { @@ -2174,7 +2175,11 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP // is from the return type of the containing function, // which will ensure that the function's predicates // hold. - return ty::GenericPredicates { parent: None, predicates: &[] }; + if !tcx.sess.features_untracked().return_position_impl_trait_v2 { + return ty::GenericPredicates { parent: None, predicates: &[] }; + } + + generics } ItemKind::OpaqueTy(OpaqueTy { ref generics, From a311717185d51eaf71a09992918f83b50c0c9259 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 20 May 2022 15:41:41 -0300 Subject: [PATCH 10/53] is_impl_trait_defn doesn't have any effect now with RPIT --- compiler/rustc_middle/src/ty/mod.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index ed04e7660339e..a9575463efc59 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2398,6 +2398,11 @@ pub fn is_impl_trait_defn(tcx: TyCtxt<'_>, def_id: DefId) -> Option if let Node::Item(item) = tcx.hir().get_by_def_id(def_id) { if let hir::ItemKind::OpaqueTy(ref opaque_ty) = item.kind { return match opaque_ty.origin { + hir::OpaqueTyOrigin::FnReturn(_) + if tcx.sess.features_untracked().return_position_impl_trait_v2 => + { + None + } hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent) => { Some(parent) } From 4642ec973938f7089b56e7e399cd9fd24b4e9394 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 20 May 2022 15:44:26 -0300 Subject: [PATCH 11/53] register_member_constraints is 0 for RPIT --- compiler/rustc_infer/src/infer/opaque_types.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index d45adf43abfcc..0372c3ed9726a 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -346,6 +346,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { debug!(?concrete_ty); let first_own_region = match self.opaque_ty_origin_unchecked(def_id, span) { + hir::OpaqueTyOrigin::FnReturn(..) + if tcx.sess.features_untracked().return_position_impl_trait_v2 => + { + 0 + } hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => { // We lower // From 35a98a7b91f346aaa7d971ae7f86bbd9dc529954 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 30 Jun 2022 15:18:29 -0300 Subject: [PATCH 12/53] gather_explicit_predicates_of return empty for OpaqueTyOrigin::AsyncFn --- compiler/rustc_typeck/src/collect.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 531ff9de0cfd4..a67b4b8770b19 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -2158,7 +2158,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP } ItemKind::OpaqueTy(OpaqueTy { ref generics, - origin: hir::OpaqueTyOrigin::AsyncFn(..) | hir::OpaqueTyOrigin::FnReturn(..), + origin: hir::OpaqueTyOrigin::FnReturn(..), .. }) => { // return-position impl trait @@ -2181,6 +2181,25 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP generics } + ItemKind::OpaqueTy(OpaqueTy { + origin: hir::OpaqueTyOrigin::AsyncFn(..), .. + }) => { + // return-position impl trait + // + // We don't inherit predicates from the parent here: + // If we have, say `fn f<'a, T: 'a>() -> impl Sized {}` + // then the return type is `f::<'static, T>::{{opaque}}`. + // + // If we inherited the predicates of `f` then we would + // require that `T: 'static` to show that the return + // type is well-formed. + // + // The only way to have something with this opaque type + // is from the return type of the containing function, + // which will ensure that the function's predicates + // hold. + return ty::GenericPredicates { parent: None, predicates: &[] }; + } ItemKind::OpaqueTy(OpaqueTy { ref generics, origin: hir::OpaqueTyOrigin::TyAlias, From fee7dc62faecb6dfcf93f7b5fc717a113480c28e Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 20 May 2022 17:30:34 -0300 Subject: [PATCH 13/53] Properly type check type parameter predicates for RPIT --- compiler/rustc_typeck/src/collect.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index a67b4b8770b19..39416d0ddf165 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -632,6 +632,19 @@ fn type_param_predicates( } generics } + ItemKind::OpaqueTy(OpaqueTy { + ref generics, + origin: hir::OpaqueTyOrigin::FnReturn(..), + .. + }) if tcx.sess.features_untracked().return_position_impl_trait_v2 => { + // Implied `Self: Trait` and supertrait bounds. + if param_id == item_hir_id { + let identity_trait_ref = ty::TraitRef::identity(tcx, item_def_id); + extend = + Some((identity_trait_ref.without_const().to_predicate(tcx), item.span)); + } + generics + } _ => return result, } } From df9356db2b29de99df653ef972a26a57bef9d384 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sat, 21 May 2022 01:16:17 -0300 Subject: [PATCH 14/53] Properly handle Const generics --- compiler/rustc_typeck/src/collect/type_of.rs | 25 ++++++++++++++++++++ src/test/ui/impl-trait/v2/const-generics.rs | 12 ++++++++++ 2 files changed, 37 insertions(+) create mode 100644 src/test/ui/impl-trait/v2/const-generics.rs diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index 9f931de6fdedb..b574eacb2a9c9 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -195,6 +195,31 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option< (generics, arg_index) } + + Node::Ty(&Ty { kind: TyKind::OpaqueDef(id, generics), .. }) + if tcx.sess.features_untracked().return_position_impl_trait_v2 => + { + let parent_generics = tcx.generics_of(id.def_id.to_def_id()); + + generics + .iter() + .enumerate() + .filter_map(|(idx, arg)| match arg { + hir::GenericArg::Const(ConstArg { + value: hir::AnonConst { hir_id: inner_hir_id, .. }, + .. + }) => { + if *inner_hir_id == hir_id { + Some((parent_generics, idx)) + } else { + None + } + } + _ => None, + }) + .next()? + } + _ => return None, }; diff --git a/src/test/ui/impl-trait/v2/const-generics.rs b/src/test/ui/impl-trait/v2/const-generics.rs new file mode 100644 index 0000000000000..7d09d1898c755 --- /dev/null +++ b/src/test/ui/impl-trait/v2/const-generics.rs @@ -0,0 +1,12 @@ +// check-pass + +#![feature(return_position_impl_trait_v2)] + +trait Trait {} +impl Trait for u32 {} + +fn rawr() -> impl Trait { + 0 +} + +fn main() {} From 79eeffaa5c9b0bdc0aa1b7d2ce7a601e9febf3f6 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 23 May 2022 17:37:08 -0300 Subject: [PATCH 15/53] Pass Generics to lower impl trait instead of generic params We're going to need where clauses too. --- compiler/rustc_ast_lowering/src/expr.rs | 6 ++-- compiler/rustc_ast_lowering/src/item.rs | 12 ++------ compiler/rustc_ast_lowering/src/lib.rs | 37 +++++++++++++++---------- 3 files changed, 30 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index caf09dfd9ee3a..2d43ea2fdcdd6 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -849,7 +849,8 @@ impl<'hir> LoweringContext<'_, 'hir> { let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params); // Lower outside new scope to preserve `is_in_loop_condition`. - let fn_decl = self.lower_fn_decl(decl, None, FnDeclKind::Closure, &[], None); + let fn_decl = + self.lower_fn_decl(decl, None, FnDeclKind::Closure, &Generics::default(), None); let c = self.arena.alloc(hir::Closure { binder: binder_clause, @@ -953,7 +954,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 = self.lower_fn_decl(&outer_decl, None, FnDeclKind::Closure, &[], None); + let fn_decl = + self.lower_fn_decl(&outer_decl, None, FnDeclKind::Closure, &Generics::default(), None); let c = self.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 b892c1bc84f2f..ff333551a6ddd 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -262,13 +262,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let itctx = ImplTraitContext::Universal; let (generics, decl) = this.lower_generics(generics, id, itctx, |this| { let ret_id = asyncness.opt_return_id(); - this.lower_fn_decl( - &decl, - Some(id), - FnDeclKind::Fn, - &generics.params, - ret_id, - ) + this.lower_fn_decl(&decl, Some(id), FnDeclKind::Fn, generics, ret_id) }); let sig = hir::FnSig { decl, @@ -662,7 +656,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fdec, None, FnDeclKind::ExternFn, - &generics.params, + generics, None, ), this.lower_fn_params_to_names(fdec), @@ -1242,7 +1236,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let header = self.lower_fn_header(sig.header); let itctx = ImplTraitContext::Universal; let (generics, decl) = self.lower_generics(generics, id, itctx, |this| { - this.lower_fn_decl(&sig.decl, Some(id), kind, &generics.params, is_async) + this.lower_fn_decl(&sig.decl, Some(id), kind, generics, 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 b7e1f8d137058..2ba95345cbcc3 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -270,8 +270,8 @@ enum ImplTraitContext<'a> { ReturnPositionOpaqueTy { /// Origin: Either OpaqueTyOrigin::FnReturn or OpaqueTyOrigin::AsyncFn, origin: hir::OpaqueTyOrigin, - /// In scope generic types and consts from AST - generic_params: &'a [GenericParam], + /// In scope generics + generics: &'a Generics, }, /// Impl trait in type aliases. TypeAliasesOpaqueTy, @@ -308,8 +308,8 @@ impl ImplTraitContext<'_> { use self::ImplTraitContext::*; match self { Universal => Universal, - ReturnPositionOpaqueTy { origin, generic_params } => { - ReturnPositionOpaqueTy { origin: *origin, generic_params: *generic_params } + ReturnPositionOpaqueTy { origin, generics } => { + ReturnPositionOpaqueTy { origin: *origin, generics: *generics } } TypeAliasesOpaqueTy => TypeAliasesOpaqueTy, Disallowed(pos) => Disallowed(*pos), @@ -1368,7 +1368,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &f.decl, None, FnDeclKind::Pointer, - &f.generic_params, + &Generics { + params: f.generic_params.clone(), + where_clause: WhereClause { + has_where_token: false, + predicates: Vec::new(), + span: DUMMY_SP, + }, + span: DUMMY_SP, + }, None, ), param_names: self.lower_fn_params_to_names(&f.decl), @@ -1437,13 +1445,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { TyKind::ImplTrait(def_node_id, ref bounds) => { let span = t.span; match itctx { - ImplTraitContext::ReturnPositionOpaqueTy { origin, generic_params } => { + ImplTraitContext::ReturnPositionOpaqueTy { origin, generics } => { if self.tcx.sess.features_untracked().return_position_impl_trait_v2 { self.lower_opaque_impl_trait_v2( span, origin, def_node_id, - generic_params, + generics, bounds, itctx, ) @@ -1682,7 +1690,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: Span, origin: hir::OpaqueTyOrigin, opaque_ty_node_id: NodeId, - ast_generic_params: &[GenericParam], + ast_generics: &Generics, bounds: &GenericBounds, itctx: ImplTraitContext<'_>, ) -> hir::TyKind<'hir> { @@ -1726,7 +1734,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { debug!(?collected_lifetimes); debug!(?new_remapping); - lctx.create_generic_defs(opaque_ty_def_id, ast_generic_params, &mut new_remapping); + lctx.create_generic_defs(opaque_ty_def_id, &ast_generics.params, &mut new_remapping); debug!(?new_remapping); // Install the remapping from old to new (if any): @@ -1761,7 +1769,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .collect(); debug!(?lifetime_defs); - let type_const_defs: Vec<_> = ast_generic_params + let type_const_defs: Vec<_> = ast_generics + .params .iter() .filter(|param| { matches!( @@ -1817,7 +1826,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .collect(); debug!(?lifetimes); - let type_const_args = self.collect_type_const_args(ast_generic_params); + let type_const_args = self.collect_type_const_args(&ast_generics.params); let generic_args = self.arena.alloc_from_iter(lifetimes.into_iter().chain(type_const_args.into_iter())); @@ -1944,7 +1953,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { decl: &FnDecl, fn_node_id: Option, kind: FnDeclKind, - generics: &[GenericParam], + generics: &Generics, make_ret_async: Option, ) -> &'hir hir::FnDecl<'hir> { let c_variadic = decl.c_variadic(); @@ -1990,7 +1999,7 @@ 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), - generic_params: generics, + generics, } } _ => ImplTraitContext::Disallowed(match kind { @@ -2286,7 +2295,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // generates. let context = ImplTraitContext::ReturnPositionOpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), - generic_params: &[], + generics: &Generics::default(), }; self.lower_ty(ty, context) } From d102712fd5c0b1c1a1081f1395685ff4e92d1896 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 23 May 2022 18:46:26 -0300 Subject: [PATCH 16/53] Copy generic param bounds and where clauses from function to RPIT --- compiler/rustc_ast_lowering/src/item.rs | 5 +++- compiler/rustc_ast_lowering/src/lib.rs | 33 ++++++++++++++++++++--- src/test/ui/impl-trait/v2/where_bounds.rs | 14 ++++++++++ 3 files changed, 47 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/impl-trait/v2/where_bounds.rs diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index ff333551a6ddd..64762b6008820 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1468,7 +1468,10 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicate<'hir> { + pub(super) fn lower_where_predicate( + &mut self, + pred: &WherePredicate, + ) -> hir::WherePredicate<'hir> { match *pred { WherePredicate::BoundPredicate(WhereBoundPredicate { ref bound_generic_params, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 2ba95345cbcc3..87c9873dd329c 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1692,7 +1692,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { opaque_ty_node_id: NodeId, ast_generics: &Generics, bounds: &GenericBounds, - itctx: ImplTraitContext<'_>, + mut itctx: ImplTraitContext<'_>, ) -> hir::TyKind<'hir> { // Make sure we know that some funky desugaring has been going on here. // This is a first: there is code in other places like for loop @@ -1784,16 +1784,41 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Then when we lower the param bounds, references to 'a are remapped to 'a1, so we // get back Debug + 'a1, which is suitable for use on the TAIT. - let hir_bounds = lctx.lower_param_bounds(bounds, itctx); + let hir_bounds = lctx.lower_param_bounds(bounds, itctx.reborrow()); debug!(?hir_bounds); let generic_defs = lifetime_defs.into_iter().chain(type_const_defs.into_iter()); + let mut predicates: Vec<_> = ast_generics + .params + .iter() + .filter_map(|param| { + lctx.lower_generic_bound_predicate( + param.ident, + param.id, + ¶m.kind, + ¶m.bounds, + itctx.reborrow(), + hir::PredicateOrigin::GenericParam, + ) + }) + .collect(); + + predicates.extend( + ast_generics + .where_clause + .predicates + .iter() + .map(|predicate| lctx.lower_where_predicate(predicate)), + ); + + let has_where_clause_predicates = !predicates.is_empty(); + let opaque_ty_item = hir::OpaqueTy { generics: self.arena.alloc(hir::Generics { params: self.arena.alloc_from_iter(generic_defs), - predicates: &[], - has_where_clause_predicates: false, + predicates: self.arena.alloc_from_iter(predicates), + has_where_clause_predicates, where_clause_span: lctx.lower_span(span), span: lctx.lower_span(span), }), diff --git a/src/test/ui/impl-trait/v2/where_bounds.rs b/src/test/ui/impl-trait/v2/where_bounds.rs new file mode 100644 index 0000000000000..110faa2c977b1 --- /dev/null +++ b/src/test/ui/impl-trait/v2/where_bounds.rs @@ -0,0 +1,14 @@ +// check-pass + +#![feature(return_position_impl_trait_v2)] + +trait MyTrait {} + +fn foo(t: T) -> impl MyTrait +where + T: MyTrait, +{ + t +} + +fn main() {} From 8d2696313d145697542ce47b419bcb31ef12b014 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 5 Aug 2022 15:01:14 -0300 Subject: [PATCH 17/53] Remap on lower_res --- compiler/rustc_ast_lowering/src/lib.rs | 9 +++++++++ compiler/rustc_hir/src/def.rs | 13 +++++++++++++ 2 files changed, 22 insertions(+) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 87c9873dd329c..675f90e2ea069 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -726,6 +726,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { #[instrument(level = "trace", skip(self))] fn lower_res(&mut self, res: Res) -> Res { + let res = res.map_def_id(|def_id| { + if let Some(local_def_id) = def_id.as_local() { + self.resolver.get_remapped_def_id(local_def_id).to_def_id() + } else { + def_id + } + }); + trace!(?res, "from remapping"); + let res: Result = res.apply_id(|id| { let owner = self.current_hir_id_owner; let local_id = self.node_id_to_local_id.get(&id).copied().ok_or(())?; diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 2d2648a8f35af..1412d09d34674 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -650,6 +650,19 @@ impl Res { } } + pub fn map_def_id(self, mut map: impl FnMut(DefId) -> DefId) -> Res { + match self { + Res::Def(kind, id) => Res::Def(kind, map(id)), + Res::SelfCtor(id) => Res::SelfCtor(id), + Res::PrimTy(id) => Res::PrimTy(id), + Res::Local(id) => Res::Local(id), + Res::SelfTy { trait_, alias_to } => Res::SelfTy { trait_, alias_to }, + Res::ToolMod => Res::ToolMod, + Res::NonMacroAttr(attr_kind) => Res::NonMacroAttr(attr_kind), + Res::Err => Res::Err, + } + } + pub fn apply_id(self, mut map: impl FnMut(Id) -> Result) -> Result, E> { Ok(match self { Res::Def(kind, id) => Res::Def(kind, id), From a08ff689c51e05451680511de1eaac77118e2899 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 5 Aug 2022 19:26:07 -0300 Subject: [PATCH 18/53] Lower lifetime bounds/predicates as static if not part of RPIT bounds --- compiler/rustc_ast_lowering/src/item.rs | 1 + compiler/rustc_ast_lowering/src/lib.rs | 31 ++++++++++++++++++++----- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 64762b6008820..42f96d2831ff9 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -82,6 +82,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { current_item: None, impl_trait_defs: Vec::new(), impl_trait_bounds: Vec::new(), + in_scope_generics: Vec::new(), allow_try_trait: Some([sym::try_trait_v2, sym::yeet_desugar_details][..].into()), allow_gen_future: Some([sym::gen_future][..].into()), allow_into_future: Some([sym::into_future][..].into()), diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 675f90e2ea069..81fbbeb30584d 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -126,6 +126,8 @@ struct LoweringContext<'a, 'hir> { impl_trait_defs: Vec>, impl_trait_bounds: Vec>, + in_scope_generics: Vec, + /// NodeIds that are lowered inside the current HIR owner. node_id_to_local_id: FxHashMap, @@ -611,11 +613,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn with_remapping( &mut self, remap: FxHashMap, + in_scope_generics: &[LocalDefId], f: impl FnOnce(&mut Self) -> R, ) -> R { + let original_len = self.in_scope_generics.len(); + self.in_scope_generics + .extend(in_scope_generics.iter().filter(|in_scope| !remap.contains_key(in_scope))); self.resolver.generics_def_id_map.push(remap); let res = f(self); self.resolver.generics_def_id_map.pop(); + self.in_scope_generics.truncate(original_len); res } @@ -1590,7 +1597,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { debug!(?new_remapping); // Install the remapping from old to new (if any): - lctx.with_remapping(new_remapping, |lctx| { + lctx.with_remapping(new_remapping, &[], |lctx| { // This creates HIR lifetime definitions as `hir::GenericParam`, in the given // example `type TestReturn<'a, T, 'x> = impl Debug + 'x`, it creates a collection // containing `&['x]`. @@ -1746,8 +1753,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { lctx.create_generic_defs(opaque_ty_def_id, &ast_generics.params, &mut new_remapping); debug!(?new_remapping); + let in_scope_generics: Vec<_> = + ast_generics.params.iter().map(|param| lctx.local_def_id(param.id)).collect(); + // Install the remapping from old to new (if any): - lctx.with_remapping(new_remapping, |lctx| { + lctx.with_remapping(new_remapping, &in_scope_generics, |lctx| { // This creates HIR lifetime definitions as `hir::GenericParam`, in the given // example `type TestReturn<'a, T, 'x> = impl Debug + 'x`, it creates a collection // containing `&['x]`. @@ -1801,6 +1811,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let mut predicates: Vec<_> = ast_generics .params .iter() + .filter(|param| { + matches!( + param.kind, + GenericParamKind::Const { .. } | GenericParamKind::Type { .. } + ) + }) .filter_map(|param| { lctx.lower_generic_bound_predicate( param.ident, @@ -2215,7 +2231,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { debug!(?new_remapping); // Install the remapping from old to new (if any): - this.with_remapping(new_remapping, |this| { + this.with_remapping(new_remapping, &[], |this| { // We have to be careful to get elision right here. The // idea is that we create a lifetime parameter for each // lifetime in the return type. So, given a return type @@ -2387,9 +2403,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let name = match res { LifetimeRes::Param { param, .. } => { let p_name = ParamName::Plain(ident); - let param = self.resolver.get_remapped_def_id(param); - - hir::LifetimeName::Param(param, p_name) + if self.in_scope_generics.contains(¶m) { + hir::LifetimeName::Static + } else { + let param = self.resolver.get_remapped_def_id(param); + hir::LifetimeName::Param(param, p_name) + } } LifetimeRes::Fresh { param, .. } => { debug_assert_eq!(ident.name, kw::UnderscoreLifetime); From cce54129f34255c999897bdca580f3adb3620363 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 24 May 2022 17:30:35 -0300 Subject: [PATCH 19/53] Add APIT test for RPIT v2 --- src/test/ui/impl-trait/v2/apit.rs | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/test/ui/impl-trait/v2/apit.rs diff --git a/src/test/ui/impl-trait/v2/apit.rs b/src/test/ui/impl-trait/v2/apit.rs new file mode 100644 index 0000000000000..a4d3049f5af8a --- /dev/null +++ b/src/test/ui/impl-trait/v2/apit.rs @@ -0,0 +1,9 @@ +// check-pass + +trait MyTrait {} + +fn foo(f: impl MyTrait) -> impl MyTrait { + f +} + +fn main() {} From 3b4ab9d48adc1c8221f04ff31a66c2f938522bf2 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 24 May 2022 17:32:15 -0300 Subject: [PATCH 20/53] Add bounds regression test for RPIT v2 --- .../ui/impl-trait/v2/bounds_regression.rs | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 src/test/ui/impl-trait/v2/bounds_regression.rs diff --git a/src/test/ui/impl-trait/v2/bounds_regression.rs b/src/test/ui/impl-trait/v2/bounds_regression.rs new file mode 100644 index 0000000000000..72a53ee6cc4a7 --- /dev/null +++ b/src/test/ui/impl-trait/v2/bounds_regression.rs @@ -0,0 +1,26 @@ +// check-pass + +#![feature(return_position_impl_trait_v2)] + +pub trait FakeGenerator { + type Yield; + type Return; +} + +pub trait FakeFuture { + type Output; +} + +pub fn future_from_generator>( + x: T, +) -> impl FakeFuture { + GenFuture(x) +} + +struct GenFuture>(T); + +impl> FakeFuture for GenFuture { + type Output = T::Return; +} + +fn main() {} From be33fa24aa7452afba36328c122b445b44966a56 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 24 May 2022 17:32:55 -0300 Subject: [PATCH 21/53] Add generic associated type test for RPIT v2 --- src/test/ui/impl-trait/v2/generics-assoc-type.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/test/ui/impl-trait/v2/generics-assoc-type.rs diff --git a/src/test/ui/impl-trait/v2/generics-assoc-type.rs b/src/test/ui/impl-trait/v2/generics-assoc-type.rs new file mode 100644 index 0000000000000..c5c3adcc05a62 --- /dev/null +++ b/src/test/ui/impl-trait/v2/generics-assoc-type.rs @@ -0,0 +1,16 @@ +// check-pass + +#![feature(return_position_impl_trait_v2)] + +trait MyTrait {} + +impl MyTrait for T {} + +fn ident_as_my_trait<'a, T>(_u: &'a i32, t: T) -> impl MyTrait +where + 'static: 'a, +{ + t +} + +fn main() {} From c67ab47d8c8bdc90f7e26eda3f42133e705fc0b9 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 24 May 2022 17:35:43 -0300 Subject: [PATCH 22/53] Add where bounds test for RPIT v2 --- src/test/ui/impl-trait/v2/where_bounds2.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/test/ui/impl-trait/v2/where_bounds2.rs diff --git a/src/test/ui/impl-trait/v2/where_bounds2.rs b/src/test/ui/impl-trait/v2/where_bounds2.rs new file mode 100644 index 0000000000000..a729aafd754c7 --- /dev/null +++ b/src/test/ui/impl-trait/v2/where_bounds2.rs @@ -0,0 +1,11 @@ +// check-pass + +#![feature(return_position_impl_trait_v2)] + +trait MyTrait {} + +fn foo(t: T) -> impl MyTrait { + t +} + +fn main() {} From 064675d5b9e9bff377e7bb7ac556f6723b96bbf5 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 8 Jun 2022 20:35:44 -0300 Subject: [PATCH 23/53] Lower APIT generics to RPIT --- Cargo.lock | 5 +- compiler/rustc_ast_lowering/Cargo.toml | 1 + compiler/rustc_ast_lowering/src/item.rs | 38 +- compiler/rustc_ast_lowering/src/lib.rs | 344 +++++++++++++----- compiler/rustc_ast_lowering/src/path.rs | 46 +-- .../ui/impl-trait/v2/async-await-bounds.rs | 16 + .../v2/async-await-generics-and-bounds.rs | 9 + 7 files changed, 337 insertions(+), 122 deletions(-) create mode 100644 src/test/ui/impl-trait/v2/async-await-bounds.rs create mode 100644 src/test/ui/impl-trait/v2/async-await-generics-and-bounds.rs diff --git a/Cargo.lock b/Cargo.lock index f83678f0ca671..47daaa030c201 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1911,9 +1911,9 @@ dependencies = [ [[package]] name = "itertools" -version = "0.10.1" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf" +checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" dependencies = [ "either", ] @@ -3216,6 +3216,7 @@ dependencies = [ name = "rustc_ast_lowering" version = "0.0.0" dependencies = [ + "itertools", "rustc_arena", "rustc_ast", "rustc_ast_pretty", diff --git a/compiler/rustc_ast_lowering/Cargo.toml b/compiler/rustc_ast_lowering/Cargo.toml index ce1c8d4997d74..a32968dd97d27 100644 --- a/compiler/rustc_ast_lowering/Cargo.toml +++ b/compiler/rustc_ast_lowering/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" doctest = false [dependencies] +itertools = "0.10.3" rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 42f96d2831ff9..68e9336b93a2e 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1,7 +1,7 @@ use super::errors::{InvalidAbi, MisplacedRelaxTraitBound}; use super::ResolverAstLoweringExt; use super::{AstOwner, ImplTraitContext, ImplTraitPosition}; -use super::{FnDeclKind, LoweringContext, ParamMode}; +use super::{FnDeclKind, LoweringArena, LoweringContext, ParamMode}; use rustc_ast::ptr::P; use rustc_ast::visit::AssocCtxt; @@ -25,6 +25,7 @@ use std::iter; pub(super) struct ItemLowerer<'a, 'hir> { pub(super) tcx: TyCtxt<'hir>, pub(super) resolver: &'a mut ResolverAstLowering, + pub(super) lowering_arena: &'a LoweringArena, pub(super) ast_index: &'a IndexVec>, pub(super) owners: &'a mut IndexVec>>, } @@ -60,6 +61,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { tcx: self.tcx, resolver: self.resolver, arena: self.tcx.hir_arena, + lowering_arena: self.lowering_arena, // HirId handling. bodies: Vec::new(), @@ -158,7 +160,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { } } -impl<'hir> LoweringContext<'_, 'hir> { +impl<'a, 'hir> LoweringContext<'a, 'hir> { pub(super) fn lower_mod(&mut self, items: &[P], spans: &ModSpans) -> hir::Mod<'hir> { hir::Mod { spans: hir::ModSpans { @@ -260,7 +262,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let body_id = this.lower_maybe_async_body(span, &decl, asyncness, body.as_deref()); - let itctx = ImplTraitContext::Universal; + let itctx = ImplTraitContext::Universal { apit_nodes: &mut Vec::new() }; let (generics, decl) = this.lower_generics(generics, id, itctx, |this| { let ret_id = asyncness.opt_return_id(); this.lower_fn_decl(&decl, Some(id), FnDeclKind::Fn, generics, ret_id) @@ -379,7 +381,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // method, it will not be considered an in-band // lifetime to be added, but rather a reference to a // parent lifetime. - let itctx = ImplTraitContext::Universal; + let itctx = ImplTraitContext::Universal { apit_nodes: &mut Vec::new() }; let (generics, (trait_ref, lowered_ty)) = self.lower_generics(ast_generics, id, itctx, |this| { let trait_ref = trait_ref.as_ref().map(|trait_ref| { @@ -648,7 +650,7 @@ impl<'hir> LoweringContext<'_, 'hir> { kind: match i.kind { ForeignItemKind::Fn(box Fn { ref sig, ref generics, .. }) => { let fdec = &sig.decl; - let itctx = ImplTraitContext::Universal; + let itctx = ImplTraitContext::Universal { apit_nodes: &mut Vec::new() }; let (generics, (fn_dec, fn_args)) = self.lower_generics(generics, i.id, itctx, |this| { ( @@ -1235,7 +1237,7 @@ impl<'hir> LoweringContext<'_, 'hir> { is_async: Option, ) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) { let header = self.lower_fn_header(sig.header); - let itctx = ImplTraitContext::Universal; + let itctx = ImplTraitContext::Universal { apit_nodes: &mut Vec::new() }; let (generics, decl) = self.lower_generics(generics, id, itctx, |this| { this.lower_fn_decl(&sig.decl, Some(id), kind, generics, is_async) }); @@ -1298,13 +1300,16 @@ impl<'hir> LoweringContext<'_, 'hir> { /// Return the pair of the lowered `generics` as `hir::Generics` and the evaluation of `f` with /// the carried impl trait definitions and bounds. #[instrument(level = "debug", skip(self, f))] - fn lower_generics( + fn lower_generics<'itctx, T>( &mut self, - generics: &Generics, + generics: &'itctx Generics, parent_node_id: NodeId, - mut itctx: ImplTraitContext<'_>, + mut itctx: ImplTraitContext<'_, 'itctx>, f: impl FnOnce(&mut Self) -> T, - ) -> (&'hir hir::Generics<'hir>, T) { + ) -> (&'hir hir::Generics<'hir>, T) + where + 'a: 'itctx, + { debug_assert!(self.impl_trait_defs.is_empty()); debug_assert!(self.impl_trait_bounds.is_empty()); @@ -1401,21 +1406,24 @@ impl<'hir> LoweringContext<'_, 'hir> { (lowered_generics, res) } - pub(super) fn lower_generic_bound_predicate( + pub(super) fn lower_generic_bound_predicate<'itctx>( &mut self, ident: Ident, id: NodeId, kind: &GenericParamKind, - bounds: &[GenericBound], - itctx: ImplTraitContext<'_>, + bounds: &'itctx [GenericBound], + mut itctx: ImplTraitContext<'_, 'itctx>, origin: PredicateOrigin, - ) -> Option> { + ) -> Option> + where + 'a: 'itctx, + { // Do not create a clause if we do not have anything inside it. if bounds.is_empty() { return None; } - let bounds = self.lower_param_bounds(bounds, itctx); + let bounds = self.lower_param_bounds(bounds, itctx.reborrow()); let ident = self.lower_ident(ident); let param_span = ident.span; diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 81fbbeb30584d..dc3206cd82232 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -44,6 +44,7 @@ extern crate tracing; use crate::errors::{AssocTyParentheses, AssocTyParenthesesSub, MisplacedImplTrait}; +use rustc_arena::TypedArena; use rustc_ast::ptr::P; use rustc_ast::visit; use rustc_ast::{self as ast, *}; @@ -95,6 +96,13 @@ struct LoweringContext<'a, 'hir> { /// Used to allocate HIR nodes. arena: &'hir hir::Arena<'hir>, + /// Used to allocate temporary AST nodes for use during lowering. + /// This allows us to create "fake" AST -- these nodes can sometimes + /// be allocated on the stack, but other times we need them to live longer + /// than the current stack frame, so they can be collected into vectors + /// and things like that. + lowering_arena: &'a LoweringArena, + /// Bodies inside the owner being lowered. bodies: Vec<(hir::ItemLocalId, &'hir hir::Body<'hir>)>, /// Attributes inside the owner being lowered. @@ -136,6 +144,12 @@ struct LoweringContext<'a, 'hir> { allow_into_future: Option>, } +struct LoweringArena { + tys: TypedArena, + aba: TypedArena, + ptr: TypedArena, +} + trait ResolverAstLoweringExt { fn legacy_const_generic_args(&self, expr: &Expr) -> Option>; fn get_partial_res(&self, id: NodeId) -> Option; @@ -257,13 +271,13 @@ impl ResolverAstLoweringExt for ResolverAstLowering { /// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree, /// and if so, what meaning it has. #[derive(Debug)] -enum ImplTraitContext<'a> { +enum ImplTraitContext<'b, 'itctx> { /// Treat `impl Trait` as shorthand for a new universal generic parameter. /// Example: `fn foo(x: impl Debug)`, where `impl Debug` is conceptually /// equivalent to a fresh universal parameter like `fn foo(x: T)`. /// /// Newly generated parameters should be inserted into the given `Vec`. - Universal, + Universal { apit_nodes: &'b mut Vec<&'itctx Ty> }, /// Treat `impl Trait` as shorthand for a new opaque type. /// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually @@ -272,8 +286,9 @@ enum ImplTraitContext<'a> { ReturnPositionOpaqueTy { /// Origin: Either OpaqueTyOrigin::FnReturn or OpaqueTyOrigin::AsyncFn, origin: hir::OpaqueTyOrigin, + impl_trait_inputs: &'b Vec<&'itctx Ty>, /// In scope generics - generics: &'a Generics, + generics: &'itctx Generics, }, /// Impl trait in type aliases. TypeAliasesOpaqueTy, @@ -305,13 +320,17 @@ enum ImplTraitPosition { ImplReturn, } -impl ImplTraitContext<'_> { - fn reborrow(&mut self) -> ImplTraitContext<'_> { +impl<'itctx> ImplTraitContext<'_, 'itctx> { + fn reborrow<'this>(&'this mut self) -> ImplTraitContext<'this, 'itctx> { use self::ImplTraitContext::*; match self { - Universal => Universal, - ReturnPositionOpaqueTy { origin, generics } => { - ReturnPositionOpaqueTy { origin: *origin, generics: *generics } + Universal { apit_nodes } => Universal { apit_nodes: *apit_nodes }, + ReturnPositionOpaqueTy { origin, impl_trait_inputs, generics } => { + ReturnPositionOpaqueTy { + origin: *origin, + impl_trait_inputs: *impl_trait_inputs, + generics: *generics, + } } TypeAliasesOpaqueTy => TypeAliasesOpaqueTy, Disallowed(pos) => Disallowed(*pos), @@ -454,10 +473,17 @@ pub fn lower_to_hir<'hir>(tcx: TyCtxt<'hir>, (): ()) -> hir::Crate<'hir> { tcx.definitions_untracked().def_index_count(), ); + let lowering_arena = LoweringArena { + tys: TypedArena::default(), + aba: TypedArena::default(), + ptr: TypedArena::default(), + }; + for def_id in ast_index.indices() { item::ItemLowerer { tcx, resolver: &mut resolver, + lowering_arena: &lowering_arena, ast_index: &ast_index, owners: &mut owners, } @@ -1087,11 +1113,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// /// returns a `hir::TypeBinding` representing `Item`. #[instrument(level = "debug", skip(self))] - fn lower_assoc_ty_constraint( + fn lower_assoc_ty_constraint<'itctx>( &mut self, - constraint: &AssocConstraint, - mut itctx: ImplTraitContext<'_>, - ) -> hir::TypeBinding<'hir> { + constraint: &'itctx AssocConstraint, + mut itctx: ImplTraitContext<'_, 'itctx>, + ) -> hir::TypeBinding<'hir> + where + 'a: 'itctx, + { debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", constraint, itctx); // lower generic arguments of identifier in constraint let gen_args = if let Some(ref gen_args) = constraint.gen_args { @@ -1106,8 +1135,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } GenericArgs::Parenthesized(ref data) => { self.emit_bad_parenthesized_trait_in_assoc_ty(data); + let aba = self.lowering_arena.aba.alloc(data.as_angle_bracketed_args()); self.lower_angle_bracketed_parameter_data( - &data.as_angle_bracketed_args(), + aba, ParamMode::Explicit, itctx.reborrow(), ) @@ -1147,7 +1177,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // so desugar to // // fn foo(x: dyn Iterator) - ImplTraitContext::Universal if self.is_in_dyn_type => (true, itctx.reborrow()), + ImplTraitContext::Universal { .. } if self.is_in_dyn_type => { + (true, itctx.reborrow()) + } // In `type Foo = dyn Iterator` we desugar to // `type Foo = dyn Iterator` but we have to override the @@ -1179,15 +1211,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.with_dyn_type_scope(false, |this| { let node_id = this.next_node_id(); - let ty = this.lower_ty( - &Ty { - id: node_id, - kind: TyKind::ImplTrait(impl_trait_node_id, bounds.clone()), - span: this.lower_span(constraint.span), - tokens: None, - }, - itctx, - ); + let ty = this.lowering_arena.tys.alloc(Ty { + id: node_id, + kind: TyKind::ImplTrait(impl_trait_node_id, bounds.clone()), + span: this.lower_span(constraint.span), + tokens: None, + }); + let ty = this.lower_ty(ty, itctx); hir::TypeBindingKind::Equality { term: ty.into() } }) @@ -1235,11 +1265,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } #[instrument(level = "debug", skip(self))] - fn lower_generic_arg( + fn lower_generic_arg<'itctx>( &mut self, - arg: &ast::GenericArg, - itctx: ImplTraitContext<'_>, - ) -> hir::GenericArg<'hir> { + arg: &'itctx ast::GenericArg, + itctx: ImplTraitContext<'_, 'itctx>, + ) -> hir::GenericArg<'hir> + where + 'a: 'itctx, + { match arg { ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(<)), ast::GenericArg::Type(ty) => { @@ -1290,7 +1323,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } _ => {} } - GenericArg::Type(self.lower_ty_direct(&ty, itctx)) + GenericArg::Type(self.lower_ty_direct(ty, itctx)) } ast::GenericArg::Const(ct) => GenericArg::Const(ConstArg { value: self.lower_anon_const(&ct), @@ -1300,18 +1333,28 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } #[instrument(level = "debug", skip(self))] - fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext<'_>) -> &'hir hir::Ty<'hir> { + fn lower_ty<'itctx>( + &mut self, + t: &'itctx Ty, + itctx: ImplTraitContext<'_, 'itctx>, + ) -> &'hir hir::Ty<'hir> + where + 'a: 'itctx, + { self.arena.alloc(self.lower_ty_direct(t, itctx)) } - fn lower_path_ty( + fn lower_path_ty<'itctx>( &mut self, - t: &Ty, - qself: &Option, - path: &Path, + t: &'itctx Ty, + qself: &'itctx Option, + path: &'itctx Path, param_mode: ParamMode, - itctx: ImplTraitContext<'_>, - ) -> hir::Ty<'hir> { + itctx: ImplTraitContext<'_, 'itctx>, + ) -> hir::Ty<'hir> + where + 'a: 'itctx, + { // Check whether we should interpret this as a bare trait object. // This check mirrors the one in late resolution. We only introduce this special case in // the rare occurrence we need to lower `Fresh` anonymous lifetimes. @@ -1323,12 +1366,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { && let Res::Def(DefKind::Trait | DefKind::TraitAlias, _) = partial_res.base_res() { let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| { + let poly_trait_ref = this.lowering_arena.ptr.alloc(PolyTraitRef { + bound_generic_params: vec![], + trait_ref: TraitRef { path: path.clone(), ref_id: t.id }, + span: t.span + }); let bound = this.lower_poly_trait_ref( - &PolyTraitRef { - bound_generic_params: vec![], - trait_ref: TraitRef { path: path.clone(), ref_id: t.id }, - span: t.span - }, + poly_trait_ref, itctx, ); let bounds = this.arena.alloc_from_iter([bound]); @@ -1352,7 +1396,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.ty(span, hir::TyKind::Tup(tys)) } - fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_>) -> hir::Ty<'hir> { + fn lower_ty_direct<'itctx>( + &mut self, + t: &'itctx Ty, + mut itctx: ImplTraitContext<'_, 'itctx>, + ) -> hir::Ty<'hir> + where + 'a: 'itctx, + { let kind = match t.kind { TyKind::Infer => hir::TyKind::Infer, TyKind::Err => hir::TyKind::Err, @@ -1461,13 +1512,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { TyKind::ImplTrait(def_node_id, ref bounds) => { let span = t.span; match itctx { - ImplTraitContext::ReturnPositionOpaqueTy { origin, generics } => { + ImplTraitContext::ReturnPositionOpaqueTy { + origin, + impl_trait_inputs, + generics, + } => { if self.tcx.sess.features_untracked().return_position_impl_trait_v2 { self.lower_opaque_impl_trait_v2( span, origin, def_node_id, generics, + impl_trait_inputs, bounds, itctx, ) @@ -1485,7 +1541,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { nested_itctx, ) } - ImplTraitContext::Universal => { + ImplTraitContext::Universal { apit_nodes } => { let span = t.span; let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span); let (param, bounds, path) = @@ -1494,6 +1550,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { if let Some(bounds) = bounds { self.impl_trait_bounds.push(bounds); } + apit_nodes.push(t); path } ImplTraitContext::Disallowed(position) => { @@ -1548,14 +1605,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// capture the lifetimes that are referenced in the bounds. Therefore, we add *extra* lifetime parameters /// for the lifetimes that get captured (`'x`, in our example above) and reference those. #[instrument(level = "debug", skip(self))] - fn lower_opaque_impl_trait( + fn lower_opaque_impl_trait<'itctx>( &mut self, span: Span, origin: hir::OpaqueTyOrigin, opaque_ty_node_id: NodeId, - bounds: &GenericBounds, - itctx: ImplTraitContext<'_>, - ) -> hir::TyKind<'hir> { + bounds: &'itctx GenericBounds, + itctx: ImplTraitContext<'_, 'itctx>, + ) -> hir::TyKind<'hir> + where + 'a: 'itctx, + { // Make sure we know that some funky desugaring has been going on here. // This is a first: there is code in other places like for loop // desugaring that explicitly states that we don't want to track that. @@ -1701,15 +1761,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// capture the lifetimes that are referenced in the bounds. Therefore, we add *extra* lifetime parameters /// for the lifetimes that get captured (`'x`, in our example above) and reference those. #[tracing::instrument(level = "debug", skip(self))] - fn lower_opaque_impl_trait_v2( + fn lower_opaque_impl_trait_v2<'itctx>( &mut self, span: Span, origin: hir::OpaqueTyOrigin, opaque_ty_node_id: NodeId, - ast_generics: &Generics, - bounds: &GenericBounds, - mut itctx: ImplTraitContext<'_>, - ) -> hir::TyKind<'hir> { + ast_generics: &'itctx Generics, + impl_trait_inputs: &Vec<&Ty>, + bounds: &'itctx GenericBounds, + mut itctx: ImplTraitContext<'_, 'itctx>, + ) -> hir::TyKind<'hir> + where + 'a: 'itctx, + { // Make sure we know that some funky desugaring has been going on here. // This is a first: there is code in other places like for loop // desugaring that explicitly states that we don't want to track that. @@ -1753,8 +1817,40 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { lctx.create_generic_defs(opaque_ty_def_id, &ast_generics.params, &mut new_remapping); debug!(?new_remapping); - let in_scope_generics: Vec<_> = - ast_generics.params.iter().map(|param| lctx.local_def_id(param.id)).collect(); + for ty in impl_trait_inputs { + if let TyKind::ImplTrait(node_id, _) = ty.kind { + let old_def_id = lctx.local_def_id(node_id); + + let node_id = lctx.next_node_id(); + // Add a definition for the generic param def. + let new_def_id = + lctx.create_def(opaque_ty_def_id, node_id, DefPathData::ImplTrait); + + new_remapping.insert(old_def_id, new_def_id); + } else { + unreachable!( + "impl_trait_inputs contains {:?} which is not TyKind::ImplTrait(..)", + ty.kind + ); + } + } + + let in_scope_generics: Vec<_> = ast_generics + .params + .iter() + .map(|param| param.id) + .chain(impl_trait_inputs.iter().map(|ty| { + if let TyKind::ImplTrait(node_id, _) = ty.kind { + node_id + } else { + unreachable!( + "impl_trait_inputs contains {:?} which is not TyKind::ImplTrait(..)", + ty.kind + ); + } + })) + .map(|node_id| lctx.local_def_id(node_id)) + .collect(); // Install the remapping from old to new (if any): lctx.with_remapping(new_remapping, &in_scope_generics, |lctx| { @@ -1801,12 +1897,38 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .collect(); debug!(?type_const_defs); + let (universal_params, universal_predicates, _): ( + Vec<_>, + Vec<_>, + Vec<_>, + ) = itertools::multiunzip(impl_trait_inputs.iter().map(|ty| { + // FIXME + if let TyKind::ImplTrait(node_id, ref bounds) = ty.kind { + let span = ty.span; + let ident = Ident::from_str_and_span(&pprust::ty_to_string(ty), span); + // FIXME: unsure if this is going to work or do we need to first create all + // the def_ids and then call this lower_generic_and_bounds method + lctx.lower_generic_and_bounds(node_id, span, ident, bounds) + } else { + unreachable!( + "impl_trait_inputs contains {:?} which is not TyKind::ImplTrait(..)", + ty.kind + ); + } + })); + + debug!(?universal_params); + debug!(?universal_predicates); + // Then when we lower the param bounds, references to 'a are remapped to 'a1, so we // get back Debug + 'a1, which is suitable for use on the TAIT. let hir_bounds = lctx.lower_param_bounds(bounds, itctx.reborrow()); debug!(?hir_bounds); - let generic_defs = lifetime_defs.into_iter().chain(type_const_defs.into_iter()); + let generic_defs = lifetime_defs + .into_iter() + .chain(type_const_defs.into_iter()) + .chain(universal_params); let mut predicates: Vec<_> = ast_generics .params @@ -1836,6 +1958,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .iter() .map(|predicate| lctx.lower_where_predicate(predicate)), ); + predicates.extend(universal_predicates.into_iter().flatten()); let has_where_clause_predicates = !predicates.is_empty(); @@ -1878,8 +2001,35 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let type_const_args = self.collect_type_const_args(&ast_generics.params); - let generic_args = - self.arena.alloc_from_iter(lifetimes.into_iter().chain(type_const_args.into_iter())); + let universal_args: Vec<_> = impl_trait_inputs.iter().map(|ty| match ty.kind { + TyKind::ImplTrait(node_id, _) => { + let def_id = self.local_def_id(node_id); + let span = ty.span; + let ident = Ident::from_str_and_span(&pprust::ty_to_string(ty), span); + hir::GenericArg::Type(hir::Ty { + hir_id: self.next_id(), + span, + kind: hir::TyKind::Path(hir::QPath::Resolved(None, self.arena.alloc(hir::Path { + span: self.lower_span(span), + res: Res::Def(DefKind::TyParam, def_id.to_def_id()), + segments: arena_vec![self; hir::PathSegment::from_ident(self.lower_ident(ident))], + }))) + }) + } + _ => { + unreachable!( + "impl_trait_inputs contains {:?} which is not TyKind::ImplTrait(..)", + ty.kind + ); + } + }).collect(); + + let generic_args = self.arena.alloc_from_iter( + lifetimes + .into_iter() + .chain(type_const_args.into_iter()) + .chain(universal_args.into_iter()), + ); // `impl Trait` now just becomes `Foo<'a, 'b, ..>`. hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, generic_args) @@ -2011,13 +2161,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Skip the `...` (`CVarArgs`) trailing arguments from the AST, // as they are not explicit in HIR/Ty function signatures. // (instead, the `c_variadic` flag is set to `true`) - let mut inputs = &decl.inputs[..]; + let mut ast_inputs = &decl.inputs[..]; if c_variadic { - inputs = &inputs[..inputs.len() - 1]; + ast_inputs = &ast_inputs[..ast_inputs.len() - 1]; } - let inputs = self.arena.alloc_from_iter(inputs.iter().map(|param| { + let mut impl_trait_inputs = vec![]; + let inputs = self.arena.alloc_from_iter(ast_inputs.iter().map(|param| { if fn_node_id.is_some() { - self.lower_ty_direct(¶m.ty, ImplTraitContext::Universal) + self.lower_ty_direct( + ¶m.ty, + ImplTraitContext::Universal { apit_nodes: &mut impl_trait_inputs }, + ) } else { self.lower_ty_direct( ¶m.ty, @@ -2049,6 +2203,7 @@ 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), + impl_trait_inputs: &impl_trait_inputs, generics, } } @@ -2345,6 +2500,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // generates. let context = ImplTraitContext::ReturnPositionOpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), + impl_trait_inputs: &mut Vec::new(), generics: &Generics::default(), }; self.lower_ty(ty, context) @@ -2370,11 +2526,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } #[instrument(level = "trace", skip(self))] - fn lower_param_bound( + fn lower_param_bound<'itctx>( &mut self, - tpb: &GenericBound, - itctx: ImplTraitContext<'_>, - ) -> hir::GenericBound<'hir> { + tpb: &'itctx GenericBound, + itctx: ImplTraitContext<'_, 'itctx>, + ) -> hir::GenericBound<'hir> + where + 'a: 'itctx, + { match tpb { GenericBound::Trait(p, modifier) => hir::GenericBound::Trait( self.lower_poly_trait_ref(p, itctx), @@ -2506,11 +2665,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } - fn lower_trait_ref( + fn lower_trait_ref<'itctx>( &mut self, - p: &TraitRef, - itctx: ImplTraitContext<'_>, - ) -> hir::TraitRef<'hir> { + p: &'itctx TraitRef, + itctx: ImplTraitContext<'_, 'itctx>, + ) -> hir::TraitRef<'hir> + where + 'a: 'itctx, + { let path = match self.lower_qpath(p.ref_id, &None, &p.path, ParamMode::Explicit, itctx) { hir::QPath::Resolved(None, path) => path, qpath => panic!("lower_trait_ref: unexpected QPath `{:?}`", qpath), @@ -2519,34 +2681,50 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } #[instrument(level = "debug", skip(self))] - fn lower_poly_trait_ref( + fn lower_poly_trait_ref<'itctx>( &mut self, - p: &PolyTraitRef, - itctx: ImplTraitContext<'_>, - ) -> hir::PolyTraitRef<'hir> { + p: &'itctx PolyTraitRef, + itctx: ImplTraitContext<'_, 'itctx>, + ) -> hir::PolyTraitRef<'hir> + where + 'a: 'itctx, + { let bound_generic_params = self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params); let trait_ref = self.lower_trait_ref(&p.trait_ref, itctx); hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) } } - fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext<'_>) -> hir::MutTy<'hir> { + fn lower_mt<'itctx>( + &mut self, + mt: &'itctx MutTy, + itctx: ImplTraitContext<'_, 'itctx>, + ) -> hir::MutTy<'hir> + where + 'a: 'itctx, + { hir::MutTy { ty: self.lower_ty(&mt.ty, itctx), mutbl: mt.mutbl } } - fn lower_param_bounds( + fn lower_param_bounds<'itctx>( &mut self, - bounds: &[GenericBound], - itctx: ImplTraitContext<'_>, - ) -> hir::GenericBounds<'hir> { + bounds: &'itctx [GenericBound], + itctx: ImplTraitContext<'_, 'itctx>, + ) -> hir::GenericBounds<'hir> + where + 'a: 'itctx, + { self.arena.alloc_from_iter(self.lower_param_bounds_mut(bounds, itctx)) } - fn lower_param_bounds_mut<'s>( + fn lower_param_bounds_mut<'s, 'itctx>( &'s mut self, - bounds: &'s [GenericBound], - mut itctx: ImplTraitContext<'s>, - ) -> impl Iterator> + Captures<'s> + Captures<'a> { + bounds: &'itctx [GenericBound], + mut itctx: ImplTraitContext<'s, 'itctx>, + ) -> impl Iterator> + Captures<'s> + Captures<'a> + Captures<'itctx> + where + 'a: 'itctx, + { bounds.iter().map(move |bound| self.lower_param_bound(bound, itctx.reborrow())) } @@ -2575,7 +2753,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { node_id, &GenericParamKind::Type { default: None }, bounds, - ImplTraitContext::Universal, + ImplTraitContext::Universal { apit_nodes: &mut Vec::new() }, hir::PredicateOrigin::ImplTrait, ); diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index e5c18001b65c9..1f6e10c46fbb2 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -16,14 +16,17 @@ use smallvec::smallvec; impl<'a, 'hir> LoweringContext<'a, 'hir> { #[instrument(level = "trace", skip(self))] - pub(crate) fn lower_qpath( + pub(crate) fn lower_qpath<'itctx>( &mut self, id: NodeId, - qself: &Option, - p: &Path, + qself: &'itctx Option, + p: &'itctx Path, param_mode: ParamMode, - mut itctx: ImplTraitContext<'_>, - ) -> hir::QPath<'hir> { + mut itctx: ImplTraitContext<'_, 'itctx>, + ) -> hir::QPath<'hir> + where + 'a: 'itctx, + { let qself_position = qself.as_ref().map(|q| q.position); let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx.reborrow())); @@ -174,14 +177,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.lower_path_extra(res, p, param_mode) } - pub(crate) fn lower_path_segment( + pub(crate) fn lower_path_segment<'itctx>( &mut self, path_span: Span, - segment: &PathSegment, + segment: &'itctx PathSegment, param_mode: ParamMode, parenthesized_generic_args: ParenthesizedGenericArgs, - itctx: ImplTraitContext<'_>, - ) -> hir::PathSegment<'hir> { + itctx: ImplTraitContext<'_, 'itctx>, + ) -> hir::PathSegment<'hir> + where + 'a: 'itctx, + { debug!("path_span: {:?}, lower_path_segment(segment: {:?})", path_span, segment,); let (mut generic_args, infer_args) = if let Some(ref generic_args) = segment.args { match **generic_args { @@ -214,15 +220,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { None }; self.tcx.sess.emit_err(GenericTypeWithParentheses { span: data.span, sub }); - ( - self.lower_angle_bracketed_parameter_data( - &data.as_angle_bracketed_args(), - param_mode, - itctx, - ) - .0, - false, - ) + let aba = self.lowering_arena.aba.alloc(data.as_angle_bracketed_args()); + (self.lower_angle_bracketed_parameter_data(aba, param_mode, itctx).0, false) } }, } @@ -312,12 +311,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ); } - pub(crate) fn lower_angle_bracketed_parameter_data( + pub(crate) fn lower_angle_bracketed_parameter_data<'itctx>( &mut self, - data: &AngleBracketedArgs, + data: &'itctx AngleBracketedArgs, param_mode: ParamMode, - mut itctx: ImplTraitContext<'_>, - ) -> (GenericArgsCtor<'hir>, bool) { + mut itctx: ImplTraitContext<'_, 'itctx>, + ) -> (GenericArgsCtor<'hir>, bool) + where + 'a: 'itctx, + { let has_non_lt_args = data.args.iter().any(|arg| match arg { AngleBracketedArg::Arg(ast::GenericArg::Lifetime(_)) | AngleBracketedArg::Constraint(_) => false, diff --git a/src/test/ui/impl-trait/v2/async-await-bounds.rs b/src/test/ui/impl-trait/v2/async-await-bounds.rs new file mode 100644 index 0000000000000..9d55bee8e13d1 --- /dev/null +++ b/src/test/ui/impl-trait/v2/async-await-bounds.rs @@ -0,0 +1,16 @@ +// build-pass (FIXME(62277): could be check-pass?) +// edition:2018 + +#![feature(return_position_impl_trait_v2)] + +use std::future::Future; + +pub trait Foo { + fn foo(&self) {} +} + +pub fn call_with_ref_block<'a>(f: &'a (impl Foo + 'a)) -> impl Future + 'a { + async move { f.foo() } +} + +fn main() {} diff --git a/src/test/ui/impl-trait/v2/async-await-generics-and-bounds.rs b/src/test/ui/impl-trait/v2/async-await-generics-and-bounds.rs new file mode 100644 index 0000000000000..937e05dc6cddf --- /dev/null +++ b/src/test/ui/impl-trait/v2/async-await-generics-and-bounds.rs @@ -0,0 +1,9 @@ +// check-pass +// edition:2018 +// compile-flags: --crate-type lib + +#![feature(return_position_impl_trait_v2)] + +pub fn foo(f: impl Send) -> impl Send { + f +} From 50bc77624de2cf0d7a9fe55e981f902fd16cc465 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 10 Aug 2022 15:54:35 -0300 Subject: [PATCH 24/53] Copy generic params from outer impl/trait blocks to RPIT --- compiler/rustc_ast/src/ast.rs | 21 +++++++++ compiler/rustc_ast_lowering/src/expr.rs | 12 +++-- compiler/rustc_ast_lowering/src/item.rs | 51 ++++++++++++++++++---- compiler/rustc_ast_lowering/src/lib.rs | 58 ++++++++++++++++++++----- 4 files changed, 120 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 3af6dee9e43f7..4dfdb8d7552c3 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -434,6 +434,27 @@ impl Default for Generics { } } +impl Generics { + pub fn merge(&self, other: &Generics) -> Generics { + let mut params = Vec::with_capacity(self.params.len() + other.params.len()); + params.extend(self.params.iter().cloned()); + params.extend(other.params.iter().cloned()); + + let has_where_token = + self.where_clause.has_where_token || other.where_clause.has_where_token; + let mut predicates = Vec::with_capacity( + self.where_clause.predicates.len() + other.where_clause.predicates.len(), + ); + predicates.extend(self.where_clause.predicates.iter().cloned()); + predicates.extend(other.where_clause.predicates.iter().cloned()); + + let where_clause = + WhereClause { has_where_token, predicates, span: self.where_clause.span }; + + Generics { params, where_clause, span: self.span } + } +} + /// A where-clause in a definition. #[derive(Clone, Encodable, Decodable, Debug)] pub struct WhereClause { diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 2d43ea2fdcdd6..232cbcfae85e2 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -850,7 +850,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params); // Lower outside new scope to preserve `is_in_loop_condition`. let fn_decl = - self.lower_fn_decl(decl, None, FnDeclKind::Closure, &Generics::default(), None); + self.lower_fn_decl(decl, None, FnDeclKind::Closure, &Generics::default(), None, None); let c = self.arena.alloc(hir::Closure { binder: binder_clause, @@ -954,8 +954,14 @@ 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 = - self.lower_fn_decl(&outer_decl, None, FnDeclKind::Closure, &Generics::default(), None); + let fn_decl = self.lower_fn_decl( + &outer_decl, + None, + FnDeclKind::Closure, + &Generics::default(), + None, + None, + ); let c = self.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 68e9336b93a2e..7bc664640469e 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -136,6 +136,10 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { let def_id = self.resolver.node_id_to_def_id[&item.id]; let parent_id = self.tcx.local_parent(def_id); + + let parent_ast_owner = self.ast_index[parent_id]; + let parent_generics = parent_ast_owner.item_generics(); + let parent_hir = self.lower_node(parent_id).unwrap(); self.with_lctx(item.id, |lctx| { // Evaluate with the lifetimes in `params` in-scope. @@ -149,8 +153,12 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { }; match ctxt { - AssocCtxt::Trait => hir::OwnerNode::TraitItem(lctx.lower_trait_item(item)), - AssocCtxt::Impl => hir::OwnerNode::ImplItem(lctx.lower_impl_item(item)), + AssocCtxt::Trait => { + hir::OwnerNode::TraitItem(lctx.lower_trait_item(item, &parent_generics)) + } + AssocCtxt::Impl => { + hir::OwnerNode::ImplItem(lctx.lower_impl_item(item, &parent_generics)) + } } }) } @@ -265,7 +273,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let itctx = ImplTraitContext::Universal { apit_nodes: &mut Vec::new() }; let (generics, decl) = this.lower_generics(generics, id, itctx, |this| { let ret_id = asyncness.opt_return_id(); - this.lower_fn_decl(&decl, Some(id), FnDeclKind::Fn, generics, ret_id) + this.lower_fn_decl(&decl, Some(id), FnDeclKind::Fn, generics, None, ret_id) }); let sig = hir::FnSig { decl, @@ -661,6 +669,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { FnDeclKind::ExternFn, generics, None, + None, ), this.lower_fn_params_to_names(fdec), ) @@ -759,7 +768,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } - fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> { + fn lower_trait_item( + &mut self, + i: &AssocItem, + parent_generics: &ast::Generics, + ) -> &'hir hir::TraitItem<'hir> { let hir_id = self.lower_node_id(i.id); let trait_item_def_id = hir_id.expect_owner(); @@ -771,8 +784,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } AssocItemKind::Fn(box Fn { ref sig, ref generics, body: None, .. }) => { 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, + parent_generics, + sig, + i.id, + FnDeclKind::Trait, + None, + ); (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false) } AssocItemKind::Fn(box Fn { ref sig, ref generics, body: Some(ref body), .. }) => { @@ -781,6 +800,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.lower_maybe_async_body(i.span, &sig.decl, asyncness, Some(&body)); let (generics, sig) = self.lower_method_sig( generics, + parent_generics, sig, i.id, FnDeclKind::Trait, @@ -854,7 +874,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.expr(span, hir::ExprKind::Err, AttrVec::new()) } - fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> { + fn lower_impl_item( + &mut self, + i: &AssocItem, + parent_generics: &ast::Generics, + ) -> &'hir hir::ImplItem<'hir> { // Since `default impl` is not yet implemented, this is always true in impls. let has_value = true; let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value); @@ -874,6 +898,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.lower_maybe_async_body(i.span, &sig.decl, asyncness, body.as_deref()); let (generics, sig) = self.lower_method_sig( generics, + parent_generics, sig, i.id, if self.is_in_trait_impl { FnDeclKind::Impl } else { FnDeclKind::Inherent }, @@ -1231,6 +1256,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_method_sig( &mut self, generics: &Generics, + parent_generics: &Generics, sig: &FnSig, id: NodeId, kind: FnDeclKind, @@ -1238,8 +1264,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) { let header = self.lower_fn_header(sig.header); let itctx = ImplTraitContext::Universal { apit_nodes: &mut Vec::new() }; - let (generics, decl) = self.lower_generics(generics, id, itctx, |this| { - this.lower_fn_decl(&sig.decl, Some(id), kind, generics, is_async) + let (generics, decl) = self.lower_generics(&generics, id, itctx, |this| { + this.lower_fn_decl( + &sig.decl, + Some(id), + kind, + &generics, + Some(parent_generics), + 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 dc3206cd82232..4a8288d8b8eb0 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -148,6 +148,7 @@ struct LoweringArena { tys: TypedArena, aba: TypedArena, ptr: TypedArena, + gs: TypedArena, } trait ResolverAstLoweringExt { @@ -289,6 +290,7 @@ enum ImplTraitContext<'b, 'itctx> { impl_trait_inputs: &'b Vec<&'itctx Ty>, /// In scope generics generics: &'itctx Generics, + parent_generics: Option<&'itctx Generics>, }, /// Impl trait in type aliases. TypeAliasesOpaqueTy, @@ -325,11 +327,12 @@ impl<'itctx> ImplTraitContext<'_, 'itctx> { use self::ImplTraitContext::*; match self { Universal { apit_nodes } => Universal { apit_nodes: *apit_nodes }, - ReturnPositionOpaqueTy { origin, impl_trait_inputs, generics } => { + ReturnPositionOpaqueTy { origin, impl_trait_inputs, generics, parent_generics } => { ReturnPositionOpaqueTy { origin: *origin, impl_trait_inputs: *impl_trait_inputs, generics: *generics, + parent_generics: *parent_generics, } } TypeAliasesOpaqueTy => TypeAliasesOpaqueTy, @@ -395,6 +398,21 @@ enum AstOwner<'a> { ForeignItem(&'a ast::ForeignItem), } +impl<'a> AstOwner<'a> { + fn item_generics(&self) -> ast::Generics { + match self { + Self::Item(Item { + kind: + ItemKind::Trait(box Trait { generics, .. }) + | ItemKind::Impl(box Impl { generics, .. }), + .. + }) => generics.clone(), + + _ => Generics::default(), + } + } +} + fn index_crate<'a>( node_id_to_def_id: &FxHashMap, krate: &'a Crate, @@ -477,6 +495,7 @@ pub fn lower_to_hir<'hir>(tcx: TyCtxt<'hir>, (): ()) -> hir::Crate<'hir> { tys: TypedArena::default(), aba: TypedArena::default(), ptr: TypedArena::default(), + gs: TypedArena::default(), }; for def_id in ast_index.indices() { @@ -1445,6 +1464,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: DUMMY_SP, }, None, + None, ), param_names: self.lower_fn_params_to_names(&f.decl), })) @@ -1516,17 +1536,32 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { origin, impl_trait_inputs, generics, + parent_generics, } => { if self.tcx.sess.features_untracked().return_position_impl_trait_v2 { - self.lower_opaque_impl_trait_v2( - span, - origin, - def_node_id, - generics, - impl_trait_inputs, - bounds, - itctx, - ) + if let Some(parent_generics) = parent_generics { + let generics = + self.lowering_arena.gs.alloc(generics.merge(parent_generics)); + self.lower_opaque_impl_trait_v2( + span, + origin, + def_node_id, + generics, + impl_trait_inputs, + bounds, + itctx, + ) + } else { + self.lower_opaque_impl_trait_v2( + span, + origin, + def_node_id, + generics, + impl_trait_inputs, + bounds, + itctx, + ) + } } else { self.lower_opaque_impl_trait(span, origin, def_node_id, bounds, itctx) } @@ -2154,6 +2189,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn_node_id: Option, kind: FnDeclKind, generics: &Generics, + parent_generics: Option<&Generics>, make_ret_async: Option, ) -> &'hir hir::FnDecl<'hir> { let c_variadic = decl.c_variadic(); @@ -2205,6 +2241,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), impl_trait_inputs: &impl_trait_inputs, generics, + parent_generics: parent_generics, } } _ => ImplTraitContext::Disallowed(match kind { @@ -2502,6 +2539,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), impl_trait_inputs: &mut Vec::new(), generics: &Generics::default(), + parent_generics: None, }; self.lower_ty(ty, context) } From 8f20d42fcdbf9a455317adb468167f40b492ae6d Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 10 Aug 2022 16:00:58 -0300 Subject: [PATCH 25/53] Add debug call on rustc_middle generics --- compiler/rustc_middle/src/ty/generics.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index a1d980af921af..b398076d223aa 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -337,6 +337,9 @@ impl<'tcx> GenericPredicates<'tcx> { if let Some(def_id) = self.parent { tcx.predicates_of(def_id).instantiate_into(tcx, instantiated, substs); } + + debug!("instantiate_into: predicates={:#?} substs={:#?}", instantiated.predicates, substs); + instantiated .predicates .extend(self.predicates.iter().map(|(p, _)| EarlyBinder(*p).subst(tcx, substs))); From 98d43e56260c572980d24867afc78eab4f6169df Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 10 Aug 2022 16:01:49 -0300 Subject: [PATCH 26/53] Supress warn on artificial static lifetimes for RPIT --- compiler/rustc_resolve/src/late/lifetimes.rs | 39 +++++++++++++------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index c16eab222f625..32f667c5744ef 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -1046,20 +1046,31 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { continue; } this.insert_lifetime(lt, Region::Static); - this.tcx - .sess - .struct_span_warn( - lifetime.span, - &format!( - "unnecessary lifetime parameter `{}`", - lifetime.name.ident(), - ), - ) - .help(&format!( - "you can use the `'static` lifetime directly, in place of `{}`", - lifetime.name.ident(), - )) - .emit(); + + let hir_map = this.tcx.hir(); + let parent = hir_map.get_parent_node(lt.hir_id); + + match hir_map.get(parent) { + hir::Node::Item(&hir::Item { kind: hir::ItemKind::OpaqueTy(..), .. }) if this.tcx.sess.features_untracked().return_position_impl_trait_v2 => { + // do not warn + } + _ => { + this.tcx + .sess + .struct_span_warn( + lifetime.span, + &format!( + "unnecessary lifetime parameter `{}`", + lifetime.name.ident(), + ), + ) + .help(&format!( + "you can use the `'static` lifetime directly, in place of `{}`", + lifetime.name.ident(), + )) + .emit(); + } + } } } } From cfa73f8b0a1cd69d1f06c5ba24c4119266786915 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 30 Jun 2022 16:26:38 -0300 Subject: [PATCH 27/53] instrument type param predicates and bounds in generic fns --- compiler/rustc_typeck/src/collect.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 39416d0ddf165..a3edd778dacb5 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -573,6 +573,7 @@ fn get_new_lifetime_name<'tcx>( /// Returns the predicates defined on `item_def_id` of the form /// `X: Foo` where `X` is the type parameter `def_id`. +#[instrument(level = "trace", skip(tcx))] fn type_param_predicates( tcx: TyCtxt<'_>, (item_def_id, def_id, assoc_name): (DefId, LocalDefId, Ident), @@ -682,7 +683,7 @@ impl<'tcx> ItemCtxt<'tcx> { /// AST. We do this to avoid having to convert *all* the bounds, which /// would create artificial cycles. Instead, we can only convert the /// bounds for a type parameter `X` if `X::Foo` is used. - #[instrument(level = "trace", skip(self, ast_generics))] + #[instrument(level = "trace", skip(self))] fn type_parameter_bounds_in_generics( &self, ast_generics: &'tcx hir::Generics<'tcx>, From 9118087215b0cc129914a3fe1ef1f2ac2cb69156 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 28 Jun 2022 13:07:16 -0300 Subject: [PATCH 28/53] Add APIT with lifetimes test --- src/test/ui/impl-trait/v2/sized_bounds.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/test/ui/impl-trait/v2/sized_bounds.rs diff --git a/src/test/ui/impl-trait/v2/sized_bounds.rs b/src/test/ui/impl-trait/v2/sized_bounds.rs new file mode 100644 index 0000000000000..12eeb6d614bda --- /dev/null +++ b/src/test/ui/impl-trait/v2/sized_bounds.rs @@ -0,0 +1,12 @@ +//run-pass +#![deny(rust_2021_incompatible_closure_captures)] +#![allow(unused_must_use)] +#![feature(return_position_impl_trait_v2)] + +fn filter_try_fold(predicate: &mut impl FnMut() -> bool) -> impl FnMut() -> bool + '_ { + move || predicate() +} + +fn main() { + filter_try_fold(&mut || true); +} From 3049a8dcc114b73125c22dc49db29bf359f77742 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 2 Sep 2022 16:47:16 -0300 Subject: [PATCH 29/53] Add a simple APIT test --- src/test/ui/impl-trait/v2/apit2.rs | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/test/ui/impl-trait/v2/apit2.rs diff --git a/src/test/ui/impl-trait/v2/apit2.rs b/src/test/ui/impl-trait/v2/apit2.rs new file mode 100644 index 0000000000000..e3e1e62f39449 --- /dev/null +++ b/src/test/ui/impl-trait/v2/apit2.rs @@ -0,0 +1,9 @@ +// check-pass + +#![feature(return_position_impl_trait_v2)] + +fn i(a: impl Iterator) -> impl Iterator { + a +} + +fn main() {} From 8b5c082d908d55bbea1f2e48b28174a92cd5d8e2 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 2 Sep 2022 16:48:44 -0300 Subject: [PATCH 30/53] Add lifetimes bounds test --- src/test/ui/impl-trait/v2/lifetimes.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/test/ui/impl-trait/v2/lifetimes.rs diff --git a/src/test/ui/impl-trait/v2/lifetimes.rs b/src/test/ui/impl-trait/v2/lifetimes.rs new file mode 100644 index 0000000000000..b8327d270a9a3 --- /dev/null +++ b/src/test/ui/impl-trait/v2/lifetimes.rs @@ -0,0 +1,17 @@ +// check-pass + +#![allow(warnings)] +#![feature(return_position_impl_trait_v2)] + +use std::fmt::Debug; + +trait MultiRegionTrait<'a, 'b>: Debug {} + +#[derive(Debug)] +struct MultiRegionStruct<'a, 'b>(&'a u32, &'b u32); +impl<'a, 'b> MultiRegionTrait<'a, 'b> for MultiRegionStruct<'a, 'b> {} + +fn finds_explicit_bound<'a: 'b, 'b>(x: &'a u32, y: &'b u32) -> impl MultiRegionTrait<'a, 'b> + 'b { + MultiRegionStruct(x, y) +} +fn main() {} From 1563a66a39eb2df385c000b1c7051cf1ddd71f52 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 5 Jul 2022 12:15:31 -0300 Subject: [PATCH 31/53] Do not assert impl_trait_* is_empty --- compiler/rustc_ast_lowering/src/lib.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 4a8288d8b8eb0..df551e417dd1f 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -626,9 +626,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let item = f(self); debug_assert_eq!(def_id, item.def_id()); - // `f` should have consumed all the elements in these vectors when constructing `item`. - debug_assert!(self.impl_trait_defs.is_empty()); - debug_assert!(self.impl_trait_bounds.is_empty()); let info = self.make_owner_info(item); self.attrs = current_attrs; From 54d5fa42a759ad236dd078926858a02b36f8b6c9 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 5 Jul 2022 11:29:08 -0300 Subject: [PATCH 32/53] Add debug information --- compiler/rustc_ast_lowering/src/lib.rs | 3 +++ compiler/rustc_typeck/src/collect.rs | 8 ++++++-- compiler/rustc_typeck/src/collect/item_bounds.rs | 8 +++++++- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index df551e417dd1f..d22c5fdc481f6 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2741,6 +2741,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::MutTy { ty: self.lower_ty(&mt.ty, itctx), mutbl: mt.mutbl } } + #[tracing::instrument(level = "debug", skip(self))] fn lower_param_bounds<'itctx>( &mut self, bounds: &'itctx [GenericBound], @@ -2763,6 +2764,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { bounds.iter().map(move |bound| self.lower_param_bound(bound, itctx.reborrow())) } + #[tracing::instrument(level = "debug", skip(self))] fn lower_generic_and_bounds( &mut self, node_id: NodeId, @@ -2801,6 +2803,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }), )); + debug!("lower_generic_and_bounds=(param={:?}, preds={:?}, ty={:?})", param, preds, ty); (param, preds, ty) } diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index a3edd778dacb5..993fd8e07838c 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -2124,11 +2124,10 @@ fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> { /// Returns a list of user-specified type predicates for the definition with ID `def_id`. /// N.B., this does not include any implied/inferred constraints. +#[instrument(level = "trace", skip(tcx))] fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> { use rustc_hir::*; - debug!("explicit_predicates_of(def_id={:?})", def_id); - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); let node = tcx.hir().get(hir_id); @@ -2267,6 +2266,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP + has_own_self as u32 + early_bound_lifetimes_from_generics(tcx, ast_generics).count() as u32; + debug!("gather_explicit_predicates_of(predicates={:?})", predicates); + debug!("gather_explicit_predicates_of(ast_generics={:?})", ast_generics); // Collect the predicates that were written inline by the user on each // type parameter (e.g., ``). for param in ast_generics.params { @@ -2287,7 +2288,9 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP Some((param.hir_id, ast_generics.predicates)), param.span, ); + debug!("gather_explicit_predicates_of(bounds={:?})", bounds); predicates.extend(bounds.predicates(tcx, param_ty)); + debug!("gather_explicit_predicates_of(predicates={:?})", predicates); } GenericParamKind::Const { .. } => { // Bounds on const parameters are currently not possible. @@ -2296,6 +2299,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP } } + debug!("gather_explicit_predicates_of(predicates={:?})", predicates); // Add in the bounds that appear in the where-clause. for predicate in ast_generics.predicates { match predicate { diff --git a/compiler/rustc_typeck/src/collect/item_bounds.rs b/compiler/rustc_typeck/src/collect/item_bounds.rs index 0d2b75d3328fc..2d9b5aaf09878 100644 --- a/compiler/rustc_typeck/src/collect/item_bounds.rs +++ b/compiler/rustc_typeck/src/collect/item_bounds.rs @@ -53,6 +53,7 @@ fn associated_type_bounds<'tcx>( /// 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. +#[instrument(level = "trace", skip(tcx))] fn opaque_type_bounds<'tcx>( tcx: TyCtxt<'tcx>, opaque_def_id: DefId, @@ -65,9 +66,14 @@ fn opaque_type_bounds<'tcx>( let icx = ItemCtxt::new(tcx, opaque_def_id); let mut bounds = >::compute_bounds(&icx, item_ty, ast_bounds); + + debug!("opaque_type_bounds(bounds={:?})", bounds); // Opaque types 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)) + debug!("opaque_type_bounds(bounds={:?})", bounds); + let result = tcx.arena.alloc_from_iter(bounds.predicates(tcx, item_ty)); + debug!("opaque_type_bounds(predicates={:?})", result); + result }) } From faafdf1edf3ce28e83e1fe9a37010f0561e916fc Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 10 Aug 2022 19:33:51 -0300 Subject: [PATCH 33/53] Add APIT anonymous lifetime test --- src/test/ui/impl-trait/v2/filter_fold.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/test/ui/impl-trait/v2/filter_fold.rs diff --git a/src/test/ui/impl-trait/v2/filter_fold.rs b/src/test/ui/impl-trait/v2/filter_fold.rs new file mode 100644 index 0000000000000..9a59debcafcec --- /dev/null +++ b/src/test/ui/impl-trait/v2/filter_fold.rs @@ -0,0 +1,13 @@ +// check-pass + +#![feature(return_position_impl_trait_v2)] + +pub trait Try { + type Output; +} + +fn filter_try_fold<'a>(predicate: &'a mut impl FnMut(&u32) -> bool) -> impl Sized { + 22 +} + +fn main() {} From fff4d3183f4173f6f1886ec0e660a4cfa36fbc59 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 16 Aug 2022 17:09:26 -0300 Subject: [PATCH 34/53] Add trait bound anonymous lifetime test --- src/test/ui/impl-trait/v2/filter_fold2.rs | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/test/ui/impl-trait/v2/filter_fold2.rs diff --git a/src/test/ui/impl-trait/v2/filter_fold2.rs b/src/test/ui/impl-trait/v2/filter_fold2.rs new file mode 100644 index 0000000000000..a742b0cee6eef --- /dev/null +++ b/src/test/ui/impl-trait/v2/filter_fold2.rs @@ -0,0 +1,7 @@ +// check-pass + +#![feature(return_position_impl_trait_v2)] + +fn foo() -> impl Sized {} + +fn main() {} From f08f19e1684295abaa8a892e56a86a8cedc280b3 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 18 Aug 2022 14:26:59 -0300 Subject: [PATCH 35/53] Create definitions and remap lifetimes in lower_lifetime_binder --- compiler/rustc_ast_lowering/src/expr.rs | 83 +++++++------- compiler/rustc_ast_lowering/src/lib.rs | 109 +++++++++++++------ compiler/rustc_resolve/src/late/lifetimes.rs | 3 + 3 files changed, 121 insertions(+), 74 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 232cbcfae85e2..c4c0ab904f10c 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -847,22 +847,29 @@ impl<'hir> LoweringContext<'_, 'hir> { (body_id, generator_option) }); - let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params); - // Lower outside new scope to preserve `is_in_loop_condition`. - let fn_decl = - self.lower_fn_decl(decl, None, FnDeclKind::Closure, &Generics::default(), None, None); - - let c = self.arena.alloc(hir::Closure { - binder: binder_clause, - capture_clause, - bound_generic_params, - fn_decl, - body: body_id, - fn_decl_span: self.lower_span(fn_decl_span), - movability: generator_option, - }); + 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, + &Generics::default(), + None, + None, + ); + + let c = lctx.arena.alloc(hir::Closure { + binder: binder_clause, + capture_clause, + bound_generic_params, + fn_decl, + body: body_id, + fn_decl_span: lctx.lower_span(fn_decl_span), + movability: generator_option, + }); - hir::ExprKind::Closure(c) + hir::ExprKind::Closure(c) + }) } fn generator_movability_for_fn( @@ -949,30 +956,30 @@ impl<'hir> LoweringContext<'_, 'hir> { body_id }); - let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params); - - // 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 = self.lower_fn_decl( - &outer_decl, - None, - FnDeclKind::Closure, - &Generics::default(), - None, - None, - ); + self.lower_lifetime_binder(closure_id, generic_params, |lctx, bound_generic_params| { + // 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, + &Generics::default(), + None, + None, + ); - let c = self.arena.alloc(hir::Closure { - binder: binder_clause, - capture_clause, - bound_generic_params, - fn_decl, - body, - fn_decl_span: self.lower_span(fn_decl_span), - movability: None, - }); - hir::ExprKind::Closure(c) + let c = lctx.arena.alloc(hir::Closure { + binder: binder_clause, + capture_clause, + bound_generic_params, + fn_decl, + body, + fn_decl_span: lctx.lower_span(fn_decl_span), + movability: None, + }); + hir::ExprKind::Closure(c) + }) } /// Destructure the LHS of complex assignments. diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index d22c5fdc481f6..a50459edb7730 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -226,7 +226,7 @@ impl ResolverAstLoweringExt for ResolverAstLowering { /// The extra lifetimes that appear from the parenthesized `Fn`-trait desugaring /// should appear at the enclosing `PolyTraitRef`. fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)> { - self.extra_lifetime_params_map.remove(&id).unwrap_or_default() + self.extra_lifetime_params_map.get(&id).map_or_else(|| Vec::new(), |map| map.clone()) } fn decl_macro_kind(&self, def_id: LocalDefId) -> MacroKind { @@ -987,23 +987,55 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// name resolver owing to lifetime elision; this also populates the resolver's node-id->def-id /// map, so that later calls to `opt_node_id_to_def_id` that refer to these extra lifetime /// parameters will be successful. - #[instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self, in_binder))] #[inline] - fn lower_lifetime_binder( + fn lower_lifetime_binder( &mut self, binder: NodeId, generic_params: &[GenericParam], - ) -> &'hir [hir::GenericParam<'hir>] { - let mut generic_params: Vec<_> = self.lower_generic_params_mut(generic_params).collect(); + in_binder: impl FnOnce(&mut Self, &'hir [hir::GenericParam<'hir>]) -> R, + ) -> R { + let mut new_remapping = FxHashMap::default(); + let extra_lifetimes = self.resolver.take_extra_lifetime_params(binder); debug!(?extra_lifetimes); - generic_params.extend(extra_lifetimes.into_iter().filter_map(|(ident, node_id, res)| { - self.lifetime_res_to_generic_param(ident, node_id, res) - })); - let generic_params = self.arena.alloc_from_iter(generic_params); - debug!(?generic_params); - generic_params + let mut hir_extra_lifetimes = Vec::new(); + + for (ident, node_id, res) in &extra_lifetimes { + if let Some(lifetime) = self.lifetime_res_to_generic_param(*ident, *node_id, *res) { + hir_extra_lifetimes.push(lifetime) + } + } + + if !self.resolver.generics_def_id_map.is_empty() { + for old_node_id in generic_params + .iter() + .filter(|param| matches!(param.kind, GenericParamKind::Lifetime)) + .map(|param| param.id) + { + let old_def_id = self.local_def_id(old_node_id); + let node_id = self.next_node_id(); + + // Add a definition for the generic param def. + let new_def_id = + self.create_def(self.current_hir_id_owner, node_id, DefPathData::ImplTrait); + + new_remapping.insert(old_def_id, new_def_id); + debug!("old_def_id={:?} new_def_id={:?}", old_def_id, new_def_id); + } + } + + // Install the remapping from old to new (if any): + self.with_remapping(new_remapping, &[], |lctx| { + let mut generic_params: Vec<_> = + lctx.lower_generic_params_mut(generic_params).collect(); + generic_params.extend(hir_extra_lifetimes); + let generic_params = lctx.arena.alloc_from_iter(generic_params); + debug!(?generic_params); + + in_binder(lctx, generic_params) + }) } fn with_dyn_type_scope(&mut self, in_scope: bool, f: impl FnOnce(&mut Self) -> T) -> T { @@ -1442,29 +1474,30 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::TyKind::Rptr(lifetime, self.lower_mt(mt, itctx)) } TyKind::BareFn(ref f) => { - let generic_params = self.lower_lifetime_binder(t.id, &f.generic_params); - hir::TyKind::BareFn(self.arena.alloc(hir::BareFnTy { - generic_params, - unsafety: self.lower_unsafety(f.unsafety), - abi: self.lower_extern(f.ext), - decl: self.lower_fn_decl( - &f.decl, - None, - FnDeclKind::Pointer, - &Generics { - params: f.generic_params.clone(), - where_clause: WhereClause { - has_where_token: false, - predicates: Vec::new(), + self.lower_lifetime_binder(t.id, &f.generic_params, |lctx, generic_params| { + hir::TyKind::BareFn(lctx.arena.alloc(hir::BareFnTy { + generic_params, + unsafety: lctx.lower_unsafety(f.unsafety), + abi: lctx.lower_extern(f.ext), + decl: lctx.lower_fn_decl( + &f.decl, + None, + FnDeclKind::Pointer, + &Generics { + params: f.generic_params.clone(), + where_clause: WhereClause { + has_where_token: false, + predicates: Vec::new(), + span: DUMMY_SP, + }, span: DUMMY_SP, }, - span: DUMMY_SP, - }, - None, - None, - ), - param_names: self.lower_fn_params_to_names(&f.decl), - })) + None, + None, + ), + param_names: lctx.lower_fn_params_to_names(&f.decl), + })) + }) } TyKind::Never => hir::TyKind::Never, TyKind::Tup(ref tys) => { @@ -2724,10 +2757,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { where 'a: 'itctx, { - let bound_generic_params = - self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params); - let trait_ref = self.lower_trait_ref(&p.trait_ref, itctx); - hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) } + self.lower_lifetime_binder( + p.trait_ref.ref_id, + &p.bound_generic_params, + |lctx, bound_generic_params| { + let trait_ref = lctx.lower_trait_ref(&p.trait_ref, itctx); + hir::PolyTraitRef { bound_generic_params, trait_ref, span: lctx.lower_span(p.span) } + }, + ) } fn lower_mt<'itctx>( diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 32f667c5744ef..5dfe41ed28f7a 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -525,6 +525,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } } + #[tracing::instrument(level = "debug", skip(self))] fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { match &item.kind { hir::ItemKind::Impl(hir::Impl { of_trait, .. }) => { @@ -839,6 +840,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } } + #[tracing::instrument(level = "debug", skip(self))] fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) { use self::hir::TraitItemKind::*; match trait_item.kind { @@ -888,6 +890,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } } + #[tracing::instrument(level = "debug", skip(self))] fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) { use self::hir::ImplItemKind::*; match impl_item.kind { From 697393fb9dc866f3f36706df320ae0065d9575f6 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 2 Sep 2022 17:38:23 -0300 Subject: [PATCH 36/53] save/restore the node-id table for poly-trait-ref The "right thing" is probably to save/restore the binders. --- compiler/rustc_ast_lowering/src/lib.rs | 18 +++++----- ...async-fn-elided-impl-lifetime-parameter.rs | 33 +++++++++++++++++++ 2 files changed, 43 insertions(+), 8 deletions(-) create mode 100644 src/test/ui/impl-trait/v2/async-fn-elided-impl-lifetime-parameter.rs diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index a50459edb7730..3528ba9c1cf51 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -546,7 +546,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) -> LocalDefId { debug_assert_ne!(node_id, ast::DUMMY_NODE_ID); assert!( - self.opt_local_def_id(node_id).is_none(), + self.resolver.node_id_to_def_id.get(&node_id).is_none(), "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}", node_id, data, @@ -1002,6 +1002,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let mut hir_extra_lifetimes = Vec::new(); + let current_node_id_to_def_id = self.resolver.node_id_to_def_id.clone(); + for (ident, node_id, res) in &extra_lifetimes { if let Some(lifetime) = self.lifetime_res_to_generic_param(*ident, *node_id, *res) { hir_extra_lifetimes.push(lifetime) @@ -1009,11 +1011,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } if !self.resolver.generics_def_id_map.is_empty() { - for old_node_id in generic_params - .iter() - .filter(|param| matches!(param.kind, GenericParamKind::Lifetime)) - .map(|param| param.id) - { + for old_node_id in generic_params.iter().map(|param| param.id) { let old_def_id = self.local_def_id(old_node_id); let node_id = self.next_node_id(); @@ -1027,7 +1025,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } // Install the remapping from old to new (if any): - self.with_remapping(new_remapping, &[], |lctx| { + let result = self.with_remapping(new_remapping, &[], |lctx| { let mut generic_params: Vec<_> = lctx.lower_generic_params_mut(generic_params).collect(); generic_params.extend(hir_extra_lifetimes); @@ -1035,7 +1033,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { debug!(?generic_params); in_binder(lctx, generic_params) - }) + }); + + self.resolver.node_id_to_def_id = current_node_id_to_def_id; + + result } fn with_dyn_type_scope(&mut self, in_scope: bool, f: impl FnOnce(&mut Self) -> T) -> T { diff --git a/src/test/ui/impl-trait/v2/async-fn-elided-impl-lifetime-parameter.rs b/src/test/ui/impl-trait/v2/async-fn-elided-impl-lifetime-parameter.rs new file mode 100644 index 0000000000000..67dd6d41f657a --- /dev/null +++ b/src/test/ui/impl-trait/v2/async-fn-elided-impl-lifetime-parameter.rs @@ -0,0 +1,33 @@ +// Check that `async fn` inside of an impl with `'_` +// in the header compiles correctly. +// +// Regression test for #63500. +// +// check-pass +// edition:2018 + +#![feature(return_position_impl_trait_v2)] + +struct Foo<'a>(&'a u8); + +impl Foo<'_> { // impl Foo<'(fresh:NodeId0)> +// ^ extra_lifetime_parameters: [fresh:NodeId0] +// +// we insert these into `node_id_to_def_id_override` + + async fn bar() {} + // but HERE, when you have an async function, you create a node-id for it (opaque_ty_id) + // + // and we attach (using `extra_lifetime_parameters`) a list of *all the lifetimes that are in scope from the impl and the fn* + // + // +} + +// for<> fn(&'(fresh:NodeId0) u32) +// ^ +// extra_lifetime_parameters: [fresh:NodeId0] instantiate def-ids for them and add them into the node_id_to_def_id_override +// with the node id NodeId0 +// +// then later when we process `fresh:NodeId0` we look up in `node_id_to_def_id_override` and we find it + +fn main() {} From 9f8a3432aae8559bc29f713fe42bc5107583b2ce Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 23 Aug 2022 16:30:59 -0300 Subject: [PATCH 37/53] impl/block types are first and then fn types --- compiler/rustc_ast_lowering/src/lib.rs | 2 +- src/test/ui/impl-trait/v2/try_trait.rs | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/impl-trait/v2/try_trait.rs diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 3528ba9c1cf51..fbc083e38f417 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1573,7 +1573,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { if self.tcx.sess.features_untracked().return_position_impl_trait_v2 { if let Some(parent_generics) = parent_generics { let generics = - self.lowering_arena.gs.alloc(generics.merge(parent_generics)); + self.lowering_arena.gs.alloc(parent_generics.merge(generics)); self.lower_opaque_impl_trait_v2( span, origin, diff --git a/src/test/ui/impl-trait/v2/try_trait.rs b/src/test/ui/impl-trait/v2/try_trait.rs new file mode 100644 index 0000000000000..c451cb802c66c --- /dev/null +++ b/src/test/ui/impl-trait/v2/try_trait.rs @@ -0,0 +1,15 @@ +// check-pass + +#![feature(return_position_impl_trait_v2)] + +pub(crate) struct NeverShortCircuit(pub T); + +impl NeverShortCircuit { + /// Wrap a binary `FnMut` to return its result wrapped in a `NeverShortCircuit`. + #[inline] + pub fn wrap_mut_2(mut f: impl FnMut(A, B) -> T) -> impl FnMut(A, B) -> Self { + move |a, b| NeverShortCircuit(f(a, b)) + } +} + +fn main() {} From f51460734b6ec298f9c656b31af086a23ead1b14 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 23 Aug 2022 16:54:10 -0300 Subject: [PATCH 38/53] Remove return_position_impl_trait_v2 feature flag and make it default --- compiler/rustc_ast_lowering/src/lib.rs | 208 +++--------------- compiler/rustc_feature/src/active.rs | 2 - .../rustc_infer/src/infer/opaque_types.rs | 9 +- compiler/rustc_middle/src/ty/mod.rs | 11 +- compiler/rustc_resolve/src/late/lifetimes.rs | 2 +- compiler/rustc_span/src/symbol.rs | 1 - compiler/rustc_typeck/src/astconv/mod.rs | 4 +- compiler/rustc_typeck/src/check/check.rs | 8 +- compiler/rustc_typeck/src/collect.rs | 53 +---- compiler/rustc_typeck/src/collect/type_of.rs | 4 +- src/test/ui/impl-trait/v2/apit.rs | 9 - src/test/ui/impl-trait/v2/apit2.rs | 9 - .../ui/impl-trait/v2/async-await-bounds.rs | 16 -- .../v2/async-await-generics-and-bounds.rs | 9 - ...async-fn-elided-impl-lifetime-parameter.rs | 33 --- .../ui/impl-trait/v2/bounds_regression.rs | 26 --- src/test/ui/impl-trait/v2/const-generics.rs | 12 - src/test/ui/impl-trait/v2/filter_fold.rs | 13 -- src/test/ui/impl-trait/v2/filter_fold2.rs | 7 - .../ui/impl-trait/v2/generics-assoc-type.rs | 16 -- src/test/ui/impl-trait/v2/generics-unbound.rs | 21 -- src/test/ui/impl-trait/v2/lifetimes.rs | 17 -- .../ui/impl-trait/v2/nested-return-type.rs | 10 - .../ui/impl-trait/v2/simple-definition.rs | 13 -- src/test/ui/impl-trait/v2/sized_bounds.rs | 12 - src/test/ui/impl-trait/v2/try_trait.rs | 15 -- src/test/ui/impl-trait/v2/where_bounds.rs | 14 -- src/test/ui/impl-trait/v2/where_bounds2.rs | 11 - 28 files changed, 37 insertions(+), 528 deletions(-) delete mode 100644 src/test/ui/impl-trait/v2/apit.rs delete mode 100644 src/test/ui/impl-trait/v2/apit2.rs delete mode 100644 src/test/ui/impl-trait/v2/async-await-bounds.rs delete mode 100644 src/test/ui/impl-trait/v2/async-await-generics-and-bounds.rs delete mode 100644 src/test/ui/impl-trait/v2/async-fn-elided-impl-lifetime-parameter.rs delete mode 100644 src/test/ui/impl-trait/v2/bounds_regression.rs delete mode 100644 src/test/ui/impl-trait/v2/const-generics.rs delete mode 100644 src/test/ui/impl-trait/v2/filter_fold.rs delete mode 100644 src/test/ui/impl-trait/v2/filter_fold2.rs delete mode 100644 src/test/ui/impl-trait/v2/generics-assoc-type.rs delete mode 100644 src/test/ui/impl-trait/v2/generics-unbound.rs delete mode 100644 src/test/ui/impl-trait/v2/lifetimes.rs delete mode 100644 src/test/ui/impl-trait/v2/nested-return-type.rs delete mode 100644 src/test/ui/impl-trait/v2/simple-definition.rs delete mode 100644 src/test/ui/impl-trait/v2/sized_bounds.rs delete mode 100644 src/test/ui/impl-trait/v2/try_trait.rs delete mode 100644 src/test/ui/impl-trait/v2/where_bounds.rs delete mode 100644 src/test/ui/impl-trait/v2/where_bounds2.rs diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index fbc083e38f417..56de7bff6fd37 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1570,32 +1570,28 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { generics, parent_generics, } => { - if self.tcx.sess.features_untracked().return_position_impl_trait_v2 { - if let Some(parent_generics) = parent_generics { - let generics = - self.lowering_arena.gs.alloc(parent_generics.merge(generics)); - self.lower_opaque_impl_trait_v2( - span, - origin, - def_node_id, - generics, - impl_trait_inputs, - bounds, - itctx, - ) - } else { - self.lower_opaque_impl_trait_v2( - span, - origin, - def_node_id, - generics, - impl_trait_inputs, - bounds, - itctx, - ) - } + if let Some(parent_generics) = parent_generics { + let generics = + self.lowering_arena.gs.alloc(parent_generics.merge(generics)); + self.lower_opaque_impl_trait( + span, + origin, + def_node_id, + generics, + impl_trait_inputs, + bounds, + itctx, + ) } else { - self.lower_opaque_impl_trait(span, origin, def_node_id, bounds, itctx) + self.lower_opaque_impl_trait( + span, + origin, + def_node_id, + generics, + impl_trait_inputs, + bounds, + itctx, + ) } } ImplTraitContext::TypeAliasesOpaqueTy => { @@ -1604,6 +1600,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span, hir::OpaqueTyOrigin::TyAlias, def_node_id, + &Generics::default(), + &Vec::new(), bounds, nested_itctx, ) @@ -1673,162 +1671,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// for the lifetimes that get captured (`'x`, in our example above) and reference those. #[instrument(level = "debug", skip(self))] fn lower_opaque_impl_trait<'itctx>( - &mut self, - span: Span, - origin: hir::OpaqueTyOrigin, - opaque_ty_node_id: NodeId, - bounds: &'itctx GenericBounds, - itctx: ImplTraitContext<'_, 'itctx>, - ) -> hir::TyKind<'hir> - where - 'a: 'itctx, - { - // Make sure we know that some funky desugaring has been going on here. - // This is a first: there is code in other places like for loop - // desugaring that explicitly states that we don't want to track that. - // Not tracking it makes lints in rustc and clippy very fragile, as - // frequently opened issues show. - let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None); - - let opaque_ty_def_id = self.local_def_id(opaque_ty_node_id); - debug!(?opaque_ty_def_id); - - // Contains the new lifetime definitions created for the TAIT (if any). - let mut collected_lifetimes = Vec::new(); - - // If this came from a TAIT (as opposed to a function that returns an RPIT), we only want - // to capture the lifetimes that appear in the bounds. So visit the bounds to find out - // exactly which ones those are. - let lifetimes_to_remap = if origin == hir::OpaqueTyOrigin::TyAlias { - // in a TAIT like `type Foo<'a> = impl Foo<'a>`, we don't keep all the lifetime parameters - Vec::new() - } else { - // in fn return position, like the `fn test<'a>() -> impl Debug + 'a` example, - // we only keep the lifetimes that appear in the `impl Debug` itself: - lifetime_collector::lifetimes_in_bounds(&self.resolver, bounds) - }; - debug!(?lifetimes_to_remap); - - self.with_hir_id_owner(opaque_ty_node_id, |lctx| { - let mut new_remapping = FxHashMap::default(); - - // If this opaque type is only capturing a subset of the lifetimes (those that appear - // in bounds), then create the new lifetime parameters required and create a mapping - // from the old `'a` (on the function) to the new `'a` (on the opaque type). - collected_lifetimes = lctx.create_lifetime_defs( - opaque_ty_def_id, - &lifetimes_to_remap, - &mut new_remapping, - ); - debug!(?collected_lifetimes); - debug!(?new_remapping); - - // Install the remapping from old to new (if any): - lctx.with_remapping(new_remapping, &[], |lctx| { - // This creates HIR lifetime definitions as `hir::GenericParam`, in the given - // example `type TestReturn<'a, T, 'x> = impl Debug + 'x`, it creates a collection - // containing `&['x]`. - let lifetime_defs = lctx.arena.alloc_from_iter(collected_lifetimes.iter().map( - |&(new_node_id, lifetime)| { - let hir_id = lctx.lower_node_id(new_node_id); - debug_assert_ne!(lctx.opt_local_def_id(new_node_id), None); - - let (name, kind) = if lifetime.ident.name == kw::UnderscoreLifetime { - (hir::ParamName::Fresh, hir::LifetimeParamKind::Elided) - } else { - ( - hir::ParamName::Plain(lifetime.ident), - hir::LifetimeParamKind::Explicit, - ) - }; - - hir::GenericParam { - hir_id, - name, - span: lifetime.ident.span, - pure_wrt_drop: false, - kind: hir::GenericParamKind::Lifetime { kind }, - colon_span: None, - } - }, - )); - debug!(?lifetime_defs); - - // Then when we lower the param bounds, references to 'a are remapped to 'a1, so we - // get back Debug + 'a1, which is suitable for use on the TAIT. - let hir_bounds = lctx.lower_param_bounds(bounds, itctx); - debug!(?hir_bounds); - - let opaque_ty_item = hir::OpaqueTy { - generics: self.arena.alloc(hir::Generics { - params: lifetime_defs, - predicates: &[], - has_where_clause_predicates: false, - where_clause_span: lctx.lower_span(span), - span: lctx.lower_span(span), - }), - bounds: hir_bounds, - origin, - }; - debug!(?opaque_ty_item); - - lctx.generate_opaque_type(opaque_ty_def_id, opaque_ty_item, span, opaque_ty_span) - }) - }); - - // This creates HIR lifetime arguments as `hir::GenericArg`, in the given example `type - // TestReturn<'a, T, 'x> = impl Debug + 'x`, it creates a collection containing `&['x]`. - let lifetimes = - self.arena.alloc_from_iter(collected_lifetimes.into_iter().map(|(_, lifetime)| { - let id = self.next_node_id(); - let span = lifetime.ident.span; - - let ident = if lifetime.ident.name == kw::UnderscoreLifetime { - Ident::with_dummy_span(kw::UnderscoreLifetime) - } else { - lifetime.ident - }; - - let l = self.new_named_lifetime(lifetime.id, id, span, ident); - hir::GenericArg::Lifetime(l) - })); - debug!(?lifetimes); - - // `impl Trait` now just becomes `Foo<'a, 'b, ..>`. - hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes) - } - - /// Lowers a `ReturnPositionOpaqueTy` (`-> impl Trait`) or a `TypeAliasesOpaqueTy` (`type F = - /// impl Trait`): this creates the associated Opaque Type (TAIT) definition and then returns a - /// HIR type that references the TAIT. - /// - /// Given a function definition like: - /// - /// ```rust - /// fn test<'a, T: Debug>(x: &'a T) -> impl Debug + 'a { - /// x - /// } - /// ``` - /// - /// we will create a TAIT definition in the HIR like - /// - /// ``` - /// type TestReturn<'a, T, 'x> = impl Debug + 'x - /// ``` - /// - /// and return a type like `TestReturn<'static, T, 'a>`, so that the function looks like: - /// - /// ```rust - /// fn test<'a, T: Debug>(x: &'a T) -> TestReturn<'static, T, 'a> - /// ``` - /// - /// Note the subtlety around type parameters! The new TAIT, `TestReturn`, inherits all the - /// type parameters from the function `test` (this is implemented in the query layer, they aren't - /// added explicitly in the HIR). But this includes all the lifetimes, and we only want to - /// capture the lifetimes that are referenced in the bounds. Therefore, we add *extra* lifetime parameters - /// for the lifetimes that get captured (`'x`, in our example above) and reference those. - #[tracing::instrument(level = "debug", skip(self))] - fn lower_opaque_impl_trait_v2<'itctx>( &mut self, span: Span, origin: hir::OpaqueTyOrigin, @@ -2099,7 +1941,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ); // `impl Trait` now just becomes `Foo<'a, 'b, ..>`. - hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, generic_args) + let result = hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, generic_args); + debug!("lower_opaque_impl_trait = {:?}", result); + result } /// Registers a new opaque type with the proper `NodeId`s and diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index dbc9b61b455a9..e09c3ccbc75ab 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -178,8 +178,6 @@ declare_features! ( /// Use for stable + negative coherence and strict coherence depending on trait's /// rustc_strict_coherence value. (active, with_negative_coherence, "1.60.0", None, None), - /// Added for testing impl trait in return position using a "sibling" type - (active, return_position_impl_trait_v2, "1.62.0", None, None), // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! // Features are listed in alphabetical order. Tidy will fail if you don't keep it this way. // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 0372c3ed9726a..32e52b4f001ca 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -346,12 +346,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { debug!(?concrete_ty); let first_own_region = match self.opaque_ty_origin_unchecked(def_id, span) { - hir::OpaqueTyOrigin::FnReturn(..) - if tcx.sess.features_untracked().return_position_impl_trait_v2 => - { - 0 - } - hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => { + hir::OpaqueTyOrigin::AsyncFn(..) => { // We lower // // fn foo<'l0..'ln>() -> impl Trait<'l0..'lm> @@ -366,7 +361,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } // These opaque type inherit all lifetime parameters from their // parent, so we have to check them all. - hir::OpaqueTyOrigin::TyAlias => 0, + hir::OpaqueTyOrigin::TyAlias | hir::OpaqueTyOrigin::FnReturn(..) => 0, }; // For a case like `impl Foo<'a, 'b>`, we would generate a constraint diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index a9575463efc59..88793dac8f37a 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2398,15 +2398,8 @@ pub fn is_impl_trait_defn(tcx: TyCtxt<'_>, def_id: DefId) -> Option if let Node::Item(item) = tcx.hir().get_by_def_id(def_id) { if let hir::ItemKind::OpaqueTy(ref opaque_ty) = item.kind { return match opaque_ty.origin { - hir::OpaqueTyOrigin::FnReturn(_) - if tcx.sess.features_untracked().return_position_impl_trait_v2 => - { - None - } - hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent) => { - Some(parent) - } - hir::OpaqueTyOrigin::TyAlias => None, + hir::OpaqueTyOrigin::AsyncFn(parent) => Some(parent), + hir::OpaqueTyOrigin::TyAlias | hir::OpaqueTyOrigin::FnReturn(_) => None, }; } } diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 5dfe41ed28f7a..8382b4f70aa6b 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -1054,7 +1054,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { let parent = hir_map.get_parent_node(lt.hir_id); match hir_map.get(parent) { - hir::Node::Item(&hir::Item { kind: hir::ItemKind::OpaqueTy(..), .. }) if this.tcx.sess.features_untracked().return_position_impl_trait_v2 => { + hir::Node::Item(&hir::Item { kind: hir::ItemKind::OpaqueTy(..), .. }) => { // do not warn } _ => { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 9e492e016326a..6eca7dc52b26a 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1178,7 +1178,6 @@ symbols! { require, residual, result, - return_position_impl_trait_v2, rhs, rintf32, rintf64, diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 3ac24af712570..859ed31dcbc0b 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -2707,9 +2707,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let tcx = self.tcx(); match origin { - hir::OpaqueTyOrigin::FnReturn(..) - if tcx.sess.features_untracked().return_position_impl_trait_v2 => - { + hir::OpaqueTyOrigin::FnReturn(..) => { let params = &self.tcx().generics_of(def_id).params; assert_eq!(params.len(), generic_args.len()); let substs: Vec<_> = generic_args diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index e8b15faffa805..367421206dd5f 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -726,13 +726,7 @@ fn check_opaque_meets_bounds<'tcx>( let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); let (param_env_did, defining_use_anchor) = match *origin { - hir::OpaqueTyOrigin::FnReturn(did) => { - if tcx.sess.features_untracked().return_position_impl_trait_v2 { - (def_id, did) - } else { - (did, did) - } - } + hir::OpaqueTyOrigin::FnReturn(did) => (def_id, did), hir::OpaqueTyOrigin::AsyncFn(did) => (did, did), hir::OpaqueTyOrigin::TyAlias => (def_id, def_id), }; diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 993fd8e07838c..81c1afd8d2ffc 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -618,7 +618,7 @@ fn type_param_predicates( | ItemKind::TyAlias(_, ref generics) | ItemKind::OpaqueTy(OpaqueTy { ref generics, - origin: hir::OpaqueTyOrigin::TyAlias, + origin: hir::OpaqueTyOrigin::TyAlias | hir::OpaqueTyOrigin::FnReturn(..), .. }) | ItemKind::Enum(_, ref generics) @@ -633,19 +633,6 @@ fn type_param_predicates( } generics } - ItemKind::OpaqueTy(OpaqueTy { - ref generics, - origin: hir::OpaqueTyOrigin::FnReturn(..), - .. - }) if tcx.sess.features_untracked().return_position_impl_trait_v2 => { - // Implied `Self: Trait` and supertrait bounds. - if param_id == item_hir_id { - let identity_trait_ref = ty::TraitRef::identity(tcx, item_def_id); - extend = - Some((identity_trait_ref.without_const().to_predicate(tcx), item.span)); - } - generics - } _ => return result, } } @@ -1596,12 +1583,6 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { Some(tcx.typeck_root_def_id(def_id)) } Node::Item(item) => match item.kind { - ItemKind::OpaqueTy(hir::OpaqueTy { - origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), - .. - }) if !tcx.sess.features_untracked().return_position_impl_trait_v2 => { - Some(fn_def_id.to_def_id()) - } ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::AsyncFn(fn_def_id), .. @@ -2169,31 +2150,6 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP is_trait = Some(ty::TraitRef::identity(tcx, def_id)); *generics } - ItemKind::OpaqueTy(OpaqueTy { - ref generics, - origin: hir::OpaqueTyOrigin::FnReturn(..), - .. - }) => { - // return-position impl trait - // - // We don't inherit predicates from the parent here: - // If we have, say `fn f<'a, T: 'a>() -> impl Sized {}` - // then the return type is `f::<'static, T>::{{opaque}}`. - // - // If we inherited the predicates of `f` then we would - // require that `T: 'static` to show that the return - // type is well-formed. - // - // The only way to have something with this opaque type - // is from the return type of the containing function, - // which will ensure that the function's predicates - // hold. - if !tcx.sess.features_untracked().return_position_impl_trait_v2 { - return ty::GenericPredicates { parent: None, predicates: &[] }; - } - - generics - } ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::AsyncFn(..), .. }) => { @@ -2215,12 +2171,9 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP } ItemKind::OpaqueTy(OpaqueTy { ref generics, - origin: hir::OpaqueTyOrigin::TyAlias, + origin: hir::OpaqueTyOrigin::TyAlias | hir::OpaqueTyOrigin::FnReturn(..), .. - }) => { - // type-alias impl trait - generics - } + }) => generics, _ => NO_GENERICS, } diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index b574eacb2a9c9..3f95361e3e8a3 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -196,9 +196,7 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option< (generics, arg_index) } - Node::Ty(&Ty { kind: TyKind::OpaqueDef(id, generics), .. }) - if tcx.sess.features_untracked().return_position_impl_trait_v2 => - { + Node::Ty(&Ty { kind: TyKind::OpaqueDef(id, generics), .. }) => { let parent_generics = tcx.generics_of(id.def_id.to_def_id()); generics diff --git a/src/test/ui/impl-trait/v2/apit.rs b/src/test/ui/impl-trait/v2/apit.rs deleted file mode 100644 index a4d3049f5af8a..0000000000000 --- a/src/test/ui/impl-trait/v2/apit.rs +++ /dev/null @@ -1,9 +0,0 @@ -// check-pass - -trait MyTrait {} - -fn foo(f: impl MyTrait) -> impl MyTrait { - f -} - -fn main() {} diff --git a/src/test/ui/impl-trait/v2/apit2.rs b/src/test/ui/impl-trait/v2/apit2.rs deleted file mode 100644 index e3e1e62f39449..0000000000000 --- a/src/test/ui/impl-trait/v2/apit2.rs +++ /dev/null @@ -1,9 +0,0 @@ -// check-pass - -#![feature(return_position_impl_trait_v2)] - -fn i(a: impl Iterator) -> impl Iterator { - a -} - -fn main() {} diff --git a/src/test/ui/impl-trait/v2/async-await-bounds.rs b/src/test/ui/impl-trait/v2/async-await-bounds.rs deleted file mode 100644 index 9d55bee8e13d1..0000000000000 --- a/src/test/ui/impl-trait/v2/async-await-bounds.rs +++ /dev/null @@ -1,16 +0,0 @@ -// build-pass (FIXME(62277): could be check-pass?) -// edition:2018 - -#![feature(return_position_impl_trait_v2)] - -use std::future::Future; - -pub trait Foo { - fn foo(&self) {} -} - -pub fn call_with_ref_block<'a>(f: &'a (impl Foo + 'a)) -> impl Future + 'a { - async move { f.foo() } -} - -fn main() {} diff --git a/src/test/ui/impl-trait/v2/async-await-generics-and-bounds.rs b/src/test/ui/impl-trait/v2/async-await-generics-and-bounds.rs deleted file mode 100644 index 937e05dc6cddf..0000000000000 --- a/src/test/ui/impl-trait/v2/async-await-generics-and-bounds.rs +++ /dev/null @@ -1,9 +0,0 @@ -// check-pass -// edition:2018 -// compile-flags: --crate-type lib - -#![feature(return_position_impl_trait_v2)] - -pub fn foo(f: impl Send) -> impl Send { - f -} diff --git a/src/test/ui/impl-trait/v2/async-fn-elided-impl-lifetime-parameter.rs b/src/test/ui/impl-trait/v2/async-fn-elided-impl-lifetime-parameter.rs deleted file mode 100644 index 67dd6d41f657a..0000000000000 --- a/src/test/ui/impl-trait/v2/async-fn-elided-impl-lifetime-parameter.rs +++ /dev/null @@ -1,33 +0,0 @@ -// Check that `async fn` inside of an impl with `'_` -// in the header compiles correctly. -// -// Regression test for #63500. -// -// check-pass -// edition:2018 - -#![feature(return_position_impl_trait_v2)] - -struct Foo<'a>(&'a u8); - -impl Foo<'_> { // impl Foo<'(fresh:NodeId0)> -// ^ extra_lifetime_parameters: [fresh:NodeId0] -// -// we insert these into `node_id_to_def_id_override` - - async fn bar() {} - // but HERE, when you have an async function, you create a node-id for it (opaque_ty_id) - // - // and we attach (using `extra_lifetime_parameters`) a list of *all the lifetimes that are in scope from the impl and the fn* - // - // -} - -// for<> fn(&'(fresh:NodeId0) u32) -// ^ -// extra_lifetime_parameters: [fresh:NodeId0] instantiate def-ids for them and add them into the node_id_to_def_id_override -// with the node id NodeId0 -// -// then later when we process `fresh:NodeId0` we look up in `node_id_to_def_id_override` and we find it - -fn main() {} diff --git a/src/test/ui/impl-trait/v2/bounds_regression.rs b/src/test/ui/impl-trait/v2/bounds_regression.rs deleted file mode 100644 index 72a53ee6cc4a7..0000000000000 --- a/src/test/ui/impl-trait/v2/bounds_regression.rs +++ /dev/null @@ -1,26 +0,0 @@ -// check-pass - -#![feature(return_position_impl_trait_v2)] - -pub trait FakeGenerator { - type Yield; - type Return; -} - -pub trait FakeFuture { - type Output; -} - -pub fn future_from_generator>( - x: T, -) -> impl FakeFuture { - GenFuture(x) -} - -struct GenFuture>(T); - -impl> FakeFuture for GenFuture { - type Output = T::Return; -} - -fn main() {} diff --git a/src/test/ui/impl-trait/v2/const-generics.rs b/src/test/ui/impl-trait/v2/const-generics.rs deleted file mode 100644 index 7d09d1898c755..0000000000000 --- a/src/test/ui/impl-trait/v2/const-generics.rs +++ /dev/null @@ -1,12 +0,0 @@ -// check-pass - -#![feature(return_position_impl_trait_v2)] - -trait Trait {} -impl Trait for u32 {} - -fn rawr() -> impl Trait { - 0 -} - -fn main() {} diff --git a/src/test/ui/impl-trait/v2/filter_fold.rs b/src/test/ui/impl-trait/v2/filter_fold.rs deleted file mode 100644 index 9a59debcafcec..0000000000000 --- a/src/test/ui/impl-trait/v2/filter_fold.rs +++ /dev/null @@ -1,13 +0,0 @@ -// check-pass - -#![feature(return_position_impl_trait_v2)] - -pub trait Try { - type Output; -} - -fn filter_try_fold<'a>(predicate: &'a mut impl FnMut(&u32) -> bool) -> impl Sized { - 22 -} - -fn main() {} diff --git a/src/test/ui/impl-trait/v2/filter_fold2.rs b/src/test/ui/impl-trait/v2/filter_fold2.rs deleted file mode 100644 index a742b0cee6eef..0000000000000 --- a/src/test/ui/impl-trait/v2/filter_fold2.rs +++ /dev/null @@ -1,7 +0,0 @@ -// check-pass - -#![feature(return_position_impl_trait_v2)] - -fn foo() -> impl Sized {} - -fn main() {} diff --git a/src/test/ui/impl-trait/v2/generics-assoc-type.rs b/src/test/ui/impl-trait/v2/generics-assoc-type.rs deleted file mode 100644 index c5c3adcc05a62..0000000000000 --- a/src/test/ui/impl-trait/v2/generics-assoc-type.rs +++ /dev/null @@ -1,16 +0,0 @@ -// check-pass - -#![feature(return_position_impl_trait_v2)] - -trait MyTrait {} - -impl MyTrait for T {} - -fn ident_as_my_trait<'a, T>(_u: &'a i32, t: T) -> impl MyTrait -where - 'static: 'a, -{ - t -} - -fn main() {} diff --git a/src/test/ui/impl-trait/v2/generics-unbound.rs b/src/test/ui/impl-trait/v2/generics-unbound.rs deleted file mode 100644 index a49850811fcb2..0000000000000 --- a/src/test/ui/impl-trait/v2/generics-unbound.rs +++ /dev/null @@ -1,21 +0,0 @@ -// check-pass - -#![feature(return_position_impl_trait_v2)] - -trait MyTrait { - fn get_inner(self) -> T; -} - -impl MyTrait for T { - fn get_inner(self) -> Self { - self - } -} - -fn ident_as_my_trait(t: T) -> impl MyTrait { - t -} - -fn main() { - assert_eq!(22, ident_as_my_trait(22).get_inner()); -} diff --git a/src/test/ui/impl-trait/v2/lifetimes.rs b/src/test/ui/impl-trait/v2/lifetimes.rs deleted file mode 100644 index b8327d270a9a3..0000000000000 --- a/src/test/ui/impl-trait/v2/lifetimes.rs +++ /dev/null @@ -1,17 +0,0 @@ -// check-pass - -#![allow(warnings)] -#![feature(return_position_impl_trait_v2)] - -use std::fmt::Debug; - -trait MultiRegionTrait<'a, 'b>: Debug {} - -#[derive(Debug)] -struct MultiRegionStruct<'a, 'b>(&'a u32, &'b u32); -impl<'a, 'b> MultiRegionTrait<'a, 'b> for MultiRegionStruct<'a, 'b> {} - -fn finds_explicit_bound<'a: 'b, 'b>(x: &'a u32, y: &'b u32) -> impl MultiRegionTrait<'a, 'b> + 'b { - MultiRegionStruct(x, y) -} -fn main() {} diff --git a/src/test/ui/impl-trait/v2/nested-return-type.rs b/src/test/ui/impl-trait/v2/nested-return-type.rs deleted file mode 100644 index ac073f8df5fb0..0000000000000 --- a/src/test/ui/impl-trait/v2/nested-return-type.rs +++ /dev/null @@ -1,10 +0,0 @@ -// Check that nested impl Trait items work in functions with generic parameters. -// check-pass - -#![feature(return_position_impl_trait_v2)] - -fn nested_assoc_type<'a, T>() -> impl Iterator { - [1].iter() -} - -fn main() {} diff --git a/src/test/ui/impl-trait/v2/simple-definition.rs b/src/test/ui/impl-trait/v2/simple-definition.rs deleted file mode 100644 index 79f609ba4ce9f..0000000000000 --- a/src/test/ui/impl-trait/v2/simple-definition.rs +++ /dev/null @@ -1,13 +0,0 @@ -// check-pass - -#![feature(return_position_impl_trait_v2)] - -use std::fmt::Debug; - -fn foo() -> impl Debug { - 22 -} - -fn main() { - assert_eq!("22", format!("{:?}", foo())); -} diff --git a/src/test/ui/impl-trait/v2/sized_bounds.rs b/src/test/ui/impl-trait/v2/sized_bounds.rs deleted file mode 100644 index 12eeb6d614bda..0000000000000 --- a/src/test/ui/impl-trait/v2/sized_bounds.rs +++ /dev/null @@ -1,12 +0,0 @@ -//run-pass -#![deny(rust_2021_incompatible_closure_captures)] -#![allow(unused_must_use)] -#![feature(return_position_impl_trait_v2)] - -fn filter_try_fold(predicate: &mut impl FnMut() -> bool) -> impl FnMut() -> bool + '_ { - move || predicate() -} - -fn main() { - filter_try_fold(&mut || true); -} diff --git a/src/test/ui/impl-trait/v2/try_trait.rs b/src/test/ui/impl-trait/v2/try_trait.rs deleted file mode 100644 index c451cb802c66c..0000000000000 --- a/src/test/ui/impl-trait/v2/try_trait.rs +++ /dev/null @@ -1,15 +0,0 @@ -// check-pass - -#![feature(return_position_impl_trait_v2)] - -pub(crate) struct NeverShortCircuit(pub T); - -impl NeverShortCircuit { - /// Wrap a binary `FnMut` to return its result wrapped in a `NeverShortCircuit`. - #[inline] - pub fn wrap_mut_2(mut f: impl FnMut(A, B) -> T) -> impl FnMut(A, B) -> Self { - move |a, b| NeverShortCircuit(f(a, b)) - } -} - -fn main() {} diff --git a/src/test/ui/impl-trait/v2/where_bounds.rs b/src/test/ui/impl-trait/v2/where_bounds.rs deleted file mode 100644 index 110faa2c977b1..0000000000000 --- a/src/test/ui/impl-trait/v2/where_bounds.rs +++ /dev/null @@ -1,14 +0,0 @@ -// check-pass - -#![feature(return_position_impl_trait_v2)] - -trait MyTrait {} - -fn foo(t: T) -> impl MyTrait -where - T: MyTrait, -{ - t -} - -fn main() {} diff --git a/src/test/ui/impl-trait/v2/where_bounds2.rs b/src/test/ui/impl-trait/v2/where_bounds2.rs deleted file mode 100644 index a729aafd754c7..0000000000000 --- a/src/test/ui/impl-trait/v2/where_bounds2.rs +++ /dev/null @@ -1,11 +0,0 @@ -// check-pass - -#![feature(return_position_impl_trait_v2)] - -trait MyTrait {} - -fn foo(t: T) -> impl MyTrait { - t -} - -fn main() {} From 25bbe2a3cc729897cea7004ac6287b94f0baf651 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 2 Sep 2022 17:38:58 -0300 Subject: [PATCH 39/53] Remove reborrow in favor of passing &mut --- compiler/rustc_ast_lowering/src/asm.rs | 2 +- compiler/rustc_ast_lowering/src/block.rs | 2 +- compiler/rustc_ast_lowering/src/expr.rs | 34 ++++--- compiler/rustc_ast_lowering/src/item.rs | 103 ++++++++++--------- compiler/rustc_ast_lowering/src/lib.rs | 120 +++++++++-------------- compiler/rustc_ast_lowering/src/pat.rs | 6 +- compiler/rustc_ast_lowering/src/path.rs | 30 +++--- 7 files changed, 143 insertions(+), 154 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 0dba9da63da2a..e5d2a45868ebb 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -220,7 +220,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &sym.qself, &sym.path, ParamMode::Optional, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); hir::InlineAsmOperand::SymStatic { path, def_id } } else { diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs index 7cbfe143b4d83..7ed92c9688863 100644 --- a/compiler/rustc_ast_lowering/src/block.rs +++ b/compiler/rustc_ast_lowering/src/block.rs @@ -87,7 +87,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let ty = l .ty .as_ref() - .map(|t| self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Variable))); + .map(|t| self.lower_ty(t, &mut ImplTraitContext::Disallowed(ImplTraitPosition::Variable))); let init = l.kind.init().map(|init| self.lower_expr(init)); let hir_id = self.lower_node_id(l.id); let pat = self.lower_pat(&l.pat); diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index c4c0ab904f10c..6ab12a72b442a 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -66,7 +66,7 @@ impl<'hir> LoweringContext<'_, 'hir> { seg, ParamMode::Optional, ParenthesizedGenericArgs::Err, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Path), )); let args = self.arena.alloc_from_iter( [&*receiver].into_iter().chain(args.iter()).map(|x| self.lower_expr_mut(x)), @@ -89,14 +89,14 @@ impl<'hir> LoweringContext<'_, 'hir> { } ExprKind::Cast(ref expr, ref ty) => { let expr = self.lower_expr(expr); - let ty = - self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + let ty = self + .lower_ty(ty, &mut ImplTraitContext::Disallowed(ImplTraitPosition::Type)); hir::ExprKind::Cast(expr, ty) } ExprKind::Type(ref expr, ref ty) => { let expr = self.lower_expr(expr); - let ty = - self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + let ty = self + .lower_ty(ty, &mut ImplTraitContext::Disallowed(ImplTraitPosition::Type)); hir::ExprKind::Type(expr, ty) } ExprKind::AddrOf(k, m, ref ohs) => { @@ -219,7 +219,7 @@ impl<'hir> LoweringContext<'_, 'hir> { qself, path, ParamMode::Optional, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); hir::ExprKind::Path(qpath) } @@ -253,7 +253,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &se.qself, &se.path, ParamMode::Optional, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Path), )), self.arena .alloc_from_iter(se.fields.iter().map(|x| self.lower_expr_field(x))), @@ -550,12 +550,14 @@ impl<'hir> LoweringContext<'_, 'hir> { async_gen_kind: hir::AsyncGeneratorKind, body: impl FnOnce(&mut Self) -> hir::Expr<'hir>, ) -> hir::ExprKind<'hir> { - let output = match ret_ty { - Some(ty) => hir::FnRetTy::Return( - self.lower_ty(&ty, ImplTraitContext::Disallowed(ImplTraitPosition::AsyncBlock)), - ), - None => hir::FnRetTy::DefaultReturn(self.lower_span(span)), - }; + let output = + match ret_ty { + Some(ty) => hir::FnRetTy::Return(self.lower_ty( + &ty, + &mut ImplTraitContext::Disallowed(ImplTraitPosition::AsyncBlock), + )), + None => hir::FnRetTy::DefaultReturn(self.lower_span(span)), + }; // Resume argument type. We let the compiler infer this to simplify the lowering. It is // fully constrained by `future::from_generator`. @@ -1138,7 +1140,7 @@ impl<'hir> LoweringContext<'_, 'hir> { qself, path, ParamMode::Optional, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); // Destructure like a tuple struct. let tuple_struct_pat = @@ -1154,7 +1156,7 @@ impl<'hir> LoweringContext<'_, 'hir> { qself, path, ParamMode::Optional, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); // Destructure like a unit struct. let unit_struct_pat = hir::PatKind::Path(qpath); @@ -1178,7 +1180,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &se.qself, &se.path, ParamMode::Optional, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); let fields_omitted = match &se.rest { StructRest::Base(e) => { diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 7bc664640469e..14a7c26715bcc 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -270,8 +270,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let body_id = this.lower_maybe_async_body(span, &decl, asyncness, body.as_deref()); - let itctx = ImplTraitContext::Universal { apit_nodes: &mut Vec::new() }; - let (generics, decl) = this.lower_generics(generics, id, itctx, |this| { + let mut itctx = ImplTraitContext::Universal { apit_nodes: &mut Vec::new() }; + 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, generics, None, ret_id) }); @@ -317,8 +317,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let (generics, ty) = self.lower_generics( &generics, id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), - |this| this.lower_ty(ty, ImplTraitContext::TypeAliasesOpaqueTy), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + |this| this.lower_ty(ty, &mut ImplTraitContext::TypeAliasesOpaqueTy), ); hir::ItemKind::TyAlias(ty, generics) } @@ -330,7 +330,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let (generics, ty) = self.lower_generics( &generics, id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| this.arena.alloc(this.ty(span, hir::TyKind::Err)), ); hir::ItemKind::TyAlias(ty, generics) @@ -339,7 +339,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let (generics, variants) = self.lower_generics( generics, id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { this.arena.alloc_from_iter( enum_definition.variants.iter().map(|x| this.lower_variant(x)), @@ -352,7 +352,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let (generics, struct_def) = self.lower_generics( generics, id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| this.lower_variant_data(hir_id, struct_def), ); hir::ItemKind::Struct(struct_def, generics) @@ -361,7 +361,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let (generics, vdata) = self.lower_generics( generics, id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| this.lower_variant_data(hir_id, vdata), ); hir::ItemKind::Union(vdata, generics) @@ -389,18 +389,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // method, it will not be considered an in-band // lifetime to be added, but rather a reference to a // parent lifetime. - let itctx = ImplTraitContext::Universal { apit_nodes: &mut Vec::new() }; + let mut itctx = ImplTraitContext::Universal { apit_nodes: &mut Vec::new() }; let (generics, (trait_ref, lowered_ty)) = - self.lower_generics(ast_generics, id, itctx, |this| { + self.lower_generics(ast_generics, id, &mut itctx, |this| { let trait_ref = trait_ref.as_ref().map(|trait_ref| { this.lower_trait_ref( trait_ref, - ImplTraitContext::Disallowed(ImplTraitPosition::Trait), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Trait), ) }); - let lowered_ty = this - .lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + let lowered_ty = this.lower_ty( + ty, + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Type), + ); (trait_ref, lowered_ty) }); @@ -439,11 +441,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let (generics, (unsafety, items, bounds)) = self.lower_generics( generics, id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { let bounds = this.lower_param_bounds( bounds, - ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Bound), ); let items = this.arena.alloc_from_iter( items.iter().map(|item| this.lower_trait_item_ref(item)), @@ -458,11 +460,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let (generics, bounds) = self.lower_generics( generics, id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { this.lower_param_bounds( bounds, - ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Bound), ) }, ); @@ -485,7 +487,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: Span, body: Option<&Expr>, ) -> (&'hir hir::Ty<'hir>, hir::BodyId) { - let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + let ty = self.lower_ty(ty, &mut ImplTraitContext::Disallowed(ImplTraitPosition::Type)); (ty, self.lower_const_body(span, body)) } @@ -658,9 +660,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { kind: match i.kind { ForeignItemKind::Fn(box Fn { ref sig, ref generics, .. }) => { let fdec = &sig.decl; - let itctx = ImplTraitContext::Universal { apit_nodes: &mut Vec::new() }; + let mut itctx = ImplTraitContext::Universal { apit_nodes: &mut Vec::new() }; let (generics, (fn_dec, fn_args)) = - self.lower_generics(generics, i.id, itctx, |this| { + self.lower_generics(generics, i.id, &mut itctx, |this| { ( // Disallow `impl Trait` in foreign items. this.lower_fn_decl( @@ -678,8 +680,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::ForeignItemKind::Fn(fn_dec, fn_args, generics) } ForeignItemKind::Static(ref t, m, _) => { - let ty = - self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + let ty = self + .lower_ty(t, &mut ImplTraitContext::Disallowed(ImplTraitPosition::Type)); hir::ForeignItemKind::Static(ty, m) } ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type, @@ -747,11 +749,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself, path, ParamMode::ExplicitNamed, // no `'_` in declarations (Issue #61124) - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); self.arena.alloc(t) } else { - self.lower_ty(&f.ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)) + self.lower_ty(&f.ty, &mut ImplTraitContext::Disallowed(ImplTraitPosition::Type)) }; let hir_id = self.lower_node_id(f.id); self.lower_attrs(hir_id, &f.attrs); @@ -778,7 +780,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let (generics, kind, has_default) = match i.kind { AssocItemKind::Const(_, ref ty, ref default) => { - let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + let ty = + self.lower_ty(ty, &mut ImplTraitContext::Disallowed(ImplTraitPosition::Type)); let body = default.as_ref().map(|x| self.lower_const_body(i.span, Some(x))); (hir::Generics::empty(), hir::TraitItemKind::Const(ty, body), body.is_some()) } @@ -820,15 +823,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let (generics, kind) = self.lower_generics( &generics, i.id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { let ty = ty.as_ref().map(|x| { - this.lower_ty(x, ImplTraitContext::Disallowed(ImplTraitPosition::Type)) + this.lower_ty( + x, + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Type), + ) }); hir::TraitItemKind::Type( this.lower_param_bounds( bounds, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Generic), ), ty, ) @@ -885,7 +891,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let (generics, kind) = match &i.kind { AssocItemKind::Const(_, ty, expr) => { - let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + let ty = + self.lower_ty(ty, &mut ImplTraitContext::Disallowed(ImplTraitPosition::Type)); ( hir::Generics::empty(), hir::ImplItemKind::Const(ty, self.lower_const_body(i.span, expr.as_deref())), @@ -913,14 +920,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.lower_generics( &generics, i.id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| match ty { None => { let ty = this.arena.alloc(this.ty(i.span, hir::TyKind::Err)); hir::ImplItemKind::TyAlias(ty) } Some(ty) => { - let ty = this.lower_ty(ty, ImplTraitContext::TypeAliasesOpaqueTy); + let ty = this.lower_ty(ty, &mut ImplTraitContext::TypeAliasesOpaqueTy); hir::ImplItemKind::TyAlias(ty) } }, @@ -1263,8 +1270,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { is_async: Option, ) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) { let header = self.lower_fn_header(sig.header); - let itctx = ImplTraitContext::Universal { apit_nodes: &mut Vec::new() }; - let (generics, decl) = self.lower_generics(&generics, id, itctx, |this| { + let mut itctx = ImplTraitContext::Universal { apit_nodes: &mut Vec::new() }; + let (generics, decl) = self.lower_generics(&generics, id, &mut itctx, |this| { this.lower_fn_decl( &sig.decl, Some(id), @@ -1337,7 +1344,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, generics: &'itctx Generics, parent_node_id: NodeId, - mut itctx: ImplTraitContext<'_, 'itctx>, + itctx: &mut ImplTraitContext<'_, 'itctx>, f: impl FnOnce(&mut Self) -> T, ) -> (&'hir hir::Generics<'hir>, T) where @@ -1396,7 +1403,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { param.id, ¶m.kind, ¶m.bounds, - itctx.reborrow(), + itctx, PredicateOrigin::GenericParam, ) })); @@ -1445,7 +1452,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { id: NodeId, kind: &GenericParamKind, bounds: &'itctx [GenericBound], - mut itctx: ImplTraitContext<'_, 'itctx>, + itctx: &mut ImplTraitContext<'_, 'itctx>, origin: PredicateOrigin, ) -> Option> where @@ -1456,7 +1463,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { return None; } - let bounds = self.lower_param_bounds(bounds, itctx.reborrow()); + let bounds = self.lower_param_bounds(bounds, itctx); let ident = self.lower_ident(ident); let param_span = ident.span; @@ -1522,12 +1529,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span, }) => hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { bound_generic_params: self.lower_generic_params(bound_generic_params), - bounded_ty: self - .lower_ty(bounded_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)), + bounded_ty: self.lower_ty( + bounded_ty, + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Type), + ), bounds: self.arena.alloc_from_iter(bounds.iter().map(|bound| { self.lower_param_bound( bound, - ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Bound), ) })), span: self.lower_span(span), @@ -1542,16 +1551,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { lifetime: self.lower_lifetime(lifetime), bounds: self.lower_param_bounds( bounds, - ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Bound), ), in_where_clause: true, }), WherePredicate::EqPredicate(WhereEqPredicate { ref lhs_ty, ref rhs_ty, span }) => { hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { - lhs_ty: self - .lower_ty(lhs_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)), - rhs_ty: self - .lower_ty(rhs_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)), + lhs_ty: self.lower_ty( + lhs_ty, + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Type), + ), + rhs_ty: self.lower_ty( + rhs_ty, + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Type), + ), span: self.lower_span(span), }) } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 56de7bff6fd37..38dd63c0c3f86 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -322,25 +322,6 @@ enum ImplTraitPosition { ImplReturn, } -impl<'itctx> ImplTraitContext<'_, 'itctx> { - fn reborrow<'this>(&'this mut self) -> ImplTraitContext<'this, 'itctx> { - use self::ImplTraitContext::*; - match self { - Universal { apit_nodes } => Universal { apit_nodes: *apit_nodes }, - ReturnPositionOpaqueTy { origin, impl_trait_inputs, generics, parent_generics } => { - ReturnPositionOpaqueTy { - origin: *origin, - impl_trait_inputs: *impl_trait_inputs, - generics: *generics, - parent_generics: *parent_generics, - } - } - TypeAliasesOpaqueTy => TypeAliasesOpaqueTy, - Disallowed(pos) => Disallowed(*pos), - } - } -} - impl std::fmt::Display for ImplTraitPosition { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let name = match self { @@ -1166,7 +1147,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_assoc_ty_constraint<'itctx>( &mut self, constraint: &'itctx AssocConstraint, - mut itctx: ImplTraitContext<'_, 'itctx>, + itctx: &mut ImplTraitContext<'_, 'itctx>, ) -> hir::TypeBinding<'hir> where 'a: 'itctx, @@ -1176,28 +1157,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let gen_args = if let Some(ref gen_args) = constraint.gen_args { let gen_args_ctor = match gen_args { GenericArgs::AngleBracketed(ref data) => { - self.lower_angle_bracketed_parameter_data( - data, - ParamMode::Explicit, - itctx.reborrow(), - ) - .0 + self.lower_angle_bracketed_parameter_data(data, ParamMode::Explicit, itctx).0 } GenericArgs::Parenthesized(ref data) => { self.emit_bad_parenthesized_trait_in_assoc_ty(data); let aba = self.lowering_arena.aba.alloc(data.as_angle_bracketed_args()); - self.lower_angle_bracketed_parameter_data( - aba, - ParamMode::Explicit, - itctx.reborrow(), - ) - .0 + self.lower_angle_bracketed_parameter_data(aba, ParamMode::Explicit, itctx).0 } }; gen_args_ctor.into_generic_args(self) } else { self.arena.alloc(hir::GenericArgs::none()) }; + let mut itctx_tait = ImplTraitContext::TypeAliasesOpaqueTy; let kind = match constraint.kind { AssocConstraintKind::Equality { ref term } => { @@ -1218,7 +1190,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // // fn foo() -> impl Iterator ImplTraitContext::ReturnPositionOpaqueTy { .. } - | ImplTraitContext::TypeAliasesOpaqueTy { .. } => (true, itctx.reborrow()), + | ImplTraitContext::TypeAliasesOpaqueTy { .. } => (true, itctx), // We are in the argument position, but within a dyn type: // @@ -1227,9 +1199,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // so desugar to // // fn foo(x: dyn Iterator) - ImplTraitContext::Universal { .. } if self.is_in_dyn_type => { - (true, itctx.reborrow()) - } + ImplTraitContext::Universal { .. } if self.is_in_dyn_type => (true, itctx), // In `type Foo = dyn Iterator` we desugar to // `type Foo = dyn Iterator` but we have to override the @@ -1238,7 +1208,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // // FIXME: this is only needed until `impl Trait` is allowed in type aliases. ImplTraitContext::Disallowed(_) if self.is_in_dyn_type => { - (true, ImplTraitContext::TypeAliasesOpaqueTy) + (true, &mut itctx_tait) } // We are in the parameter position, but not within a dyn type: @@ -1318,7 +1288,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_generic_arg<'itctx>( &mut self, arg: &'itctx ast::GenericArg, - itctx: ImplTraitContext<'_, 'itctx>, + itctx: &mut ImplTraitContext<'_, 'itctx>, ) -> hir::GenericArg<'hir> where 'a: 'itctx, @@ -1386,7 +1356,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_ty<'itctx>( &mut self, t: &'itctx Ty, - itctx: ImplTraitContext<'_, 'itctx>, + itctx: &mut ImplTraitContext<'_, 'itctx>, ) -> &'hir hir::Ty<'hir> where 'a: 'itctx, @@ -1400,7 +1370,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself: &'itctx Option, path: &'itctx Path, param_mode: ParamMode, - itctx: ImplTraitContext<'_, 'itctx>, + itctx: &mut ImplTraitContext<'_, 'itctx>, ) -> hir::Ty<'hir> where 'a: 'itctx, @@ -1449,7 +1419,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_ty_direct<'itctx>( &mut self, t: &'itctx Ty, - mut itctx: ImplTraitContext<'_, 'itctx>, + itctx: &mut ImplTraitContext<'_, 'itctx>, ) -> hir::Ty<'hir> where 'a: 'itctx, @@ -1502,11 +1472,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }) } TyKind::Never => hir::TyKind::Never, - TyKind::Tup(ref tys) => { - hir::TyKind::Tup(self.arena.alloc_from_iter( - tys.iter().map(|ty| self.lower_ty_direct(ty, itctx.reborrow())), - )) - } + TyKind::Tup(ref tys) => hir::TyKind::Tup( + self.arena.alloc_from_iter(tys.iter().map(|ty| self.lower_ty_direct(ty, itctx))), + ), TyKind::Paren(ref ty) => { return self.lower_ty_direct(ty, itctx); } @@ -1540,7 +1508,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { GenericBound::Trait( ref ty, TraitBoundModifier::None | TraitBoundModifier::MaybeConst, - ) => Some(this.lower_poly_trait_ref(ty, itctx.reborrow())), + ) => Some(this.lower_poly_trait_ref(ty, itctx)), // `~const ?Bound` will cause an error during AST validation // anyways, so treat it like `?Bound` as compilation proceeds. GenericBound::Trait( @@ -1575,7 +1543,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.lowering_arena.gs.alloc(parent_generics.merge(generics)); self.lower_opaque_impl_trait( span, - origin, + *origin, def_node_id, generics, impl_trait_inputs, @@ -1585,7 +1553,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } else { self.lower_opaque_impl_trait( span, - origin, + *origin, def_node_id, generics, impl_trait_inputs, @@ -1595,7 +1563,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } ImplTraitContext::TypeAliasesOpaqueTy => { - let nested_itctx = ImplTraitContext::TypeAliasesOpaqueTy; + let mut nested_itctx = ImplTraitContext::TypeAliasesOpaqueTy; self.lower_opaque_impl_trait( span, hir::OpaqueTyOrigin::TyAlias, @@ -1603,7 +1571,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &Generics::default(), &Vec::new(), bounds, - nested_itctx, + &mut nested_itctx, ) } ImplTraitContext::Universal { apit_nodes } => { @@ -1678,7 +1646,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ast_generics: &'itctx Generics, impl_trait_inputs: &Vec<&Ty>, bounds: &'itctx GenericBounds, - mut itctx: ImplTraitContext<'_, 'itctx>, + itctx: &mut ImplTraitContext<'_, 'itctx>, ) -> hir::TyKind<'hir> where 'a: 'itctx, @@ -1831,7 +1799,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Then when we lower the param bounds, references to 'a are remapped to 'a1, so we // get back Debug + 'a1, which is suitable for use on the TAIT. - let hir_bounds = lctx.lower_param_bounds(bounds, itctx.reborrow()); + let hir_bounds = lctx.lower_param_bounds(bounds, itctx); debug!(?hir_bounds); let generic_defs = lifetime_defs @@ -1854,7 +1822,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { param.id, ¶m.kind, ¶m.bounds, - itctx.reborrow(), + itctx, hir::PredicateOrigin::GenericParam, ) }) @@ -2082,12 +2050,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { if fn_node_id.is_some() { self.lower_ty_direct( ¶m.ty, - ImplTraitContext::Universal { apit_nodes: &mut impl_trait_inputs }, + &mut ImplTraitContext::Universal { apit_nodes: &mut impl_trait_inputs }, ) } else { self.lower_ty_direct( ¶m.ty, - ImplTraitContext::Disallowed(match kind { + &mut ImplTraitContext::Disallowed(match kind { FnDeclKind::Fn | FnDeclKind::Inherent => { unreachable!("fn should allow in-band lifetimes") } @@ -2110,7 +2078,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } else { match decl.output { FnRetTy::Ty(ref ty) => { - let context = match fn_node_id { + let mut context = match fn_node_id { Some(fn_node_id) if kind.impl_trait_return_allowed() => { let fn_def_id = self.local_def_id(fn_node_id); ImplTraitContext::ReturnPositionOpaqueTy { @@ -2131,7 +2099,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { FnDeclKind::Impl => ImplTraitPosition::ImplReturn, }), }; - hir::FnRetTy::Return(self.lower_ty(ty, context)) + hir::FnRetTy::Return(self.lower_ty(ty, &mut context)) } FnRetTy::Default(span) => hir::FnRetTy::DefaultReturn(self.lower_span(span)), } @@ -2411,13 +2379,13 @@ 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 context = ImplTraitContext::ReturnPositionOpaqueTy { + let mut context = ImplTraitContext::ReturnPositionOpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), impl_trait_inputs: &mut Vec::new(), generics: &Generics::default(), parent_generics: None, }; - self.lower_ty(ty, context) + self.lower_ty(ty, &mut context) } FnRetTy::Default(ret_ty_span) => self.arena.alloc(self.ty_tup(*ret_ty_span, &[])), }; @@ -2443,7 +2411,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_param_bound<'itctx>( &mut self, tpb: &'itctx GenericBound, - itctx: ImplTraitContext<'_, 'itctx>, + itctx: &mut ImplTraitContext<'_, 'itctx>, ) -> hir::GenericBound<'hir> where 'a: 'itctx, @@ -2561,7 +2529,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { GenericParamKind::Type { ref default, .. } => { let kind = hir::GenericParamKind::Type { default: default.as_ref().map(|x| { - self.lower_ty(x, ImplTraitContext::Disallowed(ImplTraitPosition::Type)) + self.lower_ty(x, &mut ImplTraitContext::Disallowed(ImplTraitPosition::Type)) }), synthetic: false, }; @@ -2569,7 +2537,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { (hir::ParamName::Plain(self.lower_ident(param.ident)), kind) } GenericParamKind::Const { ref ty, kw_span: _, ref default } => { - let ty = self.lower_ty(&ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + let ty = + self.lower_ty(&ty, &mut ImplTraitContext::Disallowed(ImplTraitPosition::Type)); let default = default.as_ref().map(|def| self.lower_anon_const(def)); ( hir::ParamName::Plain(self.lower_ident(param.ident)), @@ -2582,7 +2551,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_trait_ref<'itctx>( &mut self, p: &'itctx TraitRef, - itctx: ImplTraitContext<'_, 'itctx>, + itctx: &mut ImplTraitContext<'_, 'itctx>, ) -> hir::TraitRef<'hir> where 'a: 'itctx, @@ -2598,7 +2567,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_poly_trait_ref<'itctx>( &mut self, p: &'itctx PolyTraitRef, - itctx: ImplTraitContext<'_, 'itctx>, + itctx: &mut ImplTraitContext<'_, 'itctx>, ) -> hir::PolyTraitRef<'hir> where 'a: 'itctx, @@ -2616,7 +2585,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_mt<'itctx>( &mut self, mt: &'itctx MutTy, - itctx: ImplTraitContext<'_, 'itctx>, + itctx: &mut ImplTraitContext<'_, 'itctx>, ) -> hir::MutTy<'hir> where 'a: 'itctx, @@ -2625,10 +2594,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } #[tracing::instrument(level = "debug", skip(self))] - fn lower_param_bounds<'itctx>( + fn lower_param_bounds<'b, 'itctx>( &mut self, bounds: &'itctx [GenericBound], - itctx: ImplTraitContext<'_, 'itctx>, + itctx: &'b mut ImplTraitContext<'_, 'itctx>, ) -> hir::GenericBounds<'hir> where 'a: 'itctx, @@ -2636,15 +2605,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.arena.alloc_from_iter(self.lower_param_bounds_mut(bounds, itctx)) } - fn lower_param_bounds_mut<'s, 'itctx>( + fn lower_param_bounds_mut<'s, 'b, 'c, 'itctx>( &'s mut self, bounds: &'itctx [GenericBound], - mut itctx: ImplTraitContext<'s, 'itctx>, - ) -> impl Iterator> + Captures<'s> + Captures<'a> + Captures<'itctx> + itctx: &'b mut ImplTraitContext<'c, 'itctx>, + ) -> impl Iterator> + + Captures<'s> + + Captures<'b> + + Captures<'c> + + Captures<'a> + + Captures<'itctx> where 'a: 'itctx, { - bounds.iter().map(move |bound| self.lower_param_bound(bound, itctx.reborrow())) + bounds.iter().map(move |bound| self.lower_param_bound(bound, itctx)) } #[tracing::instrument(level = "debug", skip(self))] @@ -2673,7 +2647,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { node_id, &GenericParamKind::Type { default: None }, bounds, - ImplTraitContext::Universal { apit_nodes: &mut Vec::new() }, + &mut ImplTraitContext::Universal { apit_nodes: &mut Vec::new() }, hir::PredicateOrigin::ImplTrait, ); diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index 1efa19a3a8286..eeb1f66b41148 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -37,7 +37,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself, path, ParamMode::Optional, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple struct"); break hir::PatKind::TupleStruct(qpath, pats, ddpos); @@ -53,7 +53,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself, path, ParamMode::Optional, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); break hir::PatKind::Path(qpath); } @@ -63,7 +63,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself, path, ParamMode::Optional, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); let fs = self.arena.alloc_from_iter(fields.iter().map(|f| { diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 1f6e10c46fbb2..9e5103748e346 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -22,13 +22,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself: &'itctx Option, p: &'itctx Path, param_mode: ParamMode, - mut itctx: ImplTraitContext<'_, 'itctx>, + itctx: &mut ImplTraitContext<'_, 'itctx>, ) -> hir::QPath<'hir> where 'a: 'itctx, { let qself_position = qself.as_ref().map(|q| q.position); - let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx.reborrow())); + let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx)); let partial_res = self.resolver.get_partial_res(id).unwrap_or_else(|| PartialRes::new(Res::Err)); @@ -73,7 +73,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { segment, param_mode, parenthesized_generic_args, - itctx.reborrow(), + itctx, ) }, )), @@ -119,7 +119,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { segment, param_mode, ParenthesizedGenericArgs::Err, - itctx.reborrow(), + itctx, )); let qpath = hir::QPath::TypeRelative(ty, hir_segment); @@ -159,7 +159,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { segment, param_mode, ParenthesizedGenericArgs::Err, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Path), ) })), span: self.lower_span(p.span), @@ -183,7 +183,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { segment: &'itctx PathSegment, param_mode: ParamMode, parenthesized_generic_args: ParenthesizedGenericArgs, - itctx: ImplTraitContext<'_, 'itctx>, + itctx: &mut ImplTraitContext<'_, 'itctx>, ) -> hir::PathSegment<'hir> where 'a: 'itctx, @@ -315,7 +315,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, data: &'itctx AngleBracketedArgs, param_mode: ParamMode, - mut itctx: ImplTraitContext<'_, 'itctx>, + itctx: &mut ImplTraitContext<'_, 'itctx>, ) -> (GenericArgsCtor<'hir>, bool) where 'a: 'itctx, @@ -329,14 +329,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .args .iter() .filter_map(|arg| match arg { - AngleBracketedArg::Arg(arg) => Some(self.lower_generic_arg(arg, itctx.reborrow())), + AngleBracketedArg::Arg(arg) => Some(self.lower_generic_arg(arg, itctx)), AngleBracketedArg::Constraint(_) => None, }) .collect(); let bindings = self.arena.alloc_from_iter(data.args.iter().filter_map(|arg| match arg { - AngleBracketedArg::Constraint(c) => { - Some(self.lower_assoc_ty_constraint(c, itctx.reborrow())) - } + AngleBracketedArg::Constraint(c) => Some(self.lower_assoc_ty_constraint(c, itctx)), AngleBracketedArg::Arg(_) => None, })); let ctor = GenericArgsCtor { args, bindings, parenthesized: false, span: data.span }; @@ -354,12 +352,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // we generally don't permit such things (see #51008). let ParenthesizedArgs { span, inputs, inputs_span, output } = data; let inputs = self.arena.alloc_from_iter(inputs.iter().map(|ty| { - self.lower_ty_direct(ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitParam)) + self.lower_ty_direct( + ty, + &mut ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitParam), + ) })); let output_ty = match output { - FnRetTy::Ty(ty) => { - self.lower_ty(&ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn)) - } + FnRetTy::Ty(ty) => self + .lower_ty(&ty, &mut ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn)), FnRetTy::Default(_) => self.arena.alloc(self.ty_tup(*span, &[])), }; let args = smallvec![GenericArg::Type(self.ty_tup(*inputs_span, inputs))]; From bab1d54efc975d54a8d58839e51cf93ac82c0583 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 25 Aug 2022 11:53:32 -0300 Subject: [PATCH 40/53] Pass generics info from context down to the inner rpits on async fns --- compiler/rustc_ast_lowering/src/lib.rs | 55 ++++++++++++++------------ 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 38dd63c0c3f86..579d7e9fcc21d 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2070,11 +2070,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { })); let output = if let Some(ret_id) = make_ret_async { - self.lower_async_fn_ret_ty( - &decl.output, - fn_node_id.expect("`make_ret_async` but no `fn_def_id`"), - ret_id, - ) + let fn_node_id = fn_node_id.expect("`make_ret_async` but no `fn_def_id`"); + let fn_def_id = self.local_def_id(fn_node_id); + + // Not `OpaqueTyOrigin::AsyncFn`: that's only used for the + // `impl Future` opaque type that `async fn` implicitly + // generates. + let mut output_itctx = ImplTraitContext::ReturnPositionOpaqueTy { + origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), + impl_trait_inputs: &impl_trait_inputs, + generics, + parent_generics, + }; + + self.lower_async_fn_ret_ty(&decl.output, fn_node_id, ret_id, &mut output_itctx) } else { match decl.output { FnRetTy::Ty(ref ty) => { @@ -2145,12 +2154,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // `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( + fn lower_async_fn_ret_ty<'itctx>( &mut self, - output: &FnRetTy, + output: &'itctx FnRetTy, fn_node_id: NodeId, opaque_ty_node_id: NodeId, - ) -> hir::FnRetTy<'hir> { + output_itctx: &mut ImplTraitContext<'_, 'itctx>, + ) -> hir::FnRetTy<'hir> + where + 'a: 'itctx, + { let span = output.span(); let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::Async, span, None); @@ -2277,7 +2290,7 @@ 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); + this.lower_async_fn_output_type_to_future_bound(output, span, output_itctx); let generic_params = this.arena.alloc_from_iter(collected_lifetimes.iter().map( |&(new_node_id, lifetime, _)| { @@ -2367,26 +2380,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } /// Transforms `-> T` into `Future`. - fn lower_async_fn_output_type_to_future_bound( + fn lower_async_fn_output_type_to_future_bound<'itctx>( &mut self, - output: &FnRetTy, - fn_def_id: LocalDefId, + output: &'itctx FnRetTy, span: Span, - ) -> hir::GenericBound<'hir> { + output_itctx: &mut ImplTraitContext<'_, 'itctx>, + ) -> hir::GenericBound<'hir> + where + 'a: 'itctx, + { // Compute the `T` in `Future` from the return type. let output_ty = match output { - FnRetTy::Ty(ty) => { - // 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), - impl_trait_inputs: &mut Vec::new(), - generics: &Generics::default(), - parent_generics: None, - }; - self.lower_ty(ty, &mut context) - } + FnRetTy::Ty(ty) => self.lower_ty(ty, output_itctx), FnRetTy::Default(ret_ty_span) => self.arena.alloc(self.ty_tup(*ret_ty_span, &[])), }; From a19d07e6c0efb864143d43b746ed04b987c497e4 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 24 Aug 2022 16:48:08 -0300 Subject: [PATCH 41/53] Push apit nodes before lowering generics and bounds --- compiler/rustc_ast_lowering/src/lib.rs | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 579d7e9fcc21d..4e9f7d503a07e 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1577,13 +1577,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ImplTraitContext::Universal { apit_nodes } => { let span = t.span; let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span); - let (param, bounds, path) = - self.lower_generic_and_bounds(def_node_id, span, ident, bounds); + apit_nodes.push(t); + let (param, bounds, path) = self.lower_generic_and_bounds( + def_node_id, + span, + ident, + bounds, + apit_nodes, + ); self.impl_trait_defs.push(param); if let Some(bounds) = bounds { self.impl_trait_bounds.push(bounds); } - apit_nodes.push(t); path } ImplTraitContext::Disallowed(position) => { @@ -1785,7 +1790,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let ident = Ident::from_str_and_span(&pprust::ty_to_string(ty), span); // FIXME: unsure if this is going to work or do we need to first create all // the def_ids and then call this lower_generic_and_bounds method - lctx.lower_generic_and_bounds(node_id, span, ident, bounds) + lctx.lower_generic_and_bounds(node_id, span, ident, bounds, &mut Vec::new()) } else { unreachable!( "impl_trait_inputs contains {:?} which is not TyKind::ImplTrait(..)", @@ -2627,13 +2632,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } #[tracing::instrument(level = "debug", skip(self))] - fn lower_generic_and_bounds( + fn lower_generic_and_bounds<'itctx>( &mut self, node_id: NodeId, span: Span, ident: Ident, - bounds: &[GenericBound], - ) -> (hir::GenericParam<'hir>, Option>, hir::TyKind<'hir>) { + bounds: &'itctx [GenericBound], + apit_nodes: &mut Vec<&'itctx Ty>, + ) -> (hir::GenericParam<'hir>, Option>, hir::TyKind<'hir>) + where + 'a: 'itctx, + { // Add a definition for the in-band `Param`. let def_id = self.local_def_id(node_id); @@ -2652,7 +2661,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { node_id, &GenericParamKind::Type { default: None }, bounds, - &mut ImplTraitContext::Universal { apit_nodes: &mut Vec::new() }, + &mut ImplTraitContext::Universal { apit_nodes }, hir::PredicateOrigin::ImplTrait, ); From 679293af7baefec7c8d449f1716c23cc377f942d Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 31 Aug 2022 19:18:21 -0300 Subject: [PATCH 42/53] Do not create new defs and remaps when lowering Universal inside RPITs --- compiler/rustc_ast_lowering/src/lib.rs | 47 +++++++++++++------ compiler/rustc_passes/src/hir_id_validator.rs | 2 +- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 4e9f7d503a07e..8b39a0329dd7a 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -278,7 +278,11 @@ enum ImplTraitContext<'b, 'itctx> { /// equivalent to a fresh universal parameter like `fn foo(x: T)`. /// /// Newly generated parameters should be inserted into the given `Vec`. - Universal { apit_nodes: &'b mut Vec<&'itctx Ty> }, + Universal { + apit_nodes: &'b mut Vec<&'itctx Ty>, + }, + + UniversalInRPIT, /// Treat `impl Trait` as shorthand for a new opaque type. /// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually @@ -726,6 +730,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let local_id = self.item_local_id_counter; let hir_id = hir::HirId { owner, local_id }; + debug!("hir_id created: {:?} from {:?} via `lower_node_id`", hir_id, ast_node_id); + v.insert(local_id); self.item_local_id_counter.increment_by(1); @@ -750,6 +756,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let owner = self.current_hir_id_owner; let local_id = self.item_local_id_counter; assert_ne!(local_id, hir::ItemLocalId::new(0)); + debug!("hir_id created: {:?} via `next_id`", hir::HirId { owner, local_id }); + self.item_local_id_counter.increment_by(1); hir::HirId { owner, local_id } } @@ -1578,19 +1586,28 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let span = t.span; let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span); apit_nodes.push(t); - let (param, bounds, path) = self.lower_generic_and_bounds( - def_node_id, - span, - ident, - bounds, - apit_nodes, - ); + let (param, bounds, path) = + self.lower_generic_and_bounds(def_node_id, span, ident, bounds, itctx); self.impl_trait_defs.push(param); if let Some(bounds) = bounds { self.impl_trait_bounds.push(bounds); } path } + ImplTraitContext::UniversalInRPIT => { + let span = t.span; + let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span); + let def_id = self.local_def_id(def_node_id); + + hir::TyKind::Path(hir::QPath::Resolved( + None, + self.arena.alloc(hir::Path { + span: self.lower_span(span), + res: Res::Def(DefKind::TyParam, def_id.to_def_id()), + segments: arena_vec![self; hir::PathSegment::from_ident(self.lower_ident(ident))], + }), + )) + } ImplTraitContext::Disallowed(position) => { self.tcx.sess.emit_err(MisplacedImplTrait { span: t.span, @@ -1699,9 +1716,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { lctx.create_generic_defs(opaque_ty_def_id, &ast_generics.params, &mut new_remapping); debug!(?new_remapping); + debug!("impl_trait_inputs = {:#?}", impl_trait_inputs); for ty in impl_trait_inputs { - if let TyKind::ImplTrait(node_id, _) = ty.kind { - let old_def_id = lctx.local_def_id(node_id); + if let TyKind::ImplTrait(node_id, _) = &ty.kind { + let old_def_id = lctx.local_def_id(*node_id); let node_id = lctx.next_node_id(); // Add a definition for the generic param def. @@ -1784,13 +1802,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { Vec<_>, Vec<_>, ) = itertools::multiunzip(impl_trait_inputs.iter().map(|ty| { + debug!("lowering impl trait input {:?}", ty); // FIXME if let TyKind::ImplTrait(node_id, ref bounds) = ty.kind { let span = ty.span; let ident = Ident::from_str_and_span(&pprust::ty_to_string(ty), span); - // FIXME: unsure if this is going to work or do we need to first create all - // the def_ids and then call this lower_generic_and_bounds method - lctx.lower_generic_and_bounds(node_id, span, ident, bounds, &mut Vec::new()) + lctx.lower_generic_and_bounds(node_id, span, ident, bounds, &mut ImplTraitContext::UniversalInRPIT) } else { unreachable!( "impl_trait_inputs contains {:?} which is not TyKind::ImplTrait(..)", @@ -2638,7 +2655,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: Span, ident: Ident, bounds: &'itctx [GenericBound], - apit_nodes: &mut Vec<&'itctx Ty>, + itctx: &mut ImplTraitContext<'_, 'itctx>, ) -> (hir::GenericParam<'hir>, Option>, hir::TyKind<'hir>) where 'a: 'itctx, @@ -2661,7 +2678,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { node_id, &GenericParamKind::Type { default: None }, bounds, - &mut ImplTraitContext::Universal { apit_nodes }, + itctx, hir::PredicateOrigin::ImplTrait, ); diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs index 212ea9e57a37b..3bb8c0bb48c5f 100644 --- a/compiler/rustc_passes/src/hir_id_validator.rs +++ b/compiler/rustc_passes/src/hir_id_validator.rs @@ -103,7 +103,7 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> { self.error(|| { format!( "ItemLocalIds not assigned densely in {}. \ - Max ItemLocalId = {}, missing IDs = {:?}; seens IDs = {:?}", + Max ItemLocalId = {}, missing IDs = {:#?}; seens IDs = {:#?}", self.hir_map.def_path(owner).to_string_no_crate_verbose(), max, missing_items, From be9820749df87c3902b28c564b6a35cf88e22a3a Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 31 Aug 2022 22:39:40 -0300 Subject: [PATCH 43/53] Only create def and remap on lower_lifetime_binder for RPITs and not for async --- compiler/rustc_ast_lowering/src/expr.rs | 98 ++++++++++++++----------- compiler/rustc_ast_lowering/src/lib.rs | 15 ++-- 2 files changed, 64 insertions(+), 49 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 6ab12a72b442a..3e8ffccb2b6e1 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -849,29 +849,34 @@ impl<'hir> LoweringContext<'_, 'hir> { (body_id, generator_option) }); - 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, - &Generics::default(), - None, - None, - ); + self.lower_lifetime_binder( + closure_id, + generic_params, + false, + |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, + &Generics::default(), + None, + None, + ); - let c = lctx.arena.alloc(hir::Closure { - binder: binder_clause, - capture_clause, - bound_generic_params, - fn_decl, - body: body_id, - fn_decl_span: lctx.lower_span(fn_decl_span), - movability: generator_option, - }); + let c = lctx.arena.alloc(hir::Closure { + binder: binder_clause, + capture_clause, + bound_generic_params, + fn_decl, + body: body_id, + fn_decl_span: lctx.lower_span(fn_decl_span), + movability: generator_option, + }); - hir::ExprKind::Closure(c) - }) + hir::ExprKind::Closure(c) + }, + ) } fn generator_movability_for_fn( @@ -958,30 +963,35 @@ impl<'hir> LoweringContext<'_, 'hir> { body_id }); - self.lower_lifetime_binder(closure_id, generic_params, |lctx, bound_generic_params| { - // 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, - &Generics::default(), - None, - None, - ); + self.lower_lifetime_binder( + closure_id, + generic_params, + false, + |lctx, bound_generic_params| { + // 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, + &Generics::default(), + None, + None, + ); - let c = lctx.arena.alloc(hir::Closure { - binder: binder_clause, - capture_clause, - bound_generic_params, - fn_decl, - body, - fn_decl_span: lctx.lower_span(fn_decl_span), - movability: None, - }); - hir::ExprKind::Closure(c) - }) + let c = lctx.arena.alloc(hir::Closure { + binder: binder_clause, + capture_clause, + bound_generic_params, + fn_decl, + body, + fn_decl_span: lctx.lower_span(fn_decl_span), + movability: None, + }); + hir::ExprKind::Closure(c) + }, + ) } /// Destructure the LHS of complex assignments. diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 8b39a0329dd7a..9839994a140d3 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -982,6 +982,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, binder: NodeId, generic_params: &[GenericParam], + copy_generics: bool, in_binder: impl FnOnce(&mut Self, &'hir [hir::GenericParam<'hir>]) -> R, ) -> R { let mut new_remapping = FxHashMap::default(); @@ -999,7 +1000,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } - if !self.resolver.generics_def_id_map.is_empty() { + if copy_generics { for old_node_id in generic_params.iter().map(|param| param.id) { let old_def_id = self.local_def_id(old_node_id); let node_id = self.next_node_id(); @@ -1453,8 +1454,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let lifetime = self.lower_lifetime(®ion); hir::TyKind::Rptr(lifetime, self.lower_mt(mt, itctx)) } - TyKind::BareFn(ref f) => { - self.lower_lifetime_binder(t.id, &f.generic_params, |lctx, generic_params| { + TyKind::BareFn(ref f) => self.lower_lifetime_binder( + t.id, + &f.generic_params, + matches!(itctx, ImplTraitContext::ReturnPositionOpaqueTy { .. }), + |lctx, generic_params| { hir::TyKind::BareFn(lctx.arena.alloc(hir::BareFnTy { generic_params, unsafety: lctx.lower_unsafety(f.unsafety), @@ -1477,8 +1481,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ), param_names: lctx.lower_fn_params_to_names(&f.decl), })) - }) - } + }, + ), TyKind::Never => hir::TyKind::Never, TyKind::Tup(ref tys) => hir::TyKind::Tup( self.arena.alloc_from_iter(tys.iter().map(|ty| self.lower_ty_direct(ty, itctx))), @@ -2602,6 +2606,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.lower_lifetime_binder( p.trait_ref.ref_id, &p.bound_generic_params, + matches!(itctx, ImplTraitContext::ReturnPositionOpaqueTy { .. }), |lctx, bound_generic_params| { let trait_ref = lctx.lower_trait_ref(&p.trait_ref, itctx); hir::PolyTraitRef { bound_generic_params, trait_ref, span: lctx.lower_span(p.span) } From f16d7fec7dd4ee6ce1f93161307fa9bd749dbda8 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 1 Sep 2022 19:22:41 -0300 Subject: [PATCH 44/53] Ignore where-clauses wf checks for RPITs they are kinda bogus --- compiler/rustc_ast_lowering/src/block.rs | 7 ++--- .../rustc_infer/src/infer/outlives/verify.rs | 3 ++ compiler/rustc_middle/src/ty/mod.rs | 7 ++--- .../rustc_trait_selection/src/traits/wf.rs | 29 +++++++++++++++++-- compiler/rustc_ty_utils/src/ty.rs | 4 +-- compiler/rustc_typeck/src/astconv/mod.rs | 6 +++- 6 files changed, 41 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs index 7ed92c9688863..7465706d1a9bb 100644 --- a/compiler/rustc_ast_lowering/src/block.rs +++ b/compiler/rustc_ast_lowering/src/block.rs @@ -84,10 +84,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } fn lower_local(&mut self, l: &Local) -> &'hir hir::Local<'hir> { - let ty = l - .ty - .as_ref() - .map(|t| self.lower_ty(t, &mut ImplTraitContext::Disallowed(ImplTraitPosition::Variable))); + let ty = l.ty.as_ref().map(|t| { + self.lower_ty(t, &mut ImplTraitContext::Disallowed(ImplTraitPosition::Variable)) + }); let init = l.kind.init().map(|init| self.lower_expr(init)); let hir_id = self.lower_node_id(l.id); let pat = self.lower_pat(&l.pat); diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs index c7d7ef40d9d41..9187ca39c7fbd 100644 --- a/compiler/rustc_infer/src/infer/outlives/verify.rs +++ b/compiler/rustc_infer/src/infer/outlives/verify.rs @@ -57,6 +57,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { // environment. If the environment contains something like // `for<'a> T: 'a`, then we know that `T` outlives everything. let declared_bounds_from_env = self.declared_generic_bounds_from_env(param_ty); + debug!(?declared_bounds_from_env); let mut param_bounds = vec![]; for declared_bound in declared_bounds_from_env { let bound_region = declared_bound.map_bound(|outlives| outlives.1); @@ -65,6 +66,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { param_bounds.push(VerifyBound::OutlivedBy(region)); } else { // This is `for<'a> T: 'a`. This means that `T` outlives everything! All done here. + debug!("found that {param_ty:?} outlives any lifetime, returning empty vector"); return VerifyBound::AllBounds(vec![]); } } @@ -72,6 +74,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { // Add in the default bound of fn body that applies to all in // scope type parameters: if let Some(r) = self.implicit_region_bound { + debug!("adding implicit region bound of {r:?}"); param_bounds.push(VerifyBound::OutlivedBy(r)); } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 88793dac8f37a..7634b4e26dff0 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2393,14 +2393,11 @@ impl<'tcx> TyCtxt<'tcx> { } /// Yields the parent function's `LocalDefId` if `def_id` is an `impl Trait` definition. -pub fn is_impl_trait_defn(tcx: TyCtxt<'_>, def_id: DefId) -> Option { +pub fn impl_trait_origin(tcx: TyCtxt<'_>, def_id: DefId) -> Option { let def_id = def_id.as_local()?; if let Node::Item(item) = tcx.hir().get_by_def_id(def_id) { if let hir::ItemKind::OpaqueTy(ref opaque_ty) = item.kind { - return match opaque_ty.origin { - hir::OpaqueTyOrigin::AsyncFn(parent) => Some(parent), - hir::OpaqueTyOrigin::TyAlias | hir::OpaqueTyOrigin::FnReturn(_) => None, - }; + return Some(opaque_ty.origin); } } None diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index bb6009cb22a37..5c88339bfaf19 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -434,6 +434,7 @@ impl<'tcx> WfPredicates<'tcx> { } /// Pushes all the predicates needed to validate that `ty` is WF into `out`. + #[tracing::instrument(level = "debug", skip(self))] fn compute(&mut self, arg: GenericArg<'tcx>) { let mut walker = arg.walk(); let param_env = self.param_env; @@ -488,6 +489,8 @@ impl<'tcx> WfPredicates<'tcx> { } }; + debug!("wf bounds for ty={:?} ty.kind={:#?}", ty, ty.kind()); + match *ty.kind() { ty::Bool | ty::Char @@ -628,9 +631,29 @@ impl<'tcx> WfPredicates<'tcx> { // All of the requirements on type parameters // have already been checked for `impl Trait` in // return position. We do need to check type-alias-impl-trait though. - if ty::is_impl_trait_defn(self.tcx, did).is_none() { - let obligations = self.nominal_obligations(did, substs); - self.out.extend(obligations); + debug!( + "ty::Opaque(did={did:?}, substs={substs:?}, impl_trait_origin={:?}", + ty::impl_trait_origin(self.tcx, did) + ); + match ty::impl_trait_origin(self.tcx, did) { + Some(hir::OpaqueTyOrigin::TyAlias) => { + let obligations = self.nominal_obligations(did, substs); + debug!("opaque obligations = {:#?}", obligations); + self.out.extend(obligations); + } + Some(hir::OpaqueTyOrigin::AsyncFn(_)) + | Some(hir::OpaqueTyOrigin::FnReturn(_)) + | None => { + // for opaque types introduced via `-> impl Trait` or async fn desugaring, + // the where-clauses are currently kinda bogus so we skip them. + // + // These opaque type references only appear in 1 place (the fn return type) + // and we know they are well-formed in that location if the fn's where-clauses are met. + // + // The only other place this type will propagate to is the return type of a fn call, + // and it of course must satisfy the fn where clauses, so we know the type will be well-formed + // in that context as well.\ + } } } diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 9d640672cf92c..3cc957ed2fd55 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -106,7 +106,7 @@ fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AdtSizedConstrain /// See `ParamEnv` struct definition for details. fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { // The param_env of an impl Trait type is its defining function's param_env - if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) { + if let Some(hir::OpaqueTyOrigin::AsyncFn(parent)) = ty::impl_trait_origin(tcx, def_id) { return param_env(tcx, parent.to_def_id()); } // Compute the bounds on Self and the type parameters. @@ -235,7 +235,7 @@ fn well_formed_types_in_env<'tcx>( debug!("environment(def_id = {:?})", def_id); // The environment of an impl Trait type is its defining function's environment. - if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) { + if let Some(hir::OpaqueTyOrigin::AsyncFn(parent)) = ty::impl_trait_origin(tcx, def_id) { return well_formed_types_in_env(tcx, parent.to_def_id()); } diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 859ed31dcbc0b..5f30e3dc1013f 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -2362,7 +2362,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { match path.res { Res::Def(DefKind::OpaqueTy, did) => { // Check for desugared `impl Trait`. - assert!(ty::is_impl_trait_defn(tcx, did).is_none()); + assert!(matches!( + ty::impl_trait_origin(tcx, did), + None | Some(hir::OpaqueTyOrigin::FnReturn(_)) + | Some(hir::OpaqueTyOrigin::TyAlias) + )); let item_segment = path.segments.split_last().unwrap(); self.prohibit_generics(item_segment.1.iter(), |err| { err.note("`impl Trait` types can't have type parameters"); From 7200539552e1463989d05b1423949bbcc73733df Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 25 Aug 2022 12:00:47 -0300 Subject: [PATCH 45/53] Bless impl-trait-captures test as the output is better now --- src/test/ui/nll/ty-outlives/impl-trait-captures.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr b/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr index 330c6fafa2d61..1a699edcf5899 100644 --- a/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr +++ b/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr @@ -1,4 +1,4 @@ -error[E0700]: hidden type for `Opaque(DefId(0:11 ~ impl_trait_captures[1afc]::foo::{opaque#0}), [ReStatic, T, ReEarlyBound(0, 'a)])` captures lifetime that does not appear in bounds +error[E0700]: hidden type for `Opaque(DefId(0:11 ~ impl_trait_captures[1afc]::foo::{opaque#0}), [ReEarlyBound(0, 'a), T])` captures lifetime that does not appear in bounds --> $DIR/impl-trait-captures.rs:11:5 | LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> { From a4356eeb02abc21631bb2df489b26409a5d303a7 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 2 Sep 2022 11:15:40 -0300 Subject: [PATCH 46/53] Bless async test --- src/test/ui/chalkify/bugs/async.stderr | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/test/ui/chalkify/bugs/async.stderr b/src/test/ui/chalkify/bugs/async.stderr index f53ed53f73c49..2a8aa94deae02 100644 --- a/src/test/ui/chalkify/bugs/async.stderr +++ b/src/test/ui/chalkify/bugs/async.stderr @@ -28,12 +28,21 @@ note: required by a bound in `std::future::from_generator` LL | T: Generator, | ^^^^^^^^^^ required by this bound in `std::future::from_generator` +error: the type `impl Future` is not well-formed (chalk) + --> $DIR/async.rs:7:29 + | +LL | async fn foo(x: u32) -> u32 { + | _____________________________^ +LL | | x +LL | | } + | |_^ + error[E0280]: the requirement ` as Future>::Output == u32` is not satisfied --> $DIR/async.rs:7:25 | LL | async fn foo(x: u32) -> u32 { | ^^^ -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0277`. From 0791f8de2d59936c5a928ad9cd4a7b2980559ea2 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 25 Aug 2022 13:28:51 -0300 Subject: [PATCH 47/53] Bless bound-normalization-fail test --- src/test/ui/impl-trait/bound-normalization-fail.rs | 5 ++--- .../ui/impl-trait/bound-normalization-fail.stderr | 13 +++---------- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/src/test/ui/impl-trait/bound-normalization-fail.rs b/src/test/ui/impl-trait/bound-normalization-fail.rs index 3329592478d6f..88eea4551777d 100644 --- a/src/test/ui/impl-trait/bound-normalization-fail.rs +++ b/src/test/ui/impl-trait/bound-normalization-fail.rs @@ -23,7 +23,7 @@ mod impl_trait { /// `T::Assoc` can't be normalized any further here. fn foo_fail() -> impl FooLike { - //~^ ERROR: type mismatch + //~^ ERROR: type mismatch resolving ` as FooLike>::Output == ::Assoc` [E0271] Foo(()) } } @@ -39,8 +39,7 @@ mod lifetimes { /// Missing bound constraining `Assoc`, `T::Assoc` can't be normalized further. fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike { - //~^ ERROR `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope - //~| ERROR: type mismatch + //~^ ERROR: type mismatch resolving ` as FooLike>::Output == >::Assoc` [E0271] Foo(()) } } diff --git a/src/test/ui/impl-trait/bound-normalization-fail.stderr b/src/test/ui/impl-trait/bound-normalization-fail.stderr index bd8d3d3d24ece..fdaebf383df43 100644 --- a/src/test/ui/impl-trait/bound-normalization-fail.stderr +++ b/src/test/ui/impl-trait/bound-normalization-fail.stderr @@ -19,18 +19,12 @@ help: consider constraining the associated type `::Assoc LL | fn foo_fail>() -> impl FooLike { | ++++++++++++ -error[E0760]: `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope - --> $DIR/bound-normalization-fail.rs:41:41 - | -LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0271]: type mismatch resolving ` as FooLike>::Output == >::Assoc` --> $DIR/bound-normalization-fail.rs:41:41 | LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving ` as FooLike>::Output == >::Assoc` -... +LL | LL | Foo(()) | ------- return type was inferred to be `Foo<()>` here | @@ -46,7 +40,6 @@ help: consider constraining the associated type ` LL | fn foo2_fail<'a, T: Trait<'a, Assoc = ()>>() -> impl FooLike { | ++++++++++++ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0271, E0760. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0271`. From 8d53dc7caaf18e89a36ace0fe94e0296f889d2b9 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 2 Sep 2022 18:48:20 -0300 Subject: [PATCH 48/53] Avoid unneeded repeated code --- compiler/rustc_ast_lowering/src/lib.rs | 36 ++++++++++---------------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 9839994a140d3..8259411396125 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1550,29 +1550,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { generics, parent_generics, } => { - if let Some(parent_generics) = parent_generics { - let generics = - self.lowering_arena.gs.alloc(parent_generics.merge(generics)); - self.lower_opaque_impl_trait( - span, - *origin, - def_node_id, - generics, - impl_trait_inputs, - bounds, - itctx, - ) + let generics = if let Some(parent_generics) = parent_generics { + &*self.lowering_arena.gs.alloc(parent_generics.merge(generics)) } else { - self.lower_opaque_impl_trait( - span, - *origin, - def_node_id, - generics, - impl_trait_inputs, - bounds, - itctx, - ) - } + generics + }; + + self.lower_opaque_impl_trait( + span, + *origin, + def_node_id, + generics, + impl_trait_inputs, + bounds, + itctx, + ) } ImplTraitContext::TypeAliasesOpaqueTy => { let mut nested_itctx = ImplTraitContext::TypeAliasesOpaqueTy; From 49d057fa6d3d850ecdf37eddd3a568690e94eabf Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 2 Sep 2022 19:06:11 -0300 Subject: [PATCH 49/53] itertools is not needed anymore in rustc_ast_lowering --- Cargo.lock | 5 ++--- compiler/rustc_ast_lowering/Cargo.toml | 1 - compiler/rustc_ast_lowering/src/lib.rs | 11 ++++++----- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 47daaa030c201..f83678f0ca671 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1911,9 +1911,9 @@ dependencies = [ [[package]] name = "itertools" -version = "0.10.3" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" +checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf" dependencies = [ "either", ] @@ -3216,7 +3216,6 @@ dependencies = [ name = "rustc_ast_lowering" version = "0.0.0" dependencies = [ - "itertools", "rustc_arena", "rustc_ast", "rustc_ast_pretty", diff --git a/compiler/rustc_ast_lowering/Cargo.toml b/compiler/rustc_ast_lowering/Cargo.toml index a32968dd97d27..ce1c8d4997d74 100644 --- a/compiler/rustc_ast_lowering/Cargo.toml +++ b/compiler/rustc_ast_lowering/Cargo.toml @@ -7,7 +7,6 @@ edition = "2021" doctest = false [dependencies] -itertools = "0.10.3" rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 8259411396125..ef8ab43675466 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1793,24 +1793,25 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .collect(); debug!(?type_const_defs); - let (universal_params, universal_predicates, _): ( + let (universal_params, universal_predicates): ( Vec<_>, Vec<_>, - Vec<_>, - ) = itertools::multiunzip(impl_trait_inputs.iter().map(|ty| { + ) = impl_trait_inputs.iter().map(|ty| { debug!("lowering impl trait input {:?}", ty); // FIXME if let TyKind::ImplTrait(node_id, ref bounds) = ty.kind { let span = ty.span; let ident = Ident::from_str_and_span(&pprust::ty_to_string(ty), span); - lctx.lower_generic_and_bounds(node_id, span, ident, bounds, &mut ImplTraitContext::UniversalInRPIT) + + let (universal_params, universal_predicates, _) = lctx.lower_generic_and_bounds(node_id, span, ident, bounds, &mut ImplTraitContext::UniversalInRPIT); + (universal_params, universal_predicates) } else { unreachable!( "impl_trait_inputs contains {:?} which is not TyKind::ImplTrait(..)", ty.kind ); } - })); + }).unzip(); debug!(?universal_params); debug!(?universal_predicates); From 0fadeede0b5631fd13eb78fcd38e7ae1608e5f44 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 5 Sep 2022 16:24:01 -0300 Subject: [PATCH 50/53] Add debug_asserts back --- compiler/rustc_ast_lowering/src/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index ef8ab43675466..8b48837aa9422 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -611,6 +611,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let item = f(self); debug_assert_eq!(def_id, item.def_id()); + // `f` should have consumed all the elements in these vectors when constructing `item`. + debug_assert!(self.impl_trait_defs.is_empty()); + debug_assert!(self.impl_trait_bounds.is_empty()); let info = self.make_owner_info(item); self.attrs = current_attrs; From 835d7de9950804fa806aaf3ff6173b3299e99c43 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 5 Sep 2022 17:06:59 -0300 Subject: [PATCH 51/53] call lower_span before adding it to GenericArg::Type --- compiler/rustc_ast_lowering/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 8b48837aa9422..bce77a98afb25 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1903,13 +1903,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let universal_args: Vec<_> = impl_trait_inputs.iter().map(|ty| match ty.kind { TyKind::ImplTrait(node_id, _) => { let def_id = self.local_def_id(node_id); - let span = ty.span; + let span = self.lower_span(ty.span); let ident = Ident::from_str_and_span(&pprust::ty_to_string(ty), span); hir::GenericArg::Type(hir::Ty { hir_id: self.next_id(), span, kind: hir::TyKind::Path(hir::QPath::Resolved(None, self.arena.alloc(hir::Path { - span: self.lower_span(span), + span, res: Res::Def(DefKind::TyParam, def_id.to_def_id()), segments: arena_vec![self; hir::PathSegment::from_ident(self.lower_ident(ident))], }))) From 971641f5307c81f4eac7d48c252b783a23a83ba4 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 5 Sep 2022 17:19:33 -0300 Subject: [PATCH 52/53] Move itctx creation to outside loop --- compiler/rustc_ast_lowering/src/lib.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index bce77a98afb25..708c4e28ea950 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2068,12 +2068,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ast_inputs = &ast_inputs[..ast_inputs.len() - 1]; } let mut impl_trait_inputs = vec![]; + let mut itctx = ImplTraitContext::Universal { apit_nodes: &mut impl_trait_inputs }; let inputs = self.arena.alloc_from_iter(ast_inputs.iter().map(|param| { if fn_node_id.is_some() { - self.lower_ty_direct( - ¶m.ty, - &mut ImplTraitContext::Universal { apit_nodes: &mut impl_trait_inputs }, - ) + self.lower_ty_direct(¶m.ty, &mut itctx) } else { self.lower_ty_direct( ¶m.ty, From d45f1d3a83aedff4b4cca2611e8736d2dd916864 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 5 Sep 2022 17:39:00 -0300 Subject: [PATCH 53/53] Extend Rustdocs of lower_lifetime_binder --- compiler/rustc_ast_lowering/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 708c4e28ea950..8cba0b9f8623a 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -979,6 +979,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// name resolver owing to lifetime elision; this also populates the resolver's node-id->def-id /// map, so that later calls to `opt_node_id_to_def_id` that refer to these extra lifetime /// parameters will be successful. + /// Creating new definitions and remapping for `generic_params` if `copy_generics` is set to + /// `true`. This is used for RPITs. #[instrument(level = "debug", skip(self, in_binder))] #[inline] fn lower_lifetime_binder(