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

Commit bb80bba

Browse files
Make the implementation better
1 parent 3ee780b commit bb80bba

File tree

15 files changed

+325
-35
lines changed

15 files changed

+325
-35
lines changed

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

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

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

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1371,11 +1371,12 @@ rustc_queries! {
13711371
desc { |tcx| "checking if trait `{}` is dyn-compatible", tcx.def_path_str(trait_id) }
13721372
}
13731373

1374-
query trait_has_impl_which_may_shadow_dyn(trait_def_id:DefId) -> bool {
1374+
query trait_has_impl_which_may_shadow_dyn(key:(DefId,Option<DefId>)) -> bool {
13751375
desc {
13761376
|tcx| "checking if trait `{}` has an impl which may overlap with \
1377-
the built-in impl for trait objects",
1378-
tcx.def_path_str(trait_def_id)
1377+
the built-in impl for `dyn {}`",
1378+
tcx.def_path_str(key.0),
1379+
key.1.map_or(String::from("..."), |def_id| tcx.def_path_str(def_id)),
13791380
}
13801381
}
13811382

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -581,8 +581,12 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
581581
self.trait_def(trait_def_id).implement_via_object
582582
}
583583

584-
fn trait_has_impl_which_may_shadow_dyn(self, trait_def_id: DefId) -> bool {
585-
self.trait_has_impl_which_may_shadow_dyn(trait_def_id)
584+
fn trait_has_impl_which_may_shadow_dyn(
585+
self,
586+
trait_def_id: DefId,
587+
principal_def_id: Option<DefId>,
588+
) -> bool {
589+
self.trait_has_impl_which_may_shadow_dyn((trait_def_id, principal_def_id))
586590
}
587591

588592
fn is_impl_trait_in_trait(self, def_id: DefId) -> bool {

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,14 @@ where
8282
goal: Goal<I, Self>,
8383
assumption: I::Clause,
8484
) -> Result<Candidate<I>, NoSolution> {
85-
if ecx.cx().trait_has_impl_which_may_shadow_dyn(goal.predicate.trait_def_id(ecx.cx())) {
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+
) {
8693
return Err(NoSolution);
8794
}
8895

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -864,7 +864,12 @@ fn assemble_candidates_from_object_ty<'cx, 'tcx>(
864864
let env_predicates = data
865865
.projection_bounds()
866866
.filter(|bound| bound.item_def_id() == obligation.predicate.def_id)
867-
.filter(|bound| !tcx.trait_has_impl_which_may_shadow_dyn(bound.trait_def_id(tcx)))
867+
.filter(|bound| {
868+
!tcx.trait_has_impl_which_may_shadow_dyn((
869+
bound.trait_def_id(tcx),
870+
data.principal_def_id(),
871+
))
872+
})
868873
.map(|p| p.with_self_ty(tcx, object_ty).upcast(tcx));
869874

870875
assemble_candidates_from_predicates(

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -916,7 +916,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
916916
})
917917
})
918918
.filter(|(_, trait_ref)| {
919-
!tcx.trait_has_impl_which_may_shadow_dyn(trait_ref.def_id())
919+
!tcx.trait_has_impl_which_may_shadow_dyn((
920+
trait_ref.def_id(),
921+
Some(principal_trait_ref.def_id()),
922+
))
920923
})
921924
.map(|(idx, _)| ObjectCandidate(idx));
922925

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

Lines changed: 87 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
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};
1717
use rustc_hir::LangItem;
@@ -23,6 +23,8 @@ use rustc_middle::ty::print::PrintTraitRefExt as _;
2323
use rustc_middle::ty::{self, GenericArgsRef, ImplSubject, Ty, TyCtxt, TypeVisitableExt};
2424
use rustc_session::lint::builtin::{COHERENCE_LEAK_CHECK, ORDER_DEPENDENT_TRAIT_OBJECTS};
2525
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, sym};
26+
use rustc_type_ir::elaborate;
27+
use rustc_type_ir::fast_reject::{SimplifiedType, TreatParams, simplify_type};
2628
use specialization_graph::GraphExt;
2729
use tracing::{debug, instrument};
2830

@@ -482,20 +484,62 @@ fn report_conflicting_impls<'tcx>(
482484

483485
pub(super) fn trait_has_impl_which_may_shadow_dyn<'tcx>(
484486
tcx: TyCtxt<'tcx>,
485-
trait_def_id:DefId,
487+
(target_trait_def_id, principal_def_id):(DefId,Option<DefId>),
486488
) -> bool {
487489
// We only care about trait objects which have associated types.
488490
if !tcx
489-
.associated_items(trait_def_id)
491+
.associated_items(target_trait_def_id)
490492
.in_definition_order()
491493
.any(|item| item.kind == ty::AssocKind::Type)
492494
{
493495
return false;
494496
}
495497

496-
let mut has_impl = false;
497-
tcx.for_each_impl(trait_def_id, |impl_def_id| {
498-
if has_impl {
498+
let target_self_ty =
499+
principal_def_id.map_or(SimplifiedType::MarkerTraitObject, SimplifiedType::Trait);
500+
501+
let elaborated_supertraits =
502+
principal_def_id.into_iter().flat_map(|def_id| tcx.supertrait_def_ids(def_id)).collect();
503+
504+
trait_has_impl_inner(
505+
tcx,
506+
target_trait_def_id,
507+
target_self_ty,
508+
&elaborated_supertraits,
509+
&mut Default::default(),
510+
true,
511+
)
512+
}
513+
514+
fn trait_has_impl_inner<'tcx>(
515+
tcx: TyCtxt<'tcx>,
516+
target_trait_def_id: DefId,
517+
target_self_ty: SimplifiedType<DefId>,
518+
elaborated_supertraits: &FxHashSet<DefId>,
519+
seen_traits: &mut FxHashSet<DefId>,
520+
first_generation: bool,
521+
) -> bool {
522+
if tcx.is_lang_item(target_trait_def_id, LangItem::Sized) {
523+
return false;
524+
}
525+
526+
// If we've encountered a trait in a cycle, then let's just
527+
// consider it to be implemented defensively.
528+
if !seen_traits.insert(target_trait_def_id) {
529+
return true;
530+
}
531+
// Since we don't pass in the set of auto traits, and just the principal,
532+
// consider all auto traits implemented.
533+
if tcx.trait_is_auto(target_trait_def_id) {
534+
return true;
535+
}
536+
if !first_generation && elaborated_supertraits.contains(&target_trait_def_id) {
537+
return true;
538+
}
539+
540+
let mut has_offending_impl = false;
541+
tcx.for_each_impl(target_trait_def_id, |impl_def_id| {
542+
if has_offending_impl {
499543
return;
500544
}
501545

@@ -504,33 +548,51 @@ pub(super) fn trait_has_impl_which_may_shadow_dyn<'tcx>(
504548
.expect("impl must have trait ref")
505549
.instantiate_identity()
506550
.self_ty();
507-
if self_ty.is_known_rigid() {
508-
return;
509-
}
510551

511-
let sized_trait = tcx.require_lang_item(LangItem::Sized, None);
512-
if tcx
513-
.param_env(impl_def_id)
514-
.caller_bounds()
515-
.iter()
516-
.filter_map(|clause| clause.as_trait_clause())
517-
.any(|bound| bound.def_id() == sized_trait && bound.self_ty().skip_binder() == self_ty)
552+
if simplify_type(tcx, self_ty, TreatParams::InstantiateWithInfer)
553+
.is_some_and(|simp| simp != target_self_ty)
518554
{
519555
return;
520556
}
521557

522-
if let ty::Alias(ty::Projection, alias_ty) = self_ty.kind()
523-
&& tcx
524-
.item_super_predicates(alias_ty.def_id)
525-
.iter_identity()
526-
.filter_map(|clause| clause.as_trait_clause())
527-
.any(|bound| bound.def_id() == sized_trait)
558+
for (pred, _) in
559+
elaborate::elaborate(tcx, tcx.predicates_of(impl_def_id).instantiate_identity(tcx))
528560
{
529-
return;
561+
if let ty::ClauseKind::Trait(trait_pred) = pred.kind().skip_binder()
562+
&& trait_pred.self_ty() == self_ty
563+
&& !trait_has_impl_inner(
564+
tcx,
565+
trait_pred.def_id(),
566+
target_self_ty,
567+
elaborated_supertraits,
568+
seen_traits,
569+
false,
570+
)
571+
{
572+
return;
573+
}
574+
}
575+
576+
if let ty::Alias(ty::Projection, alias_ty) = self_ty.kind() {
577+
for pred in tcx.item_super_predicates(alias_ty.def_id).iter_identity() {
578+
if let ty::ClauseKind::Trait(trait_pred) = pred.kind().skip_binder()
579+
&& trait_pred.self_ty() == self_ty
580+
&& !trait_has_impl_inner(
581+
tcx,
582+
trait_pred.def_id(),
583+
target_self_ty,
584+
elaborated_supertraits,
585+
seen_traits,
586+
false,
587+
)
588+
{
589+
return;
590+
}
591+
}
530592
}
531593

532-
has_impl = true;
594+
has_offending_impl = true;
533595
});
534596

535-
has_impl
597+
has_offending_impl
536598
}

‎compiler/rustc_type_ir/src/interner.rs‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,11 @@ pub trait Interner:
274274

275275
fn trait_may_be_implemented_via_object(self, trait_def_id: Self::DefId) -> bool;
276276

277-
fn trait_has_impl_which_may_shadow_dyn(self, trait_def_id: Self::DefId) -> bool;
277+
fn trait_has_impl_which_may_shadow_dyn(
278+
self,
279+
trait_def_id: Self::DefId,
280+
principal_def_id: Option<Self::DefId>,
281+
) -> bool;
278282

279283
fn is_impl_trait_in_trait(self, def_id: Self::DefId) -> bool;
280284

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//@ check-pass
2+
3+
// Make sure that if we don't disqualify a built-in object impl
4+
// due to a blanket with a trait bound that will never apply to
5+
// the object.
6+
7+
pub trait SimpleService {
8+
type Resp;
9+
}
10+
11+
trait Service {
12+
type Resp;
13+
}
14+
15+
impl<S> Service for S where S: SimpleService + ?Sized {
16+
type Resp = <S as SimpleService>::Resp;
17+
}
18+
19+
fn implements_service(x: &(impl Service<Resp = ()> + ?Sized)) {}
20+
21+
fn test(x: &dyn Service<Resp = ()>) {
22+
implements_service(x);
23+
}
24+
25+
fn main() {}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
trait Trait {
2+
type Assoc;
3+
fn generate(&self) -> Self::Assoc;
4+
}
5+
6+
trait Other {}
7+
8+
impl<S> Trait for S where S: Other + ?Sized {
9+
type Assoc = &'static str;
10+
fn generate(&self) -> Self::Assoc { "hi" }
11+
}
12+
13+
trait Downstream: Trait<Assoc = usize> {}
14+
impl<T> Other for T where T: ?Sized + Downstream + OnlyDyn {}
15+
16+
trait OnlyDyn {}
17+
impl OnlyDyn for dyn Downstream {}
18+
19+
struct Concrete;
20+
impl Trait for Concrete {
21+
type Assoc = usize;
22+
fn generate(&self) -> Self::Assoc { 42 }
23+
}
24+
impl Downstream for Concrete {}
25+
26+
fn test<T: ?Sized + Other>(x: &T) {
27+
let s: &str = x.generate();
28+
println!("{s}");
29+
}
30+
31+
fn impl_downstream<T: ?Sized + Downstream>(x: &T) {}
32+
33+
fn main() {
34+
let x: &dyn Downstream = &Concrete;
35+
36+
test(x); // This call used to segfault.
37+
//~^ ERROR type mismatch resolving
38+
39+
// This no longer holds since `Downstream: Trait<Assoc = usize>`,
40+
// but the `Trait<Assoc = &'static str>` blanket impl now shadows.
41+
impl_downstream(x);
42+
//~^ ERROR type mismatch resolving
43+
}

0 commit comments

Comments
(0)

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