Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 22a8823

Browse files
committed
Auto merge of rust-lang#133397 - compiler-errors:fix-dyn-incompleteness, r=<try>
Fix dyn incompleteness with multiple supertraits with different substitutions So much to write about this. Fixes rust-lang#133361 r? `@ghost`
2 parents 96e51d9 + 753da78 commit 22a8823

File tree

73 files changed

+1324
-936
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+1324
-936
lines changed

compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs

Lines changed: 233 additions & 139 deletions
Large diffs are not rendered by default.

compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs

Lines changed: 144 additions & 146 deletions
Large diffs are not rendered by default.

compiler/rustc_hir_typeck/src/closure.rs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use rustc_span::def_id::LocalDefId;
1818
use rustc_span::{DUMMY_SP, Span};
1919
use rustc_trait_selection::error_reporting::traits::ArgKind;
2020
use rustc_trait_selection::traits;
21-
use rustc_type_ir::ClosureKind;
21+
use rustc_type_ir::{ClosureKind, Upcast as _};
2222
use tracing::{debug, instrument, trace};
2323

2424
use super::{CoroutineTypes, Expectation, FnCtxt, check_fn};
@@ -312,16 +312,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
312312
.iter_instantiated_copied(self.tcx, args)
313313
.map(|(c, s)| (c.as_predicate(), s)),
314314
),
315-
ty::Dynamic(object_type, ..) => {
316-
let sig = object_type.projection_bounds().find_map(|pb| {
317-
let pb = pb.with_self_ty(self.tcx, self.tcx.types.trait_object_dummy_self);
318-
self.deduce_sig_from_projection(None, closure_kind, pb)
319-
});
320-
let kind = object_type
321-
.principal_def_id()
322-
.and_then(|did| self.tcx.fn_trait_kind_from_def_id(did));
323-
(sig, kind)
324-
}
315+
ty::Dynamic(data, ..) => self.deduce_closure_signature_from_predicates(
316+
self.tcx.types.trait_object_dummy_self,
317+
closure_kind,
318+
data.iter().map(|bound| {
319+
(
320+
bound
321+
.with_self_ty(self.tcx, self.tcx.types.trait_object_dummy_self)
322+
.upcast(self.tcx),
323+
DUMMY_SP,
324+
)
325+
}),
326+
),
325327
ty::Infer(ty::TyVar(vid)) => self.deduce_closure_signature_from_predicates(
326328
Ty::new_var(self.tcx, self.root_var(vid)),
327329
closure_kind,

compiler/rustc_hir_typeck/src/method/probe.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use std::cell::{Cell, RefCell};
22
use std::cmp::max;
3-
use std::iter;
43
use std::ops::Deref;
54

65
use rustc_data_structures::fx::FxHashSet;
@@ -901,11 +900,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
901900

902901
if self.tcx.is_trait_alias(trait_def_id) {
903902
// For trait aliases, recursively assume all explicitly named traits are relevant
904-
for expansion in traits::expand_trait_aliases(
905-
self.tcx,
906-
iter::once((ty::Binder::dummy(trait_ref), self.span)),
907-
) {
908-
let bound_trait_ref = expansion.trait_ref();
903+
for (bound_trait_pred, _) in
904+
traits::expand_trait_aliases(self.tcx, [(trait_ref.upcast(self.tcx), self.span)]).0
905+
{
906+
assert_eq!(bound_trait_pred.polarity(), ty::PredicatePolarity::Positive);
907+
let bound_trait_ref = bound_trait_pred.map_bound(|pred| pred.trait_ref);
909908
for item in self.impl_or_trait_item(bound_trait_ref.def_id()) {
910909
if !self.has_applicable_self(&item) {
911910
self.record_static_candidate(CandidateSource::Trait(

compiler/rustc_lint_defs/src/builtin.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ declare_lint_pass! {
3939
DEPRECATED_SAFE_2024,
4040
DEPRECATED_WHERE_CLAUSE_LOCATION,
4141
DUPLICATE_MACRO_ATTRIBUTES,
42+
DYN_ASSOC_REDUNDANT,
43+
DYN_ASSOC_SHADOWED,
4244
ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT,
4345
ELIDED_LIFETIMES_IN_PATHS,
4446
ELIDED_NAMED_LIFETIMES,
@@ -5112,6 +5114,20 @@ declare_lint! {
51125114
crate_level_only
51135115
}
51145116

5117+
declare_lint! {
5118+
/// Hi
5119+
pub DYN_ASSOC_REDUNDANT,
5120+
Warn,
5121+
"oops",
5122+
}
5123+
5124+
declare_lint! {
5125+
/// Hi
5126+
pub DYN_ASSOC_SHADOWED,
5127+
Deny,
5128+
"oops",
5129+
}
5130+
51155131
declare_lint! {
51165132
/// The `abi_unsupported_vector_types` lint detects function definitions and calls
51175133
/// whose ABI depends on enabling certain target features, but those features are not enabled.

compiler/rustc_middle/src/ty/relate.rs

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -80,19 +80,12 @@ impl<'tcx> Relate<TyCtxt<'tcx>> for &'tcx ty::List<ty::PolyExistentialPredicate<
8080
) -> RelateResult<'tcx, Self> {
8181
let tcx = relation.cx();
8282

83-
// FIXME: this is wasteful, but want to do a perf run to see how slow it is.
84-
// We need to perform this deduplication as we sometimes generate duplicate projections
85-
// in `a`.
86-
let mut a_v: Vec<_> = a.into_iter().collect();
87-
let mut b_v: Vec<_> = b.into_iter().collect();
88-
a_v.dedup();
89-
b_v.dedup();
90-
if a_v.len() != b_v.len() {
83+
if a.len() != b.len() {
9184
return Err(TypeError::ExistentialMismatch(ExpectedFound::new(a, b)));
9285
}
9386

94-
let v = iter::zip(a_v, b_v).map(|(ep_a, ep_b)| {
95-
match (ep_a.skip_binder(), ep_b.skip_binder()) {
87+
let v =
88+
iter::zip(a, b).map(|(ep_a, ep_b)| match (ep_a.skip_binder(), ep_b.skip_binder()) {
9689
(ty::ExistentialPredicate::Trait(a), ty::ExistentialPredicate::Trait(b)) => {
9790
Ok(ep_a.rebind(ty::ExistentialPredicate::Trait(
9891
relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(),
@@ -109,8 +102,7 @@ impl<'tcx> Relate<TyCtxt<'tcx>> for &'tcx ty::List<ty::PolyExistentialPredicate<
109102
ty::ExistentialPredicate::AutoTrait(b),
110103
) if a == b => Ok(ep_a.rebind(ty::ExistentialPredicate::AutoTrait(a))),
111104
_ => Err(TypeError::ExistentialMismatch(ExpectedFound::new(a, b))),
112-
}
113-
});
105+
});
114106
tcx.mk_poly_existential_predicates_from_iter(v)
115107
}
116108
}

compiler/rustc_middle/src/ty/sty.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -978,6 +978,10 @@ impl<'tcx> rustc_type_ir::inherent::Ty<TyCtxt<'tcx>> for Ty<'tcx> {
978978
fn async_destructor_ty(self, interner: TyCtxt<'tcx>) -> Ty<'tcx> {
979979
self.async_destructor_ty(interner)
980980
}
981+
982+
fn is_self_param(self) -> bool {
983+
self.is_param(0)
984+
}
981985
}
982986

983987
/// Type utilities

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -696,6 +696,15 @@ where
696696
assumption.upcast(cx),
697697
));
698698
}
699+
700+
for assumption in elaborate::implied_supertrait_projections(cx, principal) {
701+
candidates.extend(G::probe_and_consider_object_bound_candidate(
702+
self,
703+
CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
704+
goal,
705+
assumption.with_self_ty(cx, self_ty).upcast(cx),
706+
));
707+
}
699708
}
700709
}
701710

compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
44
use derive_where::derive_where;
55
use rustc_ast_ir::{Movability, Mutability};
6-
use rustc_type_ir::data_structures::HashMap;
6+
use rustc_type_ir::data_structures::{HashMap, HashSet};
77
use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
88
use rustc_type_ir::inherent::*;
99
use rustc_type_ir::lang_items::TraitSolverLangItem;
@@ -841,6 +841,14 @@ where
841841
.map(|(pred, _)| pred),
842842
));
843843

844+
// It's sufficient to just keep track of the def ids of the explicitly specified
845+
// associated types since when users write `dyn Trait<Assoc = T>`, that associated
846+
// type must resolve to *one* bound from all of the supertraits. So the fact that
847+
// there is a user-provided projection is enough proof that it's unique and we don't
848+
// need to care about substitutions or anything like that.
849+
let specified_associated_projections: HashSet<_> =
850+
object_bounds.projection_bounds().into_iter().map(|proj| proj.item_def_id()).collect();
851+
844852
// FIXME(associated_const_equality): Also add associated consts to
845853
// the requirements here.
846854
for associated_type_def_id in cx.associated_type_def_ids(trait_ref.def_id) {
@@ -850,6 +858,11 @@ where
850858
continue;
851859
}
852860

861+
// We don't require these bounds to hold for supertrait implied projection bounds.
862+
if !specified_associated_projections.contains(&associated_type_def_id) {
863+
continue;
864+
}
865+
853866
requirements
854867
.extend(cx.item_bounds(associated_type_def_id).iter_instantiated(cx, trait_ref.args));
855868
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,8 @@ pub fn report_dyn_incompatibility<'tcx>(
436436
tcx.dcx(),
437437
span,
438438
E0038,
439-
"the trait `{}` cannot be made into an object",
439+
"the {} `{}` cannot be made into an object",
440+
tcx.def_descr(trait_def_id),
440441
trait_str
441442
);
442443
err.span_label(span, format!("`{trait_str}` cannot be made into an object"));

compiler/rustc_trait_selection/src/traits/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,9 @@ pub use self::specialize::{
6666
};
6767
pub use self::structural_normalize::StructurallyNormalizeExt;
6868
pub use self::util::{
69-
BoundVarReplacer, PlaceholderReplacer, TraitAliasExpander, TraitAliasExpansionInfo, elaborate,
70-
expand_trait_aliases, impl_item_is_final, supertraits,
71-
transitive_bounds_that_define_assoc_item, upcast_choices, with_replaced_escaping_bound_vars,
69+
BoundVarReplacer, PlaceholderReplacer, elaborate, expand_trait_aliases, impl_item_is_final,
70+
supertraits, transitive_bounds_that_define_assoc_item, upcast_choices,
71+
with_replaced_escaping_bound_vars,
7272
};
7373
use crate::error_reporting::InferCtxtErrorExt;
7474
use crate::infer::outlives::env::OutlivesEnvironment;

compiler/rustc_trait_selection/src/traits/project.rs

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use rustc_middle::ty::visit::TypeVisitableExt;
1818
use rustc_middle::ty::{self, Term, Ty, TyCtxt, TypingMode, Upcast};
1919
use rustc_middle::{bug, span_bug};
2020
use rustc_span::symbol::sym;
21+
use rustc_type_ir::elaborate;
2122
use tracing::{debug, instrument};
2223

2324
use super::{
@@ -59,7 +60,7 @@ enum ProjectionCandidate<'tcx> {
5960
TraitDef(ty::PolyProjectionPredicate<'tcx>),
6061

6162
/// Bounds specified on an object type
62-
Object(ty::PolyProjectionPredicate<'tcx>),
63+
Object(ty::PolyProjectionPredicate<'tcx>, bool),
6364

6465
/// From an "impl" (or a "pseudo-impl" returned by select)
6566
Select(Selection<'tcx>),
@@ -658,7 +659,7 @@ fn project<'cx, 'tcx>(
658659

659660
assemble_candidates_from_object_ty(selcx, obligation, &mut candidates);
660661

661-
if let ProjectionCandidateSet::Single(ProjectionCandidate::Object(_)) = candidates {
662+
if let ProjectionCandidateSet::Single(ProjectionCandidate::Object(..)) = candidates {
662663
// Avoid normalization cycle from selection (see
663664
// `assemble_candidates_from_object_ty`).
664665
// FIXME(lazy_normalization): Lazy normalization should save us from
@@ -814,6 +815,7 @@ fn assemble_candidates_from_object_ty<'cx, 'tcx>(
814815
}
815816
_ => return,
816817
};
818+
817819
let env_predicates = data
818820
.projection_bounds()
819821
.filter(|bound| bound.item_def_id() == obligation.predicate.def_id)
@@ -823,10 +825,22 @@ fn assemble_candidates_from_object_ty<'cx, 'tcx>(
823825
selcx,
824826
obligation,
825827
candidate_set,
826-
ProjectionCandidate::Object,
828+
|c| ProjectionCandidate::Object(c, false),
827829
env_predicates,
828830
false,
829831
);
832+
833+
if let Some(principal) = data.principal() {
834+
assemble_candidates_from_predicates(
835+
selcx,
836+
obligation,
837+
candidate_set,
838+
|c| ProjectionCandidate::Object(c, true),
839+
elaborate::implied_supertrait_projections(tcx, principal)
840+
.map(|pred| pred.with_self_ty(tcx, object_ty).upcast(tcx)),
841+
true,
842+
);
843+
}
830844
}
831845

832846
#[instrument(
@@ -1235,10 +1249,12 @@ fn confirm_candidate<'cx, 'tcx>(
12351249
) -> Progress<'tcx> {
12361250
debug!(?obligation, ?candidate, "confirm_candidate");
12371251
let mut progress = match candidate {
1238-
ProjectionCandidate::ParamEnv(poly_projection)
1239-
| ProjectionCandidate::Object(poly_projection) => {
1252+
ProjectionCandidate::ParamEnv(poly_projection) => {
12401253
confirm_param_env_candidate(selcx, obligation, poly_projection, false)
12411254
}
1255+
ProjectionCandidate::Object(poly_projection, from_super) => {
1256+
confirm_param_env_candidate(selcx, obligation, poly_projection, from_super)
1257+
}
12421258

12431259
ProjectionCandidate::TraitDef(poly_projection) => {
12441260
confirm_param_env_candidate(selcx, obligation, poly_projection, true)

0 commit comments

Comments
 (0)