diff options
| author | Michael Goulet <michael@errs.io> | 2022-08-31 04:03:24 +0000 |
|---|---|---|
| committer | Michael Goulet <michael@errs.io> | 2022-09-09 01:31:44 +0000 |
| commit | d34cb98fb0bbaf86860b4ad5ff0c3d79b077f565 (patch) | |
| tree | 31f9a2b56052f3bfed4ee797ffca15678c985cb6 | |
| parent | 78b962a4f348c0b901d2eae9e5852cb3675b1233 (diff) | |
| download | rust-d34cb98fb0bbaf86860b4ad5ff0c3d79b077f565.tar.gz rust-d34cb98fb0bbaf86860b4ad5ff0c3d79b077f565.zip | |
Lower RPITIT to ImplTraitPlaceholder item
| -rw-r--r-- | compiler/rustc_ast_lowering/src/lib.rs | 47 | ||||
| -rw-r--r-- | compiler/rustc_feature/src/active.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_hir/src/target.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/error.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/sty.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/late/lifetimes.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_span/src/symbol.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/project.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_typeck/src/astconv/mod.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_typeck/src/collect.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_typeck/src/collect/item_bounds.rs | 28 |
11 files changed, 99 insertions, 8 deletions
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index f57c92fd70c..2e8fcd7dca4 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -255,6 +255,8 @@ enum ImplTraitContext { }, /// Impl trait in type aliases. TypeAliasesOpaqueTy, + /// Return-position `impl Trait` in trait definition + InTrait, /// `impl Trait` is not accepted in this position. Disallowed(ImplTraitPosition), } @@ -323,9 +325,17 @@ enum FnDeclKind { } impl FnDeclKind { - fn impl_trait_return_allowed(&self) -> bool { + fn impl_trait_return_allowed(&self, tcx: TyCtxt<'_>) -> bool { match self { FnDeclKind::Fn | FnDeclKind::Inherent => true, + FnDeclKind::Impl if tcx.features().return_position_impl_trait_in_trait => true, + _ => false, + } + } + + fn impl_trait_in_trait_allowed(&self, tcx: TyCtxt<'_>) -> bool { + match self { + FnDeclKind::Trait if tcx.features().return_position_impl_trait_in_trait => true, _ => false, } } @@ -1346,6 +1356,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut nested_itctx, ) } + ImplTraitContext::InTrait => { + // FIXME(RPITIT): Should we use def_node_id here? + self.lower_impl_trait_in_trait(span, def_node_id, bounds) + } ImplTraitContext::Universal => { let span = t.span; let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span); @@ -1532,6 +1546,32 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes) } + #[tracing::instrument(level = "debug", skip(self))] + fn lower_impl_trait_in_trait( + &mut self, + span: Span, + opaque_ty_node_id: NodeId, + bounds: &GenericBounds, + ) -> hir::TyKind<'hir> { + let opaque_ty_def_id = self.local_def_id(opaque_ty_node_id); + self.with_hir_id_owner(opaque_ty_node_id, |lctx| { + // FIXME(RPITIT): This should be a more descriptive ImplTraitPosition, i.e. nested RPITIT + // FIXME(RPITIT): We _also_ should support this eventually + let hir_bounds = lctx + .lower_param_bounds(bounds, ImplTraitContext::Disallowed(ImplTraitPosition::Trait)); + let rpitit_placeholder = hir::ImplTraitPlaceholder { bounds: hir_bounds }; + let rpitit_item = hir::Item { + def_id: opaque_ty_def_id, + ident: Ident::empty(), + kind: hir::ItemKind::ImplTraitPlaceholder(rpitit_placeholder), + span: lctx.lower_span(span), + vis_span: lctx.lower_span(span.shrink_to_lo()), + }; + hir::OwnerNode::Item(lctx.arena.alloc(rpitit_item)) + }); + hir::TyKind::ImplTraitInTrait(hir::ItemId { def_id: opaque_ty_def_id }) + } + /// Registers a new opaque type with the proper `NodeId`s and /// returns the lowered node-ID for the opaque type. fn generate_opaque_type( @@ -1690,12 +1730,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { match decl.output { FnRetTy::Ty(ref ty) => { let mut context = match fn_node_id { - Some(fn_node_id) if kind.impl_trait_return_allowed() => { + Some(fn_node_id) if kind.impl_trait_return_allowed(self.tcx) => { let fn_def_id = self.local_def_id(fn_node_id); ImplTraitContext::ReturnPositionOpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), } } + Some(_) if kind.impl_trait_in_trait_allowed(self.tcx) => { + ImplTraitContext::InTrait + } _ => ImplTraitContext::Disallowed(match kind { FnDeclKind::Fn | FnDeclKind::Inherent => { unreachable!("fn should allow in-band lifetimes") diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index f71b3d59e2c..3b8032040e7 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -487,6 +487,8 @@ declare_features! ( (incomplete, repr128, "1.16.0", Some(56071), None), /// Allows `repr(simd)` and importing the various simd intrinsics. (active, repr_simd, "1.4.0", Some(27731), None), + /// Allows return-position `impl Trait` in traits. + (incomplete, return_position_impl_trait_in_trait, "CURRENT_RUSTC_VERSION", Some(91611), None), /// Allows `extern "rust-cold"`. (active, rust_cold_cc, "1.63.0", Some(97544), None), /// Allows the use of SIMD types in functions declared in `extern` blocks. diff --git a/compiler/rustc_hir/src/target.rs b/compiler/rustc_hir/src/target.rs index ea23c48cc53..0e9b05729d2 100644 --- a/compiler/rustc_hir/src/target.rs +++ b/compiler/rustc_hir/src/target.rs @@ -105,6 +105,7 @@ impl Target { DefKind::GlobalAsm => Target::GlobalAsm, DefKind::TyAlias => Target::TyAlias, DefKind::OpaqueTy => Target::OpaqueTy, + DefKind::ImplTraitPlaceholder => Target::ImplTraitPlaceholder, DefKind::Enum => Target::Enum, DefKind::Struct => Target::Struct, DefKind::Union => Target::Union, diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index da564c66a70..279c8c8d6d1 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -2,6 +2,7 @@ use crate::traits::{ObligationCause, ObligationCauseCode}; use crate::ty::diagnostics::suggest_constraining_type_param; use crate::ty::print::{FmtPrinter, Printer}; use crate::ty::{self, BoundRegionKind, Region, Ty, TyCtxt}; +use hir::def::DefKind; use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect}; use rustc_errors::{pluralize, Diagnostic, MultiSpan}; use rustc_hir as hir; @@ -538,7 +539,7 @@ impl<T> Trait<T> for X { diag.span_label(p_span, "this type parameter"); } } - (ty::Projection(proj_ty), _) => { + (ty::Projection(proj_ty), _) if self.def_kind(proj_ty.item_def_id) != DefKind::ImplTraitPlaceholder => { self.expected_projection( diag, proj_ty, @@ -547,7 +548,7 @@ impl<T> Trait<T> for X { cause.code(), ); } - (_, ty::Projection(proj_ty)) => { + (_, ty::Projection(proj_ty)) if self.def_kind(proj_ty.item_def_id) != DefKind::ImplTraitPlaceholder => { let msg = format!( "consider constraining the associated type `{}` to `{}`", values.found, values.expected, diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 9fb91b5fe87..c5c5d347341 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -11,6 +11,7 @@ use crate::ty::{ TypeVisitor, }; use crate::ty::{List, ParamEnv}; +use hir::def::DefKind; use polonius_engine::Atom; use rustc_data_structures::captures::Captures; use rustc_data_structures::intern::Interned; @@ -1196,7 +1197,9 @@ pub struct ProjectionTy<'tcx> { impl<'tcx> ProjectionTy<'tcx> { pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId { - tcx.parent(self.item_def_id) + let parent = tcx.parent(self.item_def_id); + assert_eq!(tcx.def_kind(parent), DefKind::Trait); + parent } /// Extracts the underlying trait reference and own substs from this projection. diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index b72b033534b..e9e4f8fc483 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -597,7 +597,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } } hir::ItemKind::ImplTraitPlaceholder(..) => { - // FIXME(RPITIT): We don't need to do anything here, right? + // FIXME(RPITIT): We don't need to do anything special here, right? + intravisit::walk_item(self, item); } hir::ItemKind::TyAlias(_, ref generics) | hir::ItemKind::Enum(_, ref generics) diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 75b1dfc856a..4fd9e7407ce 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1183,6 +1183,7 @@ symbols! { require, residual, result, + return_position_impl_trait_in_trait, rhs, rintf32, rintf64, diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 8a093bf4281..cd6b42be5ad 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1465,6 +1465,11 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( obligation: &ProjectionTyObligation<'tcx>, candidate_set: &mut ProjectionCandidateSet<'tcx>, ) { + // Can't assemble candidate from impl for RPITIT + if selcx.tcx().def_kind(obligation.predicate.item_def_id) == DefKind::ImplTraitPlaceholder { + return; + } + // If we are resolving `<T as TraitRef<...>>::Item == Type`, // start out by selecting the predicate `T as TraitRef<...>`: let poly_trait_ref = ty::Binder::dummy(obligation.predicate.trait_ref(selcx.tcx())); diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 1f43221a420..6eec2c57639 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -2638,8 +2638,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i), } } - hir::TyKind::ImplTraitInTrait(..) => { - span_bug!(ast_ty.span, "not yet implemented") + hir::TyKind::ImplTraitInTrait(item_id) => { + let def_id = item_id.def_id.to_def_id(); + tcx.mk_projection(def_id, InternalSubsts::identity_for_item(tcx, def_id)) } hir::TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => { debug!(?qself, ?segment); diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 293a32051b9..5429598871d 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -1600,6 +1600,11 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { // inherit the generics of the item. Some(parent_id.to_def_id()) } + ItemKind::ImplTraitPlaceholder(_) => { + let parent_id = tcx.hir().get_parent_item(hir_id).to_def_id(); + assert_eq!(tcx.def_kind(parent_id), DefKind::AssocFn); + Some(parent_id) + } _ => None, }, _ => None, diff --git a/compiler/rustc_typeck/src/collect/item_bounds.rs b/compiler/rustc_typeck/src/collect/item_bounds.rs index 318e8f581f7..fe8d8f54f04 100644 --- a/compiler/rustc_typeck/src/collect/item_bounds.rs +++ b/compiler/rustc_typeck/src/collect/item_bounds.rs @@ -74,6 +74,29 @@ fn opaque_type_bounds<'tcx>( }) } +/// Opaque types don't inherit bounds from their parent: for return position +/// impl trait it isn't possible to write a suitable predicate on the +/// containing function and for type-alias impl trait we don't have a backwards +/// compatibility issue. +fn impl_trait_in_trait_item_bounds<'tcx>( + tcx: TyCtxt<'tcx>, + opaque_def_id: DefId, + ast_bounds: &'tcx [hir::GenericBound<'tcx>], + span: Span, +) -> &'tcx [(ty::Predicate<'tcx>, Span)] { + ty::print::with_no_queries!({ + // FIXME(RPITIT): DRY-er code please + let item_ty = + tcx.mk_projection(opaque_def_id, InternalSubsts::identity_for_item(tcx, opaque_def_id)); + + let icx = ItemCtxt::new(tcx, opaque_def_id); + let mut bounds = <dyn AstConv<'_>>::compute_bounds(&icx, item_ty, ast_bounds); + // RPITITs are implicitly sized unless a `?Sized` bound is found + <dyn AstConv<'_>>::add_implicitly_sized(&icx, &mut bounds, ast_bounds, None, span); + tcx.arena.alloc_from_iter(bounds.predicates(tcx, item_ty)) + }) +} + pub(super) fn explicit_item_bounds( tcx: TyCtxt<'_>, def_id: DefId, @@ -90,6 +113,11 @@ pub(super) fn explicit_item_bounds( span, .. }) => opaque_type_bounds(tcx, def_id, bounds, *span), + hir::Node::Item(hir::Item { + kind: hir::ItemKind::ImplTraitPlaceholder(hir::ImplTraitPlaceholder { bounds }), + span, + .. + }) => impl_trait_in_trait_item_bounds(tcx, def_id, bounds, *span), _ => bug!("item_bounds called on {:?}", def_id), } } |
