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`
This commit is contained in:
commit
6153d3cbe6
69 changed files with 617 additions and 104 deletions
|
@ -256,7 +256,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
if let ty::Dynamic(traits, _) = self_ty.kind() {
|
||||
if let ty::Dynamic(traits, _, _) = self_ty.kind() {
|
||||
for t in traits.iter() {
|
||||
if let ty::ExistentialPredicate::Trait(trait_ref) = t.skip_binder() {
|
||||
flags.push((sym::_Self, Some(self.tcx.def_path_str(trait_ref.def_id))))
|
||||
|
|
|
@ -1067,7 +1067,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||
self_ty: Ty<'tcx>,
|
||||
object_ty: Ty<'tcx>,
|
||||
) {
|
||||
let ty::Dynamic(predicates, _) = object_ty.kind() else { return; };
|
||||
let ty::Dynamic(predicates, _, ty::Dyn) = object_ty.kind() else { return; };
|
||||
let self_ref_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, self_ty);
|
||||
|
||||
for predicate in predicates.iter() {
|
||||
|
@ -1365,7 +1365,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||
let trait_pred = self.resolve_vars_if_possible(trait_pred);
|
||||
let ty = trait_pred.skip_binder().self_ty();
|
||||
let is_object_safe = match ty.kind() {
|
||||
ty::Dynamic(predicates, _) => {
|
||||
ty::Dynamic(predicates, _, ty::Dyn) => {
|
||||
// If the `dyn Trait` is not object safe, do not suggest `Box<dyn Trait>`.
|
||||
predicates
|
||||
.principal_def_id()
|
||||
|
@ -1425,7 +1425,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||
let mut spans_and_needs_box = vec![];
|
||||
|
||||
match liberated_sig.output().kind() {
|
||||
ty::Dynamic(predicates, _) => {
|
||||
ty::Dynamic(predicates, _, _) => {
|
||||
let cause = ObligationCause::misc(ret_ty.span, fn_hir_id);
|
||||
let param_env = ty::ParamEnv::empty();
|
||||
|
||||
|
|
|
@ -600,7 +600,7 @@ fn object_ty_for_trait<'tcx>(
|
|||
let existential_predicates = tcx
|
||||
.mk_poly_existential_predicates(iter::once(trait_predicate).chain(projection_predicates));
|
||||
|
||||
let object_ty = tcx.mk_dynamic(existential_predicates, lifetime);
|
||||
let object_ty = tcx.mk_dynamic(existential_predicates, lifetime, ty::Dyn);
|
||||
|
||||
debug!("object_ty_for_trait: object_ty=`{}`", object_ty);
|
||||
|
||||
|
|
|
@ -1039,7 +1039,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
| ty::Ref(_, _, _)
|
||||
| ty::FnDef(_, _)
|
||||
| ty::FnPtr(_)
|
||||
| ty::Dynamic(_, _)
|
||||
| ty::Dynamic(_, _, _)
|
||||
| ty::Closure(_, _)
|
||||
| ty::Generator(_, _, _)
|
||||
| ty::GeneratorWitness(_)
|
||||
|
|
|
@ -784,7 +784,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
let upcast_trait_ref;
|
||||
match (source.kind(), target.kind()) {
|
||||
// TraitA+Kx+'a -> TraitB+Ky+'b (trait upcasting coercion).
|
||||
(&ty::Dynamic(ref data_a, r_a), &ty::Dynamic(ref data_b, r_b)) => {
|
||||
(&ty::Dynamic(ref data_a, r_a, repr_a), &ty::Dynamic(ref data_b, r_b, repr_b))
|
||||
if repr_a == repr_b =>
|
||||
{
|
||||
// See `assemble_candidates_for_unsizing` for more info.
|
||||
// We already checked the compatibility of auto traits within `assemble_candidates_for_unsizing`.
|
||||
let principal_a = data_a.principal().unwrap();
|
||||
|
@ -810,7 +812,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
.map(ty::Binder::dummy),
|
||||
);
|
||||
let existential_predicates = tcx.mk_poly_existential_predicates(iter);
|
||||
let source_trait = tcx.mk_dynamic(existential_predicates, r_b);
|
||||
let source_trait = tcx.mk_dynamic(existential_predicates, r_b, repr_b);
|
||||
|
||||
// Require that the traits involved in this upcast are **equal**;
|
||||
// only the **lifetime bound** is changed.
|
||||
|
@ -888,7 +890,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
let mut nested = vec![];
|
||||
match (source.kind(), target.kind()) {
|
||||
// Trait+Kx+'a -> Trait+Ky+'b (auto traits and lifetime subtyping).
|
||||
(&ty::Dynamic(ref data_a, r_a), &ty::Dynamic(ref data_b, r_b)) => {
|
||||
(&ty::Dynamic(ref data_a, r_a, ty::Dyn), &ty::Dynamic(ref data_b, r_b, ty::Dyn)) => {
|
||||
// See `assemble_candidates_for_unsizing` for more info.
|
||||
// We already checked the compatibility of auto traits within `assemble_candidates_for_unsizing`.
|
||||
let iter = data_a
|
||||
|
@ -907,7 +909,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
.map(ty::Binder::dummy),
|
||||
);
|
||||
let existential_predicates = tcx.mk_poly_existential_predicates(iter);
|
||||
let source_trait = tcx.mk_dynamic(existential_predicates, r_b);
|
||||
let source_trait = tcx.mk_dynamic(existential_predicates, r_b, ty::Dyn);
|
||||
|
||||
// Require that the traits involved in this upcast are **equal**;
|
||||
// only the **lifetime bound** is changed.
|
||||
|
@ -934,7 +936,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
}
|
||||
|
||||
// `T` -> `Trait`
|
||||
(_, &ty::Dynamic(ref data, r)) => {
|
||||
(_, &ty::Dynamic(ref data, r, ty::Dyn)) => {
|
||||
let mut object_dids = data.auto_traits().chain(data.principal_def_id());
|
||||
if let Some(did) = object_dids.find(|did| !tcx.is_object_safe(*did)) {
|
||||
return Err(TraitNotObjectSafe(did));
|
||||
|
|
|
@ -1865,6 +1865,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
| ty::Array(..)
|
||||
| ty::Closure(..)
|
||||
| ty::Never
|
||||
| ty::Dynamic(_, _, ty::DynStar)
|
||||
| ty::Error(_) => {
|
||||
// safe for everything
|
||||
Where(ty::Binder::dummy(Vec::new()))
|
||||
|
|
|
@ -639,7 +639,7 @@ impl<'tcx> WfPredicates<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
ty::Dynamic(data, r) => {
|
||||
ty::Dynamic(data, r, _) => {
|
||||
// WfObject
|
||||
//
|
||||
// Here, we defer WF checking due to higher-ranked
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue