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:
bors 2022-09-14 18:10:51 +00:00
commit f6a07d1d36
3 changed files with 9 additions and 6 deletions

View file

@ -2,7 +2,7 @@ use rustc_hir::Expr;
use rustc_lint::LateContext; use rustc_lint::LateContext;
use rustc_middle::ty::{cast::CastKind, Ty}; use rustc_middle::ty::{cast::CastKind, Ty};
use rustc_span::DUMMY_SP; use rustc_span::DUMMY_SP;
use rustc_typeck::check::{cast::CastCheck, FnCtxt, Inherited}; use rustc_typeck::check::{cast::{self, CastCheckResult}, FnCtxt, Inherited};
// check if the component types of the transmuted collection and the result have different ABI, // check if the component types of the transmuted collection and the result have different ABI,
// size or alignment // size or alignment
@ -53,7 +53,7 @@ fn check_cast<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty<'tcx>
"Newly created FnCtxt contained errors" "Newly created FnCtxt contained errors"
); );
if let Ok(check) = CastCheck::new( if let CastCheckResult::Deferred(check) = cast::check_cast(
&fn_ctxt, e, from_ty, to_ty, &fn_ctxt, e, from_ty, to_ty,
// We won't show any error to the user, so we don't care what the span is here. // We won't show any error to the user, so we don't care what the span is here.
DUMMY_SP, DUMMY_SP, DUMMY_SP, DUMMY_SP,

View file

@ -82,7 +82,7 @@ fn check_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) -> McfResult {
ty::FnPtr(..) => { ty::FnPtr(..) => {
return Err((span, "function pointers in const fn are unstable".into())); return Err((span, "function pointers in const fn are unstable".into()));
}, },
ty::Dynamic(preds, _) => { ty::Dynamic(preds, _, _) => {
for pred in preds.iter() { for pred in preds.iter() {
match pred.skip_binder() { match pred.skip_binder() {
ty::ExistentialPredicate::AutoTrait(_) | ty::ExistentialPredicate::Projection(_) => { ty::ExistentialPredicate::AutoTrait(_) | ty::ExistentialPredicate::Projection(_) => {
@ -161,6 +161,10 @@ fn check_rvalue<'tcx>(
Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => { Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => {
Err((span, "casting pointers to ints is unstable in const fn".into())) Err((span, "casting pointers to ints is unstable in const fn".into()))
}, },
Rvalue::Cast(CastKind::DynStar, _, _) => {
// FIXME(dyn-star)
unimplemented!()
},
// binops are fine on integers // binops are fine on integers
Rvalue::BinaryOp(_, box (lhs, rhs)) | Rvalue::CheckedBinaryOp(_, box (lhs, rhs)) => { Rvalue::BinaryOp(_, box (lhs, rhs)) | Rvalue::CheckedBinaryOp(_, box (lhs, rhs)) => {
check_operand(tcx, lhs, span, body)?; check_operand(tcx, lhs, span, body)?;
@ -221,7 +225,6 @@ fn check_statement<'tcx>(
check_operand(tcx, src, span, body)?; check_operand(tcx, src, span, body)?;
check_operand(tcx, count, span, body) check_operand(tcx, count, span, body)
}, },
// These are all NOPs // These are all NOPs
StatementKind::StorageLive(_) StatementKind::StorageLive(_)
| StatementKind::StorageDead(_) | StatementKind::StorageDead(_)

View file

@ -201,7 +201,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
} }
false false
}, },
ty::Dynamic(binder, _) => { ty::Dynamic(binder, _, _) => {
for predicate in binder.iter() { for predicate in binder.iter() {
if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() { if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() {
if cx.tcx.has_attr(trait_ref.def_id, sym::must_use) { if cx.tcx.has_attr(trait_ref.def_id, sym::must_use) {
@ -579,7 +579,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'t
ty::FnDef(id, subs) => Some(ExprFnSig::Sig(cx.tcx.bound_fn_sig(id).subst(cx.tcx, subs), Some(id))), ty::FnDef(id, subs) => Some(ExprFnSig::Sig(cx.tcx.bound_fn_sig(id).subst(cx.tcx, subs), Some(id))),
ty::Opaque(id, _) => sig_from_bounds(cx, ty, cx.tcx.item_bounds(id), cx.tcx.opt_parent(id)), ty::Opaque(id, _) => sig_from_bounds(cx, ty, cx.tcx.item_bounds(id), cx.tcx.opt_parent(id)),
ty::FnPtr(sig) => Some(ExprFnSig::Sig(sig, None)), ty::FnPtr(sig) => Some(ExprFnSig::Sig(sig, None)),
ty::Dynamic(bounds, _) => { ty::Dynamic(bounds, _, _) => {
let lang_items = cx.tcx.lang_items(); let lang_items = cx.tcx.lang_items();
match bounds.principal() { match bounds.principal() {
Some(bound) Some(bound)