Remove existing AFIDT implementation

This commit is contained in:
Michael Goulet 2025-03-18 16:17:18 +00:00
parent 75530e9f72
commit 93b31d9b21
18 changed files with 177 additions and 301 deletions

View File

@ -176,7 +176,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
.in_definition_order()
// We only care about associated types.
.filter(|item| item.kind == ty::AssocKind::Type)
// No RPITITs -- even with `async_fn_in_dyn_trait`, they are implicit.
// No RPITITs -- they're not dyn-compatible for now.
.filter(|item| !item.is_impl_trait_in_trait())
// If the associated type has a `where Self: Sized` bound,
// we do not need to constrain the associated type.

View File

@ -712,10 +712,7 @@ impl<'tcx> Instance<'tcx> {
..
})
);
// We also need to generate a shim if this is an AFIT.
let needs_rpitit_shim =
tcx.return_position_impl_trait_in_trait_shim_data(def).is_some();
if needs_track_caller_shim || needs_rpitit_shim {
if needs_track_caller_shim {
if tcx.is_closure_like(def) {
debug!(
" => vtable fn pointer created for closure with #[track_caller]: {:?} for method {:?} {:?}",

View File

@ -149,7 +149,6 @@ mod opaque_types;
mod parameterized;
mod predicate;
mod region;
mod return_position_impl_trait_in_trait;
mod rvalue_scopes;
mod structural_impls;
#[allow(hidden_glob_reexports)]

View File

@ -1,95 +0,0 @@
use rustc_hir::def_id::DefId;
use crate::ty::{self, ExistentialPredicateStableCmpExt, TyCtxt};
impl<'tcx> TyCtxt<'tcx> {
/// Given a `def_id` of a trait or impl method, compute whether that method needs to
/// have an RPITIT shim applied to it for it to be dyn compatible. If so, return the
/// `def_id` of the RPITIT, and also the args of trait method that returns the RPITIT.
///
/// NOTE that these args are not, in general, the same as than the RPITIT's args. They
/// are a subset of those args, since they do not include the late-bound lifetimes of
/// the RPITIT. Depending on the context, these will need to be dealt with in different
/// ways -- in codegen, it's okay to fill them with ReErased.
pub fn return_position_impl_trait_in_trait_shim_data(
self,
def_id: DefId,
) -> Option<(DefId, ty::EarlyBinder<'tcx, ty::GenericArgsRef<'tcx>>)> {
let assoc_item = self.opt_associated_item(def_id)?;
let (trait_item_def_id, opt_impl_def_id) = match assoc_item.container {
ty::AssocItemContainer::Impl => {
(assoc_item.trait_item_def_id?, Some(self.parent(def_id)))
}
ty::AssocItemContainer::Trait => (def_id, None),
};
let sig = self.fn_sig(trait_item_def_id);
// Check if the trait returns an RPITIT.
let ty::Alias(ty::Projection, ty::AliasTy { def_id, .. }) =
*sig.skip_binder().skip_binder().output().kind()
else {
return None;
};
if !self.is_impl_trait_in_trait(def_id) {
return None;
}
let args = if let Some(impl_def_id) = opt_impl_def_id {
// Rebase the args from the RPITIT onto the impl trait ref, so we can later
// substitute them with the method args of the *impl* method, since that's
// the instance we're building a vtable shim for.
ty::GenericArgs::identity_for_item(self, trait_item_def_id).rebase_onto(
self,
self.parent(trait_item_def_id),
self.impl_trait_ref(impl_def_id)
.expect("expected impl trait ref from parent of impl item")
.instantiate_identity()
.args,
)
} else {
// This is when we have a default trait implementation.
ty::GenericArgs::identity_for_item(self, trait_item_def_id)
};
Some((def_id, ty::EarlyBinder::bind(args)))
}
/// Given a `DefId` of an RPITIT and its args, return the existential predicates
/// that corresponds to the RPITIT's bounds with the self type erased.
pub fn item_bounds_to_existential_predicates(
self,
def_id: DefId,
args: ty::GenericArgsRef<'tcx>,
) -> &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> {
let mut bounds: Vec<_> = self
.item_self_bounds(def_id)
.iter_instantiated(self, args)
.filter_map(|clause| {
clause
.kind()
.map_bound(|clause| match clause {
ty::ClauseKind::Trait(trait_pred) => Some(ty::ExistentialPredicate::Trait(
ty::ExistentialTraitRef::erase_self_ty(self, trait_pred.trait_ref),
)),
ty::ClauseKind::Projection(projection_pred) => {
Some(ty::ExistentialPredicate::Projection(
ty::ExistentialProjection::erase_self_ty(self, projection_pred),
))
}
ty::ClauseKind::TypeOutlives(_) => {
// Type outlives bounds don't really turn into anything,
// since we must use an intersection region for the `dyn*`'s
// region anyways.
None
}
_ => unreachable!("unexpected clause in item bounds: {clause:?}"),
})
.transpose()
})
.collect();
bounds.sort_by(|a, b| a.skip_binder().stable_cmp(self, &b.skip_binder()));
self.mk_poly_existential_predicates(&bounds)
}
}

View File

@ -8,7 +8,6 @@ use rustc_hir::lang_items::LangItem;
use rustc_index::{Idx, IndexVec};
use rustc_middle::mir::*;
use rustc_middle::query::Providers;
use rustc_middle::ty::adjustment::PointerCoercion;
use rustc_middle::ty::{
self, CoroutineArgs, CoroutineArgsExt, EarlyBinder, GenericArgs, Ty, TyCtxt,
};
@ -718,12 +717,6 @@ fn build_call_shim<'tcx>(
let def_id = instance.def_id();
let rpitit_shim = if let ty::InstanceKind::ReifyShim(..) = instance {
tcx.return_position_impl_trait_in_trait_shim_data(def_id)
} else {
None
};
let sig = tcx.fn_sig(def_id);
let sig = sig.map_bound(|sig| tcx.instantiate_bound_regions_with_erased(sig));
@ -779,30 +772,7 @@ fn build_call_shim<'tcx>(
let mut local_decls = local_decls_for_sig(&sig, span);
let source_info = SourceInfo::outermost(span);
let mut destination = Place::return_place();
if let Some((rpitit_def_id, fn_args)) = rpitit_shim {
let rpitit_args =
fn_args.instantiate_identity().extend_to(tcx, rpitit_def_id, |param, _| {
match param.kind {
ty::GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
ty::GenericParamDefKind::Type { .. }
| ty::GenericParamDefKind::Const { .. } => {
unreachable!("rpitit should have no addition ty/ct")
}
}
});
let dyn_star_ty = Ty::new_dynamic(
tcx,
tcx.item_bounds_to_existential_predicates(rpitit_def_id, rpitit_args),
tcx.lifetimes.re_erased,
ty::DynStar,
);
destination = local_decls.push(local_decls[RETURN_PLACE].clone()).into();
local_decls[RETURN_PLACE].ty = dyn_star_ty;
let mut inputs_and_output = sig.inputs_and_output.to_vec();
*inputs_and_output.last_mut().unwrap() = dyn_star_ty;
sig.inputs_and_output = tcx.mk_type_list(&inputs_and_output);
}
let destination = Place::return_place();
let rcvr_place = || {
assert!(rcvr_adjustment.is_some());
@ -921,23 +891,7 @@ fn build_call_shim<'tcx>(
);
}
// BB #1/#2 - return
// NOTE: If this is an RPITIT in dyn, we also want to coerce
// the return type of the function into a `dyn*`.
let stmts = if rpitit_shim.is_some() {
vec![Statement {
source_info,
kind: StatementKind::Assign(Box::new((
Place::return_place(),
Rvalue::Cast(
CastKind::PointerCoercion(PointerCoercion::DynStar, CoercionSource::Implicit),
Operand::Move(destination),
sig.output(),
),
))),
}]
} else {
vec![]
};
let stmts = vec![];
block(&mut blocks, stmts, TerminatorKind::Return, false);
if let Some(Adjustment::RefMut) = rcvr_adjustment {
// BB #3 - drop if closure panics

View File

@ -9,7 +9,6 @@ use std::ops::ControlFlow;
use rustc_errors::FatalError;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_middle::bug;
use rustc_middle::query::Providers;
use rustc_middle::ty::{
self, EarlyBinder, GenericArgs, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
@ -807,31 +806,8 @@ fn contains_illegal_impl_trait_in_trait<'tcx>(
let ty = tcx.liberate_late_bound_regions(fn_def_id, ty);
if tcx.asyncness(fn_def_id).is_async() {
// FIXME(async_fn_in_dyn_trait): Think of a better way to unify these code paths
// to issue an appropriate feature suggestion when users try to use AFIDT.
// Obviously we must only do this once AFIDT is finished enough to actually be usable.
if tcx.features().async_fn_in_dyn_trait() {
let ty::Alias(ty::Projection, proj) = *ty.kind() else {
bug!("expected async fn in trait to return an RPITIT");
};
assert!(tcx.is_impl_trait_in_trait(proj.def_id));
// FIXME(async_fn_in_dyn_trait): We should check that this bound is legal too,
// and stop relying on `async fn` in the definition.
for bound in tcx.item_bounds(proj.def_id).instantiate(tcx, proj.args) {
if let Some(violation) = bound
.visit_with(&mut IllegalRpititVisitor { tcx, allowed: Some(proj) })
.break_value()
{
return Some(violation);
}
}
None
} else {
// Rendering the error as a separate `async-specific` message is better.
Some(MethodViolationCode::AsyncFn)
}
// Rendering the error as a separate `async-specific` message is better.
Some(MethodViolationCode::AsyncFn)
} else {
ty.visit_with(&mut IllegalRpititVisitor { tcx, allowed: None }).break_value()
}

View File

@ -7,8 +7,8 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def::DefKind;
use rustc_hir::lang_items::LangItem;
use rustc_infer::infer::DefineOpaqueTypes;
use rustc_infer::infer::resolve::OpportunisticRegionResolver;
use rustc_infer::infer::{DefineOpaqueTypes, RegionVariableOrigin};
use rustc_infer::traits::{ObligationCauseCode, PredicateObligations};
use rustc_middle::traits::select::OverflowError;
use rustc_middle::traits::{BuiltinImplSource, ImplSource, ImplSourceUserDefinedData};
@ -18,8 +18,6 @@ use rustc_middle::ty::{
};
use rustc_middle::{bug, span_bug};
use rustc_span::sym;
use rustc_type_ir::elaborate;
use thin_vec::thin_vec;
use tracing::{debug, instrument};
use super::{
@ -63,9 +61,6 @@ enum ProjectionCandidate<'tcx> {
/// Bounds specified on an object type
Object(ty::PolyProjectionPredicate<'tcx>),
/// Built-in bound for a dyn async fn in trait
ObjectRpitit,
/// From an "impl" (or a "pseudo-impl" returned by select)
Select(Selection<'tcx>),
}
@ -832,16 +827,6 @@ fn assemble_candidates_from_object_ty<'cx, 'tcx>(
env_predicates,
false,
);
// `dyn Trait` automagically project their AFITs to `dyn* Future`.
if tcx.is_impl_trait_in_trait(obligation.predicate.def_id)
&& let Some(out_trait_def_id) = data.principal_def_id()
&& let rpitit_trait_def_id = tcx.parent(obligation.predicate.def_id)
&& elaborate::supertrait_def_ids(tcx, out_trait_def_id)
.any(|trait_def_id| trait_def_id == rpitit_trait_def_id)
{
candidate_set.push_candidate(ProjectionCandidate::ObjectRpitit);
}
}
#[instrument(
@ -1273,8 +1258,6 @@ fn confirm_candidate<'cx, 'tcx>(
ProjectionCandidate::Select(impl_source) => {
confirm_select_candidate(selcx, obligation, impl_source)
}
ProjectionCandidate::ObjectRpitit => confirm_object_rpitit_candidate(selcx, obligation),
};
// When checking for cycle during evaluation, we compare predicates with
@ -2070,45 +2053,6 @@ fn confirm_impl_candidate<'cx, 'tcx>(
}
}
fn confirm_object_rpitit_candidate<'cx, 'tcx>(
selcx: &mut SelectionContext<'cx, 'tcx>,
obligation: &ProjectionTermObligation<'tcx>,
) -> Progress<'tcx> {
let tcx = selcx.tcx();
let mut obligations = thin_vec![];
// Compute an intersection lifetime for all the input components of this GAT.
let intersection =
selcx.infcx.next_region_var(RegionVariableOrigin::MiscVariable(obligation.cause.span));
for component in obligation.predicate.args {
match component.unpack() {
ty::GenericArgKind::Lifetime(lt) => {
obligations.push(obligation.with(tcx, ty::OutlivesPredicate(lt, intersection)));
}
ty::GenericArgKind::Type(ty) => {
obligations.push(obligation.with(tcx, ty::OutlivesPredicate(ty, intersection)));
}
ty::GenericArgKind::Const(_ct) => {
// Consts have no outlives...
}
}
}
Progress {
term: Ty::new_dynamic(
tcx,
tcx.item_bounds_to_existential_predicates(
obligation.predicate.def_id,
obligation.predicate.args,
),
intersection,
ty::DynStar,
)
.into(),
obligations,
}
}
// Get obligations corresponding to the predicates from the where-clause of the
// associated type itself.
fn assoc_ty_own_obligations<'cx, 'tcx>(

View File

@ -616,12 +616,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
for assoc_type in assoc_types {
let defs: &ty::Generics = tcx.generics_of(assoc_type);
// When `async_fn_in_dyn_trait` is enabled, we don't need to check the
// RPITIT for compatibility, since it's not provided by the user.
if tcx.features().async_fn_in_dyn_trait() && tcx.is_impl_trait_in_trait(assoc_type) {
continue;
}
if !defs.own_params.is_empty() {
tcx.dcx().span_delayed_bug(
obligation.cause.span,

View File

@ -55,31 +55,6 @@ fn fn_sig_for_fn_abi<'tcx>(
sig.inputs_and_output = tcx.mk_type_list(&inputs_and_output);
}
// Modify `fn() -> impl Future` to `fn() -> dyn* Future`.
if let ty::InstanceKind::ReifyShim(def_id, _) = instance.def
&& let Some((rpitit_def_id, fn_args)) =
tcx.return_position_impl_trait_in_trait_shim_data(def_id)
{
let fn_args = fn_args.instantiate(tcx, args);
let rpitit_args =
fn_args.extend_to(tcx, rpitit_def_id, |param, _| match param.kind {
ty::GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
ty::GenericParamDefKind::Type { .. }
| ty::GenericParamDefKind::Const { .. } => {
unreachable!("rpitit should have no addition ty/ct")
}
});
let dyn_star_ty = Ty::new_dynamic(
tcx,
tcx.item_bounds_to_existential_predicates(rpitit_def_id, rpitit_args),
tcx.lifetimes.re_erased,
ty::DynStar,
);
let mut inputs_and_output = sig.inputs_and_output.to_vec();
*inputs_and_output.last_mut().unwrap() = dyn_star_ty;
sig.inputs_and_output = tcx.mk_type_list(&inputs_and_output);
}
sig
}
ty::Closure(def_id, args) => {

View File

@ -1,7 +0,0 @@
//@ known-bug: #136286
//@ compile-flags: --edition=2024
#![feature(async_fn_in_dyn_trait)]
trait A {
async fn b(self: A);
}

View File

@ -1,7 +0,0 @@
//@ known-bug: #137706
//@ needs-rustc-debug-assertions
trait A {
fn b() -> impl IntoIterator<Item = ()>;
}
impl A<()> for dyn A {}

View File

@ -1,6 +0,0 @@
//@ known-bug: #137895
trait A {
fn b() -> impl ?Sized + 'a;
}
impl A for dyn A {}

View File

@ -1,11 +1,9 @@
//@ aux-build:block-on.rs
//@ edition: 2021
//@ run-pass
//@ check-run-results
//@ known-bug: #133119
#![allow(refining_impl_trait)]
#![feature(async_fn_in_dyn_trait)]
//~^ WARN the feature `async_fn_in_dyn_trait` is incomplete
extern crate block_on;

View File

@ -1,5 +1,5 @@
warning: the feature `async_fn_in_dyn_trait` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/mut-is-pointer-like.rs:7:12
--> $DIR/mut-is-pointer-like.rs:6:12
|
LL | #![feature(async_fn_in_dyn_trait)]
| ^^^^^^^^^^^^^^^^^^^^^
@ -7,5 +7,65 @@ LL | #![feature(async_fn_in_dyn_trait)]
= note: see issue #133119 <https://github.com/rust-lang/rust/issues/133119> for more information
= note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
error[E0038]: the trait `AsyncTrait` is not dyn compatible
--> $DIR/mut-is-pointer-like.rs:35:16
|
LL | let x: Pin<&mut dyn AsyncTrait<Output = ()>> = f;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `AsyncTrait` is not dyn compatible
|
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $DIR/mut-is-pointer-like.rs:16:14
|
LL | trait AsyncTrait {
| ---------- this trait is not dyn compatible...
...
LL | async fn async_dispatch(self: Pin<&mut Self>) -> Self::Output;
| ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async`
= help: consider moving `async_dispatch` to another trait
error[E0038]: the trait `AsyncTrait` is not dyn compatible
--> $DIR/mut-is-pointer-like.rs:35:56
|
LL | let x: Pin<&mut dyn AsyncTrait<Output = ()>> = f;
| ^ `AsyncTrait` is not dyn compatible
|
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $DIR/mut-is-pointer-like.rs:16:14
|
LL | trait AsyncTrait {
| ---------- this trait is not dyn compatible...
...
LL | async fn async_dispatch(self: Pin<&mut Self>) -> Self::Output;
| ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async`
= help: consider moving `async_dispatch` to another trait
= note: required for the cast from `Pin<&mut {async block@$DIR/mut-is-pointer-like.rs:32:32: 32:37}>` to `Pin<&mut dyn AsyncTrait<Output = ()>>`
error[E0277]: the trait bound `dyn AsyncTrait<Output = ()>: AsyncTrait` is not satisfied
--> $DIR/mut-is-pointer-like.rs:36:11
|
LL | x.async_dispatch().await;
| ^^^^^^^^^^^^^^ the trait `AsyncTrait` is not implemented for `dyn AsyncTrait<Output = ()>`
error[E0038]: the trait `AsyncTrait` is not dyn compatible
--> $DIR/mut-is-pointer-like.rs:36:9
|
LL | x.async_dispatch().await;
| ^^^^^^^^^^^^^^^^^^ `AsyncTrait` is not dyn compatible
|
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $DIR/mut-is-pointer-like.rs:16:14
|
LL | trait AsyncTrait {
| ---------- this trait is not dyn compatible...
...
LL | async fn async_dispatch(self: Pin<&mut Self>) -> Self::Output;
| ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async`
= help: consider moving `async_dispatch` to another trait
error: aborting due to 4 previous errors; 1 warning emitted
Some errors have detailed explanations: E0038, E0277.
For more information about an error, try `rustc --explain E0038`.

View File

@ -1,11 +1,9 @@
//@ aux-build:block-on.rs
//@ edition: 2021
//@ run-pass
//@ check-run-results
//@ known-bug: #133119
#![allow(refining_impl_trait)]
#![feature(async_fn_in_dyn_trait)]
//~^ WARN the feature `async_fn_in_dyn_trait` is incomplete
extern crate block_on;

View File

@ -1,5 +1,5 @@
warning: the feature `async_fn_in_dyn_trait` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/works.rs:7:12
--> $DIR/works.rs:6:12
|
LL | #![feature(async_fn_in_dyn_trait)]
| ^^^^^^^^^^^^^^^^^^^^^
@ -7,5 +7,75 @@ LL | #![feature(async_fn_in_dyn_trait)]
= note: see issue #133119 <https://github.com/rust-lang/rust/issues/133119> for more information
= note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
error[E0038]: the trait `AsyncTrait` is not dyn compatible
--> $DIR/works.rs:27:34
|
LL | let x: &dyn AsyncTrait = &"hello, world!";
| ^^^^^^^^^^^^^^^^ `AsyncTrait` is not dyn compatible
|
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $DIR/works.rs:14:14
|
LL | trait AsyncTrait {
| ---------- this trait is not dyn compatible...
LL | async fn async_dispatch(&self);
| ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async`
= help: consider moving `async_dispatch` to another trait
= help: only type `&'static str` implements `AsyncTrait`; consider using it directly instead.
= note: required for the cast from `&&'static str` to `&dyn AsyncTrait`
error[E0038]: the trait `AsyncTrait` is not dyn compatible
--> $DIR/works.rs:27:16
|
LL | let x: &dyn AsyncTrait = &"hello, world!";
| ^^^^^^^^^^^^^^^ `AsyncTrait` is not dyn compatible
|
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $DIR/works.rs:14:14
|
LL | trait AsyncTrait {
| ---------- this trait is not dyn compatible...
LL | async fn async_dispatch(&self);
| ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async`
= help: consider moving `async_dispatch` to another trait
= help: only type `&'static str` implements `AsyncTrait`; consider using it directly instead.
error[E0038]: the trait `AsyncTrait` is not dyn compatible
--> $DIR/works.rs:28:11
|
LL | x.async_dispatch().await;
| ^^^^^^^^^^^^^^ `AsyncTrait` is not dyn compatible
|
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $DIR/works.rs:14:14
|
LL | trait AsyncTrait {
| ---------- this trait is not dyn compatible...
LL | async fn async_dispatch(&self);
| ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async`
= help: consider moving `async_dispatch` to another trait
= help: only type `&'static str` implements `AsyncTrait`; consider using it directly instead.
error[E0038]: the trait `AsyncTrait` is not dyn compatible
--> $DIR/works.rs:28:9
|
LL | x.async_dispatch().await;
| ^^^^^^^^^^^^^^^^^^ `AsyncTrait` is not dyn compatible
|
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $DIR/works.rs:14:14
|
LL | trait AsyncTrait {
| ---------- this trait is not dyn compatible...
LL | async fn async_dispatch(&self);
| ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async`
= help: consider moving `async_dispatch` to another trait
= help: only type `&'static str` implements `AsyncTrait`; consider using it directly instead.
error: aborting due to 4 previous errors; 1 warning emitted
For more information about this error, try `rustc --explain E0038`.

View File

@ -1,7 +1,7 @@
//@ edition: 2021
//@ known-bug: #133119
#![feature(async_fn_in_dyn_trait)]
//~^ WARN the feature `async_fn_in_dyn_trait` is incomplete
use std::future::Future;
@ -19,5 +19,5 @@ impl AsyncTrait for &'static str {
fn main() {
let x: &dyn AsyncTrait = &"hello, world!";
//~^ ERROR `impl Future<Output = ()>` needs to have the same ABI as a pointer
// FIXME ~^ ERROR `impl Future<Output = ()>` needs to have the same ABI as a pointer
}

View File

@ -1,5 +1,5 @@
warning: the feature `async_fn_in_dyn_trait` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/wrong-size.rs:3:12
--> $DIR/wrong-size.rs:4:12
|
LL | #![feature(async_fn_in_dyn_trait)]
| ^^^^^^^^^^^^^^^^^^^^^
@ -7,15 +7,41 @@ LL | #![feature(async_fn_in_dyn_trait)]
= note: see issue #133119 <https://github.com/rust-lang/rust/issues/133119> for more information
= note: `#[warn(incomplete_features)]` on by default
error[E0277]: `impl Future<Output = ()>` needs to have the same ABI as a pointer
error[E0038]: the trait `AsyncTrait` is not dyn compatible
--> $DIR/wrong-size.rs:21:30
|
LL | let x: &dyn AsyncTrait = &"hello, world!";
| ^^^^^^^^^^^^^^^^ `impl Future<Output = ()>` needs to be a pointer-like type
| ^^^^^^^^^^^^^^^^ `AsyncTrait` is not dyn compatible
|
= help: the trait `for<'a> PointerLike` is not implemented for `impl Future<Output = ()>`
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $DIR/wrong-size.rs:9:14
|
LL | trait AsyncTrait {
| ---------- this trait is not dyn compatible...
LL | async fn async_dispatch(&self);
| ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async`
= help: consider moving `async_dispatch` to another trait
= help: only type `&'static str` implements `AsyncTrait`; consider using it directly instead.
= note: required for the cast from `&&'static str` to `&dyn AsyncTrait`
error: aborting due to 1 previous error; 1 warning emitted
error[E0038]: the trait `AsyncTrait` is not dyn compatible
--> $DIR/wrong-size.rs:21:12
|
LL | let x: &dyn AsyncTrait = &"hello, world!";
| ^^^^^^^^^^^^^^^ `AsyncTrait` is not dyn compatible
|
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $DIR/wrong-size.rs:9:14
|
LL | trait AsyncTrait {
| ---------- this trait is not dyn compatible...
LL | async fn async_dispatch(&self);
| ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async`
= help: consider moving `async_dispatch` to another trait
= help: only type `&'static str` implements `AsyncTrait`; consider using it directly instead.
For more information about this error, try `rustc --explain E0277`.
error: aborting due to 2 previous errors; 1 warning emitted
For more information about this error, try `rustc --explain E0038`.