Skip to content

Commit 81c2385

Browse files
committed
trait_sel: MetaSized bounds in dispatchable check
Given the necessary additions of bounds to these traits and their impls in the standard library, it is necessary to add `MetaSized` bounds to the obligation which is proven as part of checking for dyn dispatchability.
1 parent 52c4478 commit 81c2385

File tree

1 file changed

+23
-9
lines changed

1 file changed

+23
-9
lines changed

compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
use std::ops::ControlFlow;
88

99
use rustc_errors::FatalError;
10-
use rustc_hir as hir;
1110
use rustc_hir::def_id::DefId;
11+
use rustc_hir::{self as hir, LangItem};
1212
use rustc_middle::bug;
1313
use rustc_middle::query::Providers;
1414
use rustc_middle::ty::{
@@ -540,11 +540,11 @@ fn receiver_for_self_ty<'tcx>(
540540
/// In practice, we cannot use `dyn Trait` explicitly in the obligation because it would result in
541541
/// a new check that `Trait` is dyn-compatible, creating a cycle.
542542
/// Instead, we emulate a placeholder by introducing a new type parameter `U` such that
543-
/// `Self: Unsize<U>` and `U: Trait + ?Sized`, and use `U` in place of `dyn Trait`.
543+
/// `Self: Unsize<U>` and `U: Trait + MetaSized`, and use `U` in place of `dyn Trait`.
544544
///
545545
/// Written as a chalk-style query:
546546
/// ```ignore (not-rust)
547-
/// forall (U: Trait + ?Sized) {
547+
/// forall (U: Trait + MetaSized) {
548548
/// if (Self: Unsize<U>) {
549549
/// Receiver: DispatchFromDyn<Receiver[Self => U]>
550550
/// }
@@ -564,9 +564,10 @@ fn receiver_is_dispatchable<'tcx>(
564564
) -> bool {
565565
debug!("receiver_is_dispatchable: method = {:?}, receiver_ty = {:?}", method, receiver_ty);
566566

567-
let traits = (tcx.lang_items().unsize_trait(), tcx.lang_items().dispatch_from_dyn_trait());
568-
let (Some(unsize_did), Some(dispatch_from_dyn_did)) = traits else {
569-
debug!("receiver_is_dispatchable: Missing Unsize or DispatchFromDyn traits");
567+
let (Some(unsize_did), Some(dispatch_from_dyn_did)) =
568+
(tcx.lang_items().unsize_trait(), tcx.lang_items().dispatch_from_dyn_trait())
569+
else {
570+
debug!("receiver_is_dispatchable: Missing `Unsize` or `DispatchFromDyn` traits");
570571
return false;
571572
};
572573

@@ -580,7 +581,7 @@ fn receiver_is_dispatchable<'tcx>(
580581
receiver_for_self_ty(tcx, receiver_ty, unsized_self_ty, method.def_id);
581582

582583
// create a modified param env, with `Self: Unsize<U>` and `U: Trait` added to caller bounds
583-
// `U: ?Sized` is already implied here
584+
// `U: MetaSized` is already implied here
584585
let param_env = {
585586
let param_env = tcx.param_env(method.def_id);
586587

@@ -598,8 +599,21 @@ fn receiver_is_dispatchable<'tcx>(
598599
ty::TraitRef::new_from_args(tcx, trait_def_id, args).upcast(tcx)
599600
};
600601

601-
let caller_bounds =
602-
param_env.caller_bounds().iter().chain([unsize_predicate, trait_predicate]);
602+
let metasized_predicate = {
603+
let metasized_did = tcx.require_lang_item(LangItem::MetaSized, None);
604+
ty::TraitRef::new(tcx, metasized_did, [unsized_self_ty]).upcast(tcx)
605+
};
606+
let pointeesized_predicate = {
607+
let pointeesized_did = tcx.require_lang_item(LangItem::PointeeSized, None);
608+
ty::TraitRef::new(tcx, pointeesized_did, [unsized_self_ty]).upcast(tcx)
609+
};
610+
611+
let caller_bounds = param_env.caller_bounds().iter().chain([
612+
unsize_predicate,
613+
metasized_predicate,
614+
pointeesized_predicate,
615+
trait_predicate,
616+
]);
603617

604618
ty::ParamEnv::new(tcx.mk_clauses_from_iter(caller_bounds))
605619
};

0 commit comments

Comments
 (0)