Skip to content

Commit 3165a83

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 a45391f + 22cb94a commit 3165a83

File tree

23 files changed

+369
-241
lines changed

23 files changed

+369
-241
lines changed

compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs

+58-30
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,14 @@ use rustc_errors::codes::*;
33
use rustc_errors::struct_span_code_err;
44
use rustc_hir as hir;
55
use rustc_hir::def::{DefKind, Res};
6-
use rustc_hir::def_id::DefId;
76
use rustc_lint_defs::builtin::UNUSED_ASSOCIATED_TYPE_BOUNDS;
87
use rustc_middle::span_bug;
98
use rustc_middle::ty::fold::BottomUpFolder;
109
use rustc_middle::ty::{
1110
self, DynKind, ExistentialPredicateStableCmpExt as _, Ty, TyCtxt, TypeFoldable,
1211
TypeVisitableExt, Upcast,
1312
};
14-
use rustc_span::{ErrorGuaranteed, Span};
13+
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
1514
use rustc_trait_selection::error_reporting::traits::report_dyn_incompatibility;
1615
use rustc_trait_selection::traits::{self, hir_ty_lowering_dyn_compatibility_violations};
1716
use rustc_type_ir::elaborate::ClauseWithSupertraitSpan;
@@ -62,7 +61,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
6261
}
6362

6463
let mut trait_bounds = vec![];
65-
let mut projection_bounds = vec![];
64+
let mut projection_bounds = FxIndexMap::default();
6665
for (pred, span) in bounds.clauses() {
6766
let bound_pred = pred.kind();
6867
match bound_pred.skip_binder() {
@@ -71,7 +70,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
7170
trait_bounds.push((bound_pred.rebind(trait_pred.trait_ref), span));
7271
}
7372
ty::ClauseKind::Projection(proj) => {
74-
projection_bounds.push((bound_pred.rebind(proj), span));
73+
let anon = tcx.anonymize_bound_vars(bound_pred.rebind(proj));
74+
projection_bounds.insert(anon, (bound_pred.rebind(proj), span));
7575
}
7676
ty::ClauseKind::TypeOutlives(_) => {
7777
// Do nothing, we deal with regions separately
@@ -88,8 +88,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
8888

8989
// Expand trait aliases recursively and check that only one regular (non-auto) trait
9090
// is used and no 'maybe' bounds are used.
91-
let expanded_traits =
92-
traits::expand_trait_aliases(tcx, trait_bounds.iter().map(|&(a, b)| (a, b)));
91+
let mut trait_alias_projection_bounds = FxIndexSet::default();
92+
let expanded_traits = traits::expand_trait_aliases(
93+
tcx,
94+
&mut trait_alias_projection_bounds,
95+
trait_bounds.iter().map(|&(a, b)| (a, b)),
96+
);
9397

9498
let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) =
9599
expanded_traits.partition(|i| tcx.trait_is_auto(i.trait_ref().def_id()));
@@ -128,12 +132,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
128132
}
129133
}
130134

131-
let mut associated_types: FxIndexMap<Span, FxIndexSet<DefId>> = FxIndexMap::default();
135+
let mut needed_associated_types = FxIndexSet::default();
132136

137+
let principal_span = regular_traits.first().map_or(DUMMY_SP, |info| info.bottom().1);
133138
let regular_traits_refs_spans = trait_bounds
134139
.into_iter()
135140
.filter(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id()));
136141

142+
let mut implied_projection_bounds = vec![];
137143
for (base_trait_ref, original_span) in regular_traits_refs_spans {
138144
let base_pred: ty::Predicate<'tcx> = base_trait_ref.upcast(tcx);
139145
for ClauseWithSupertraitSpan { pred, supertrait_span } in
@@ -145,17 +151,28 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
145151
let bound_predicate = pred.kind();
146152
match bound_predicate.skip_binder() {
147153
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
148-
let pred = bound_predicate.rebind(pred);
149-
associated_types.entry(original_span).or_default().extend(
150-
tcx.associated_items(pred.def_id())
154+
// FIXME(negative_bounds): Handle this correctly...
155+
let trait_ref =
156+
tcx.anonymize_bound_vars(bound_predicate.rebind(pred.trait_ref));
157+
needed_associated_types.extend(
158+
tcx.associated_items(trait_ref.def_id())
151159
.in_definition_order()
152160
.filter(|item| item.kind == ty::AssocKind::Type)
153161
.filter(|item| !item.is_impl_trait_in_trait())
154-
.map(|item| item.def_id),
162+
// If the associated type has a `where Self: Sized` bound,
163+
// we do not need to constrain the associated type.
164+
.filter(|item| !tcx.generics_require_sized_self(item.def_id))
165+
.map(|item| (item.def_id, trait_ref)),
155166
);
156167
}
157168
ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => {
158169
let pred = bound_predicate.rebind(pred);
170+
171+
let pred_key = tcx.anonymize_bound_vars(pred);
172+
if !trait_alias_projection_bounds.contains(&pred_key) {
173+
projection_bounds.shift_remove(&pred_key);
174+
}
175+
159176
// A `Self` within the original bound will be instantiated with a
160177
// `trait_object_dummy_self`, so check for that.
161178
let references_self = match pred.skip_binder().term.unpack() {
@@ -182,8 +199,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
182199
// `dyn MyTrait<MyOutput = X, Output = X>`, which is uglier but works. See
183200
// the discussion in #56288 for alternatives.
184201
if !references_self {
185-
// Include projections defined on supertraits.
186-
projection_bounds.push((pred, original_span));
202+
if trait_alias_projection_bounds.contains(&pred_key) {
203+
// Include projections defined on supertraits.
204+
projection_bounds.insert(pred_key, (pred, supertrait_span));
205+
} else {
206+
// Include projections defined on supertraits.
207+
implied_projection_bounds.push(pred);
208+
}
187209
}
188210

189211
self.check_elaborated_projection_mentions_input_lifetimes(
@@ -201,26 +223,32 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
201223
// So every `Projection` clause is an `Assoc = Foo` bound. `associated_types` contains all associated
202224
// types's `DefId`, so the following loop removes all the `DefIds` of the associated types that have a
203225
// corresponding `Projection` clause
204-
for def_ids in associated_types.values_mut() {
205-
for (projection_bound, span) in &projection_bounds {
206-
let def_id = projection_bound.projection_def_id();
207-
def_ids.swap_remove(&def_id);
208-
if tcx.generics_require_sized_self(def_id) {
209-
tcx.emit_node_span_lint(
210-
UNUSED_ASSOCIATED_TYPE_BOUNDS,
211-
hir_id,
212-
*span,
213-
crate::errors::UnusedAssociatedTypeBounds { span: *span },
214-
);
215-
}
226+
for (projection_bound, span) in projection_bounds.values() {
227+
let def_id = projection_bound.projection_def_id();
228+
let trait_ref = tcx.anonymize_bound_vars(
229+
projection_bound.map_bound(|p| p.projection_term.trait_ref(tcx)),
230+
);
231+
needed_associated_types.swap_remove(&(def_id, trait_ref));
232+
if tcx.generics_require_sized_self(def_id) {
233+
tcx.emit_node_span_lint(
234+
UNUSED_ASSOCIATED_TYPE_BOUNDS,
235+
hir_id,
236+
*span,
237+
crate::errors::UnusedAssociatedTypeBounds { span: *span },
238+
);
216239
}
217-
// If the associated type has a `where Self: Sized` bound, we do not need to constrain the associated
218-
// type in the `dyn Trait`.
219-
def_ids.retain(|def_id| !tcx.generics_require_sized_self(def_id));
240+
}
241+
for projection_bound in &implied_projection_bounds {
242+
let def_id = projection_bound.projection_def_id();
243+
let trait_ref = tcx.anonymize_bound_vars(
244+
projection_bound.map_bound(|p| p.projection_term.trait_ref(tcx)),
245+
);
246+
needed_associated_types.swap_remove(&(def_id, trait_ref));
220247
}
221248

222249
self.complain_about_missing_assoc_tys(
223-
associated_types,
250+
principal_span,
251+
needed_associated_types,
224252
potential_assoc_types,
225253
hir_trait_bounds,
226254
);
@@ -302,7 +330,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
302330
})
303331
});
304332

305-
let existential_projections = projection_bounds.iter().map(|(bound, _)| {
333+
let existential_projections = projection_bounds.values().map(|(bound, _)| {
306334
bound.map_bound(|mut b| {
307335
assert_eq!(b.projection_term.self_ty(), dummy_self);
308336

0 commit comments

Comments
 (0)