Skip to content

Remove existing AFIDT implementation #138670

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
5 changes: 1 addition & 4 deletions compiler/rustc_middle/src/ty/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {:?} {:?}",
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down

This file was deleted.

50 changes: 2 additions & 48 deletions compiler/rustc_mir_transform/src/shim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down Expand Up @@ -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));

Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -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
Expand Down
28 changes: 2 additions & 26 deletions compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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()
}
Expand Down
58 changes: 1 addition & 57 deletions compiler/rustc_trait_selection/src/traits/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand All @@ -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::{
Expand Down Expand Up @@ -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>),
}
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
25 changes: 0 additions & 25 deletions compiler/rustc_ty_utils/src/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down
7 changes: 0 additions & 7 deletions tests/crashes/136286.rs

This file was deleted.

Loading
Loading