diff options
| author | bors <bors@rust-lang.org> | 2022-09-14 18:10:51 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-09-14 18:10:51 +0000 |
| commit | 6153d3cbe6abc74fb37e4ebe48cc825484fd6bbf (patch) | |
| tree | bef7759236490fe278aa160a8ac63f41d37ecd27 /compiler/rustc_middle/src | |
| parent | a92669638461836f41f54f95e396f9082bb91391 (diff) | |
| parent | 0faafbf1d91f7b9ea4c775cd33cf12008575a35b (diff) | |
| download | rust-6153d3cbe6abc74fb37e4ebe48cc825484fd6bbf.tar.gz rust-6153d3cbe6abc74fb37e4ebe48cc825484fd6bbf.zip | |
Auto merge of #101212 - eholk:dyn-star, r=compiler-errors
Initial implementation of dyn* This PR adds extremely basic and incomplete support for [dyn*](https://smallcultfollowing.com/babysteps//blog/2022/03/29/dyn-can-we-make-dyn-sized/). The goal is to get something in tree behind a flag to make collaboration easier, and also to make sure the implementation so far is not unreasonable. This PR does quite a few things: * Introduce `dyn_star` feature flag * Adds parsing for `dyn* Trait` types * Defines `dyn* Trait` as a sized type * Adds support for explicit casts, like `42usize as dyn* Debug` * Including const evaluation of such casts * Adds codegen for drop glue so things are cleaned up properly when a `dyn* Trait` object goes out of scope * Adds codegen for method calls, at least for methods that take `&self` Quite a bit is still missing, but this gives us a starting point. Note that this is never intended to become stable surface syntax for Rust, but rather `dyn*` is planned to be used as an implementation detail for async functions in dyn traits. Joint work with `@nikomatsakis` and `@compiler-errors.` r? `@bjorn3`
Diffstat (limited to 'compiler/rustc_middle/src')
| -rw-r--r-- | compiler/rustc_middle/src/mir/mod.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/mir/syntax.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/cast.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/context.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/diagnostics.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/flags.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/layout.rs | 47 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/mod.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/normalize_erasing_regions.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/print/pretty.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/relate.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/structural_impls.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/sty.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/walk.rs | 2 |
14 files changed, 88 insertions, 20 deletions
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 9a6d34c8ddd..526bb5d7285 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1818,6 +1818,7 @@ impl<'tcx> Rvalue<'tcx> { // While the model is undecided, we should be conservative. See // <https://www.ralfj.de/blog/2022/04/11/provenance-exposed.html> Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => false, + Rvalue::Cast(CastKind::DynStar, _, _) => false, Rvalue::Use(_) | Rvalue::CopyForDeref(_) diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 1f7643a76af..d2bb897b5b6 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1139,6 +1139,8 @@ pub enum CastKind { /// All sorts of pointer-to-pointer casts. Note that reference-to-raw-ptr casts are /// translated into `&raw mut/const *r`, i.e., they are not actually casts. Pointer(PointerCast), + /// Cast into a dyn* object. + DynStar, /// Remaining unclassified casts. Misc, } diff --git a/compiler/rustc_middle/src/ty/cast.rs b/compiler/rustc_middle/src/ty/cast.rs index c4b743dd467..981e2d3b6d2 100644 --- a/compiler/rustc_middle/src/ty/cast.rs +++ b/compiler/rustc_middle/src/ty/cast.rs @@ -33,6 +33,8 @@ pub enum CastTy<'tcx> { FnPtr, /// Raw pointers. Ptr(ty::TypeAndMut<'tcx>), + /// Casting into a `dyn*` value. + DynStar, } /// Cast Kind. See [RFC 401](https://rust-lang.github.io/rfcs/0401-coercions.html) @@ -50,6 +52,7 @@ pub enum CastKind { ArrayPtrCast, FnPtrPtrCast, FnPtrAddrCast, + DynStarCast, } impl<'tcx> CastTy<'tcx> { @@ -67,6 +70,7 @@ impl<'tcx> CastTy<'tcx> { ty::Adt(d, _) if d.is_enum() && d.is_payloadfree() => Some(CastTy::Int(IntTy::CEnum)), ty::RawPtr(mt) => Some(CastTy::Ptr(mt)), ty::FnPtr(..) => Some(CastTy::FnPtr), + ty::Dynamic(_, _, ty::DynStar) => Some(CastTy::DynStar), _ => None, } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 94eddef944a..d0b49c4ee9e 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -63,7 +63,7 @@ use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{Layout, LayoutS, TargetDataLayout, VariantIdx}; use rustc_target::spec::abi; use rustc_type_ir::sty::TyKind::*; -use rustc_type_ir::{InternAs, InternIteratorElement, Interner, TypeFlags}; +use rustc_type_ir::{DynKind, InternAs, InternIteratorElement, Interner, TypeFlags}; use std::any::Any; use std::borrow::Borrow; @@ -2545,8 +2545,9 @@ impl<'tcx> TyCtxt<'tcx> { self, obj: &'tcx List<ty::Binder<'tcx, ExistentialPredicate<'tcx>>>, reg: ty::Region<'tcx>, + repr: DynKind, ) -> Ty<'tcx> { - self.mk_ty(Dynamic(obj, reg)) + self.mk_ty(Dynamic(obj, reg, repr)) } #[inline] diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 648f5f7161f..855917fb828 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -467,7 +467,7 @@ impl<'tcx> TypeVisitor<'tcx> for IsSuggestableVisitor<'tcx> { } } - Dynamic(dty, _) => { + Dynamic(dty, _, _) => { for pred in *dty { match pred.skip_binder() { ExistentialPredicate::Trait(_) | ExistentialPredicate::Projection(_) => { diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index c22c899c5cc..98b8a7386fe 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -171,7 +171,7 @@ impl FlagComputation { self.add_substs(substs); } - &ty::Dynamic(obj, r) => { + &ty::Dynamic(obj, r, _) => { for predicate in obj.iter() { self.bound_computation(predicate, |computation, predicate| match predicate { ty::ExistentialPredicate::Trait(tr) => computation.add_substs(tr.substs), diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index abb7ddd88b1..042eeec3f46 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -625,6 +625,14 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { tcx.intern_layout(self.scalar_pair(data_ptr, metadata)) } + ty::Dynamic(_, _, ty::DynStar) => { + let mut data = scalar_unit(Int(dl.ptr_sized_integer(), false)); + data.valid_range_mut().start = 0; + let mut vtable = scalar_unit(Pointer); + vtable.valid_range_mut().start = 1; + tcx.intern_layout(self.scalar_pair(data, vtable)) + } + // Arrays and slices. ty::Array(element, mut count) => { if count.has_projections() { @@ -679,7 +687,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // Odd unit types. ty::FnDef(..) => univariant(&[], &ReprOptions::default(), StructKind::AlwaysSized)?, - ty::Dynamic(..) | ty::Foreign(..) => { + ty::Dynamic(_, _, ty::Dyn) | ty::Foreign(..) => { let mut unit = self.univariant_uninterned( ty, &[], @@ -2435,7 +2443,9 @@ where | ty::FnDef(..) | ty::GeneratorWitness(..) | ty::Foreign(..) - | ty::Dynamic(..) => bug!("TyAndLayout::field({:?}): not applicable", this), + | ty::Dynamic(_, _, ty::Dyn) => { + bug!("TyAndLayout::field({:?}): not applicable", this) + } // Potentially-fat pointers. ty::Ref(_, pointee, _) | ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => { @@ -2464,7 +2474,7 @@ where match tcx.struct_tail_erasing_lifetimes(pointee, cx.param_env()).kind() { ty::Slice(_) | ty::Str => TyMaybeWithLayout::Ty(tcx.types.usize), - ty::Dynamic(_, _) => { + ty::Dynamic(_, _, ty::Dyn) => { TyMaybeWithLayout::Ty(tcx.mk_imm_ref( tcx.lifetimes.re_static, tcx.mk_array(tcx.types.usize, 3), @@ -2533,6 +2543,22 @@ where } } + ty::Dynamic(_, _, ty::DynStar) => { + if i == 0 { + TyMaybeWithLayout::Ty(tcx.types.usize) + } else if i == 1 { + // FIXME(dyn-star) same FIXME as above applies here too + TyMaybeWithLayout::Ty( + tcx.mk_imm_ref( + tcx.lifetimes.re_static, + tcx.mk_array(tcx.types.usize, 3), + ), + ) + } else { + bug!("no field {i} on dyn*") + } + } + ty::Projection(_) | ty::Bound(..) | ty::Placeholder(..) @@ -2728,6 +2754,7 @@ impl<'tcx> ty::Instance<'tcx> { // for `Instance` (e.g. typeck would use `Ty::fn_sig` instead), // or should go through `FnAbi` instead, to avoid losing any // adjustments `fn_abi_of_instance` might be performing. + #[tracing::instrument(level = "debug", skip(tcx, param_env))] fn fn_sig_for_fn_abi( &self, tcx: TyCtxt<'tcx>, @@ -2874,6 +2901,7 @@ impl<'tcx> ty::Instance<'tcx> { /// with `-Cpanic=abort` will look like they can't unwind when in fact they /// might (from a foreign exception or similar). #[inline] +#[tracing::instrument(level = "debug", skip(tcx))] pub fn fn_can_unwind<'tcx>(tcx: TyCtxt<'tcx>, fn_def_id: Option<DefId>, abi: SpecAbi) -> bool { if let Some(did) = fn_def_id { // Special attribute for functions which can't unwind. @@ -3090,6 +3118,7 @@ pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'tcx> { /// NB: that includes virtual calls, which are represented by "direct calls" /// to an `InstanceDef::Virtual` instance (of `<dyn Trait as Trait>::fn`). #[inline] + #[tracing::instrument(level = "debug", skip(self))] fn fn_abi_of_instance( &self, instance: ty::Instance<'tcx>, @@ -3236,6 +3265,10 @@ pub fn adjust_for_rust_scalar<'tcx>( impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // FIXME(eddyb) perhaps group the signature/type-containing (or all of them?) // arguments of this method, into a separate `struct`. + #[tracing::instrument( + level = "debug", + skip(self, caller_location, fn_def_id, force_thin_self_ptr) + )] fn fn_abi_new_uncached( &self, sig: ty::PolyFnSig<'tcx>, @@ -3245,8 +3278,6 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // FIXME(eddyb) replace this with something typed, like an `enum`. force_thin_self_ptr: bool, ) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> { - debug!("fn_abi_new_uncached({:?}, {:?})", sig, extra_args); - let sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, sig); let conv = conv_from_spec_abi(self.tcx(), sig.abi); @@ -3289,6 +3320,8 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let rust_abi = matches!(sig.abi, RustIntrinsic | PlatformIntrinsic | Rust | RustCall); let arg_of = |ty: Ty<'tcx>, arg_idx: Option<usize>| -> Result<_, FnAbiError<'tcx>> { + let span = tracing::debug_span!("arg_of"); + let _entered = span.enter(); let is_return = arg_idx.is_none(); let layout = self.layout_of(ty)?; @@ -3345,6 +3378,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { Ok(self.tcx.arena.alloc(fn_abi)) } + #[tracing::instrument(level = "trace", skip(self))] fn fn_abi_adjust_for_abi( &self, fn_abi: &mut FnAbi<'tcx, Ty<'tcx>>, @@ -3419,6 +3453,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } } +#[tracing::instrument(level = "debug", skip(cx))] fn make_thin_self_ptr<'tcx>( cx: &(impl HasTyCtxt<'tcx> + HasParamEnv<'tcx>), layout: TyAndLayout<'tcx>, @@ -3430,7 +3465,7 @@ fn make_thin_self_ptr<'tcx>( tcx.mk_mut_ptr(layout.ty) } else { match layout.abi { - Abi::ScalarPair(..) => (), + Abi::ScalarPair(..) | Abi::Scalar(..) => (), _ => bug!("receiver type has unsupported layout: {:?}", layout), } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 3ff62647105..6641ab9b756 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -58,6 +58,7 @@ use std::ops::ControlFlow; use std::{fmt, str}; pub use crate::ty::diagnostics::*; +pub use rustc_type_ir::DynKind::*; pub use rustc_type_ir::InferTy::*; pub use rustc_type_ir::RegionKind::*; pub use rustc_type_ir::TyKind::*; @@ -1113,6 +1114,12 @@ pub trait ToPredicate<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx>; } +impl<'tcx> ToPredicate<'tcx> for Predicate<'tcx> { + fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + self + } +} + impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> { #[inline(always)] fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs index cac8560ce1c..9db5a289484 100644 --- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs +++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs @@ -36,6 +36,7 @@ impl<'tcx> TyCtxt<'tcx> { /// /// This should only be used outside of type inference. For example, /// it assumes that normalization will succeed. + #[tracing::instrument(level = "debug", skip(self, param_env))] pub fn normalize_erasing_regions<T>(self, param_env: ty::ParamEnv<'tcx>, value: T) -> T where T: TypeFoldable<'tcx>, @@ -100,6 +101,7 @@ impl<'tcx> TyCtxt<'tcx> { /// N.B., currently, higher-ranked type bounds inhibit /// normalization. Therefore, each time we erase them in /// codegen, we need to normalize the contents. + #[tracing::instrument(level = "debug", skip(self, param_env))] pub fn normalize_erasing_late_bound_regions<T>( self, param_env: ty::ParamEnv<'tcx>, diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index e9eecfe78d3..f7d5d3116af 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -619,12 +619,16 @@ pub trait PrettyPrinter<'tcx>: ty::Adt(def, substs) => { p!(print_def_path(def.did(), substs)); } - ty::Dynamic(data, r) => { + ty::Dynamic(data, r, repr) => { let print_r = self.should_print_region(r); if print_r { p!("("); } - p!("dyn ", print(data)); + match repr { + ty::Dyn => p!("dyn "), + ty::DynStar => p!("dyn* "), + } + p!(print(data)); if print_r { p!(" + ", print(r), ")"); } diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 81476195d29..5b3750b8b4d 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -441,7 +441,9 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>( (&ty::Foreign(a_id), &ty::Foreign(b_id)) if a_id == b_id => Ok(tcx.mk_foreign(a_id)), - (&ty::Dynamic(a_obj, a_region), &ty::Dynamic(b_obj, b_region)) => { + (&ty::Dynamic(a_obj, a_region, a_repr), &ty::Dynamic(b_obj, b_region, b_repr)) + if a_repr == b_repr => + { let region_bound = relation.with_cause(Cause::ExistentialRegionBound, |relation| { relation.relate_with_variance( ty::Contravariant, @@ -450,7 +452,7 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>( b_region, ) })?; - Ok(tcx.mk_dynamic(relation.relate(a_obj, b_obj)?, region_bound)) + Ok(tcx.mk_dynamic(relation.relate(a_obj, b_obj)?, region_bound, a_repr)) } (&ty::Generator(a_id, a_substs, movability), &ty::Generator(b_id, b_substs, _)) diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 37f88016f60..d7e74d675de 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -1028,9 +1028,11 @@ impl<'tcx> TypeSuperFoldable<'tcx> for Ty<'tcx> { ty::Array(typ, sz) => ty::Array(typ.try_fold_with(folder)?, sz.try_fold_with(folder)?), ty::Slice(typ) => ty::Slice(typ.try_fold_with(folder)?), ty::Adt(tid, substs) => ty::Adt(tid, substs.try_fold_with(folder)?), - ty::Dynamic(trait_ty, region) => { - ty::Dynamic(trait_ty.try_fold_with(folder)?, region.try_fold_with(folder)?) - } + ty::Dynamic(trait_ty, region, representation) => ty::Dynamic( + trait_ty.try_fold_with(folder)?, + region.try_fold_with(folder)?, + representation, + ), ty::Tuple(ts) => ty::Tuple(ts.try_fold_with(folder)?), ty::FnDef(def_id, substs) => ty::FnDef(def_id, substs.try_fold_with(folder)?), ty::FnPtr(f) => ty::FnPtr(f.try_fold_with(folder)?), @@ -1074,7 +1076,7 @@ impl<'tcx> TypeSuperVisitable<'tcx> for Ty<'tcx> { } ty::Slice(typ) => typ.visit_with(visitor), ty::Adt(_, substs) => substs.visit_with(visitor), - ty::Dynamic(ref trait_ty, ref reg) => { + ty::Dynamic(ref trait_ty, ref reg, _) => { trait_ty.visit_with(visitor)?; reg.visit_with(visitor) } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 702c2d27187..18169045c90 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -692,6 +692,9 @@ impl<'tcx> ExistentialPredicate<'tcx> { } impl<'tcx> Binder<'tcx, ExistentialPredicate<'tcx>> { + /// Given an existential predicate like `?Self: PartialEq<u32>` (e.g., derived from `dyn PartialEq<u32>`), + /// and a concrete type `self_ty`, returns a full predicate where the existentially quantified variable `?Self` + /// has been replaced with `self_ty` (e.g., `self_ty: PartialEq<u32>`, in our example). pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::Predicate<'tcx> { use crate::ty::ToPredicate; match self.skip_binder() { @@ -1849,7 +1852,12 @@ impl<'tcx> Ty<'tcx> { #[inline] pub fn is_trait(self) -> bool { - matches!(self.kind(), Dynamic(..)) + matches!(self.kind(), Dynamic(_, _, ty::Dyn)) + } + + #[inline] + pub fn is_dyn_star(self) -> bool { + matches!(self.kind(), Dynamic(_, _, ty::DynStar)) } #[inline] diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs index 831724bc4b0..a3e11bbf056 100644 --- a/compiler/rustc_middle/src/ty/walk.rs +++ b/compiler/rustc_middle/src/ty/walk.rs @@ -152,7 +152,7 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) ty::Projection(data) => { stack.extend(data.substs.iter().rev()); } - ty::Dynamic(obj, lt) => { + ty::Dynamic(obj, lt, _) => { stack.push(lt.into()); stack.extend(obj.iter().rev().flat_map(|predicate| { let (substs, opt_ty) = match predicate.skip_binder() { |
