Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 1a961a0

Browse files
committed
Auto merge of rust-lang#132289 - compiler-errors:vanquish-dyn-incompleteness, r=<try>
Disqualify built-in trait impl if it seems likely to overlap in an unsound way with a blanket impl cc rust-lang#57893 r? lcnr
2 parents 2d0ea79 + bb80bba commit 1a961a0

22 files changed

+453
-20
lines changed

‎compiler/rustc_middle/src/query/keys.rs‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,14 @@ impl Key for (DefId, SimplifiedType) {
320320
}
321321
}
322322

323+
impl Key for (DefId, Option<DefId>) {
324+
type Cache<V> = DefaultCache<Self, V>;
325+
326+
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
327+
self.0.default_span(tcx)
328+
}
329+
}
330+
323331
impl<'tcx> Key for GenericArgsRef<'tcx> {
324332
type Cache<V> = DefaultCache<Self, V>;
325333

‎compiler/rustc_middle/src/query/mod.rs‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1370,6 +1370,15 @@ rustc_queries! {
13701370
desc { |tcx| "checking if trait `{}` is dyn-compatible", tcx.def_path_str(trait_id) }
13711371
}
13721372

1373+
query trait_has_impl_which_may_shadow_dyn(key: (DefId, Option<DefId>)) -> bool {
1374+
desc {
1375+
|tcx| "checking if trait `{}` has an impl which may overlap with \
1376+
the built-in impl for `dyn {}`",
1377+
tcx.def_path_str(key.0),
1378+
key.1.map_or(String::from("..."), |def_id| tcx.def_path_str(def_id)),
1379+
}
1380+
}
1381+
13731382
/// Gets the ParameterEnvironment for a given item; this environment
13741383
/// will be in "user-facing" mode, meaning that it is suitable for
13751384
/// type-checking etc, and it does not normalize specializable

‎compiler/rustc_middle/src/ty/context.rs‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,14 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
578578
self.trait_def(trait_def_id).implement_via_object
579579
}
580580

581+
fn trait_has_impl_which_may_shadow_dyn(
582+
self,
583+
trait_def_id: DefId,
584+
principal_def_id: Option<DefId>,
585+
) -> bool {
586+
self.trait_has_impl_which_may_shadow_dyn((trait_def_id, principal_def_id))
587+
}
588+
581589
fn is_impl_trait_in_trait(self, def_id: DefId) -> bool {
582590
self.is_impl_trait_in_trait(def_id)
583591
}

‎compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,17 @@ where
8282
goal: Goal<I, Self>,
8383
assumption: I::Clause,
8484
) -> Result<Candidate<I>, NoSolution> {
85+
let ty::Dynamic(data, _, _) = goal.predicate.self_ty().kind() else {
86+
unreachable!();
87+
};
88+
89+
if ecx.cx().trait_has_impl_which_may_shadow_dyn(
90+
goal.predicate.trait_def_id(ecx.cx()),
91+
data.principal_def_id(),
92+
) {
93+
return Err(NoSolution);
94+
}
95+
8596
Self::probe_and_match_goal_against_assumption(ecx, source, goal, assumption, |ecx| {
8697
let cx = ecx.cx();
8798
let ty::Dynamic(bounds, _, _) = goal.predicate.self_ty().kind() else {

‎compiler/rustc_trait_selection/src/traits/mod.rs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -824,6 +824,7 @@ pub fn provide(providers: &mut Providers) {
824824
specialization_graph_of: specialize::specialization_graph_provider,
825825
specializes: specialize::specializes,
826826
specialization_enabled_in: specialize::specialization_enabled_in,
827+
trait_has_impl_which_may_shadow_dyn: specialize::trait_has_impl_which_may_shadow_dyn,
827828
instantiate_and_check_impossible_predicates,
828829
is_impossible_associated_item,
829830
..*providers

‎compiler/rustc_trait_selection/src/traits/project.rs‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -842,6 +842,12 @@ fn assemble_candidates_from_object_ty<'cx, 'tcx>(
842842
let env_predicates = data
843843
.projection_bounds()
844844
.filter(|bound| bound.item_def_id() == obligation.predicate.def_id)
845+
.filter(|bound| {
846+
!tcx.trait_has_impl_which_may_shadow_dyn((
847+
bound.trait_def_id(tcx),
848+
data.principal_def_id(),
849+
))
850+
})
845851
.map(|p| p.with_self_ty(tcx, object_ty).upcast(tcx));
846852

847853
assemble_candidates_from_predicates(

‎compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs‎

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -855,7 +855,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
855855
"assemble_candidates_from_object_ty",
856856
);
857857

858-
if !self.tcx().trait_def(obligation.predicate.def_id()).implement_via_object {
858+
let tcx = self.tcx();
859+
if !tcx.trait_def(obligation.predicate.def_id()).implement_via_object {
859860
return;
860861
}
861862

@@ -876,9 +877,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
876877

877878
if let Some(principal) = data.principal() {
878879
if !self.infcx.tcx.features().dyn_compatible_for_dispatch() {
879-
principal.with_self_ty(self.tcx(), self_ty)
880-
} else if self.tcx().is_dyn_compatible(principal.def_id()) {
881-
principal.with_self_ty(self.tcx(), self_ty)
880+
principal.with_self_ty(tcx, self_ty)
881+
} else if tcx.is_dyn_compatible(principal.def_id()) {
882+
principal.with_self_ty(tcx, self_ty)
882883
} else {
883884
return;
884885
}
@@ -902,7 +903,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
902903
// correct trait, but also the correct type parameters.
903904
// For example, we may be trying to upcast `Foo` to `Bar<i32>`,
904905
// but `Foo` is declared as `trait Foo: Bar<u32>`.
905-
let candidate_supertraits = util::supertraits(self.tcx(), principal_trait_ref)
906+
let candidate_supertraits = util::supertraits(tcx, principal_trait_ref)
906907
.enumerate()
907908
.filter(|&(_, upcast_trait_ref)| {
908909
self.infcx.probe(|_| {
@@ -914,6 +915,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
914915
.is_ok()
915916
})
916917
})
918+
.filter(|(_, trait_ref)| {
919+
!tcx.trait_has_impl_which_may_shadow_dyn((
920+
trait_ref.def_id(),
921+
Some(principal_trait_ref.def_id()),
922+
))
923+
})
917924
.map(|(idx, _)| ObjectCandidate(idx));
918925

919926
candidates.vec.extend(candidate_supertraits);

‎compiler/rustc_trait_selection/src/traits/specialize/mod.rs‎

Lines changed: 119 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@
1111
1212
pub mod specialization_graph;
1313

14-
use rustc_data_structures::fx::FxIndexSet;
14+
use rustc_data_structures::fx::{FxHashSet,FxIndexSet};
1515
use rustc_errors::codes::*;
1616
use rustc_errors::{Diag, EmissionGuarantee};
17+
use rustc_hir::LangItem;
1718
use rustc_hir::def_id::{DefId, LocalDefId};
1819
use rustc_infer::infer::DefineOpaqueTypes;
1920
use rustc_middle::bug;
@@ -24,6 +25,8 @@ use rustc_middle::ty::{
2425
};
2526
use rustc_session::lint::builtin::{COHERENCE_LEAK_CHECK, ORDER_DEPENDENT_TRAIT_OBJECTS};
2627
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, sym};
28+
use rustc_type_ir::elaborate;
29+
use rustc_type_ir::fast_reject::{SimplifiedType, TreatParams, simplify_type};
2730
use specialization_graph::GraphExt;
2831
use tracing::{debug, instrument};
2932

@@ -480,3 +483,118 @@ fn report_conflicting_impls<'tcx>(
480483
}
481484
}
482485
}
486+
487+
pub(super) fn trait_has_impl_which_may_shadow_dyn<'tcx>(
488+
tcx: TyCtxt<'tcx>,
489+
(target_trait_def_id, principal_def_id): (DefId, Option<DefId>),
490+
) -> bool {
491+
// We only care about trait objects which have associated types.
492+
if !tcx
493+
.associated_items(target_trait_def_id)
494+
.in_definition_order()
495+
.any(|item| item.kind == ty::AssocKind::Type)
496+
{
497+
return false;
498+
}
499+
500+
let target_self_ty =
501+
principal_def_id.map_or(SimplifiedType::MarkerTraitObject, SimplifiedType::Trait);
502+
503+
let elaborated_supertraits =
504+
principal_def_id.into_iter().flat_map(|def_id| tcx.supertrait_def_ids(def_id)).collect();
505+
506+
trait_has_impl_inner(
507+
tcx,
508+
target_trait_def_id,
509+
target_self_ty,
510+
&elaborated_supertraits,
511+
&mut Default::default(),
512+
true,
513+
)
514+
}
515+
516+
fn trait_has_impl_inner<'tcx>(
517+
tcx: TyCtxt<'tcx>,
518+
target_trait_def_id: DefId,
519+
target_self_ty: SimplifiedType<DefId>,
520+
elaborated_supertraits: &FxHashSet<DefId>,
521+
seen_traits: &mut FxHashSet<DefId>,
522+
first_generation: bool,
523+
) -> bool {
524+
if tcx.is_lang_item(target_trait_def_id, LangItem::Sized) {
525+
return false;
526+
}
527+
528+
// If we've encountered a trait in a cycle, then let's just
529+
// consider it to be implemented defensively.
530+
if !seen_traits.insert(target_trait_def_id) {
531+
return true;
532+
}
533+
// Since we don't pass in the set of auto traits, and just the principal,
534+
// consider all auto traits implemented.
535+
if tcx.trait_is_auto(target_trait_def_id) {
536+
return true;
537+
}
538+
if !first_generation && elaborated_supertraits.contains(&target_trait_def_id) {
539+
return true;
540+
}
541+
542+
let mut has_offending_impl = false;
543+
tcx.for_each_impl(target_trait_def_id, |impl_def_id| {
544+
if has_offending_impl {
545+
return;
546+
}
547+
548+
let self_ty = tcx
549+
.impl_trait_ref(impl_def_id)
550+
.expect("impl must have trait ref")
551+
.instantiate_identity()
552+
.self_ty();
553+
554+
if simplify_type(tcx, self_ty, TreatParams::InstantiateWithInfer)
555+
.is_some_and(|simp| simp != target_self_ty)
556+
{
557+
return;
558+
}
559+
560+
for (pred, _) in
561+
elaborate::elaborate(tcx, tcx.predicates_of(impl_def_id).instantiate_identity(tcx))
562+
{
563+
if let ty::ClauseKind::Trait(trait_pred) = pred.kind().skip_binder()
564+
&& trait_pred.self_ty() == self_ty
565+
&& !trait_has_impl_inner(
566+
tcx,
567+
trait_pred.def_id(),
568+
target_self_ty,
569+
elaborated_supertraits,
570+
seen_traits,
571+
false,
572+
)
573+
{
574+
return;
575+
}
576+
}
577+
578+
if let ty::Alias(ty::Projection, alias_ty) = self_ty.kind() {
579+
for pred in tcx.item_super_predicates(alias_ty.def_id).iter_identity() {
580+
if let ty::ClauseKind::Trait(trait_pred) = pred.kind().skip_binder()
581+
&& trait_pred.self_ty() == self_ty
582+
&& !trait_has_impl_inner(
583+
tcx,
584+
trait_pred.def_id(),
585+
target_self_ty,
586+
elaborated_supertraits,
587+
seen_traits,
588+
false,
589+
)
590+
{
591+
return;
592+
}
593+
}
594+
}
595+
596+
has_offending_impl = true;
597+
});
598+
599+
has_offending_impl
600+
}

‎compiler/rustc_type_ir/src/interner.rs‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,12 @@ pub trait Interner:
269269

270270
fn trait_may_be_implemented_via_object(self, trait_def_id: Self::DefId) -> bool;
271271

272+
fn trait_has_impl_which_may_shadow_dyn(
273+
self,
274+
trait_def_id: Self::DefId,
275+
principal_def_id: Option<Self::DefId>,
276+
) -> bool;
277+
272278
fn is_impl_trait_in_trait(self, def_id: Self::DefId) -> bool;
273279

274280
fn delay_bug(self, msg: impl ToString) -> Self::ErrorGuaranteed;

‎compiler/rustc_type_ir/src/predicate.rs‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,10 @@ impl<I: Interner> ty::Binder<I, ExistentialProjection<I>> {
433433
pub fn item_def_id(&self) -> I::DefId {
434434
self.skip_binder().def_id
435435
}
436+
437+
pub fn trait_def_id(self, interner: I) -> I::DefId {
438+
interner.parent(self.skip_binder().def_id)
439+
}
436440
}
437441

438442
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /