Skip to content

Commit 22cb94a

Browse files
wuwuwuwuwuwu
1 parent 0320ee1 commit 22cb94a

File tree

8 files changed

+70
-42
lines changed

8 files changed

+70
-42
lines changed

Diff for: compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs

+25-9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
1+
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
22
use rustc_errors::codes::*;
33
use rustc_errors::struct_span_code_err;
44
use rustc_hir as hir;
@@ -61,7 +61,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
6161
}
6262

6363
let mut trait_bounds = vec![];
64-
let mut projection_bounds = vec![];
64+
let mut projection_bounds = FxIndexMap::default();
6565
for (pred, span) in bounds.clauses() {
6666
let bound_pred = pred.kind();
6767
match bound_pred.skip_binder() {
@@ -70,7 +70,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
7070
trait_bounds.push((bound_pred.rebind(trait_pred.trait_ref), span));
7171
}
7272
ty::ClauseKind::Projection(proj) => {
73-
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));
7475
}
7576
ty::ClauseKind::TypeOutlives(_) => {
7677
// Do nothing, we deal with regions separately
@@ -87,8 +88,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
8788

8889
// Expand trait aliases recursively and check that only one regular (non-auto) trait
8990
// is used and no 'maybe' bounds are used.
90-
let expanded_traits =
91-
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+
);
9297

9398
let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) =
9499
expanded_traits.partition(|i| tcx.trait_is_auto(i.trait_ref().def_id()));
@@ -162,6 +167,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
162167
}
163168
ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => {
164169
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+
165176
// A `Self` within the original bound will be instantiated with a
166177
// `trait_object_dummy_self`, so check for that.
167178
let references_self = match pred.skip_binder().term.unpack() {
@@ -188,8 +199,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
188199
// `dyn MyTrait<MyOutput = X, Output = X>`, which is uglier but works. See
189200
// the discussion in #56288 for alternatives.
190201
if !references_self {
191-
// Include projections defined on supertraits.
192-
implied_projection_bounds.push(pred);
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+
}
193209
}
194210

195211
self.check_elaborated_projection_mentions_input_lifetimes(
@@ -207,7 +223,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
207223
// So every `Projection` clause is an `Assoc = Foo` bound. `associated_types` contains all associated
208224
// types's `DefId`, so the following loop removes all the `DefIds` of the associated types that have a
209225
// corresponding `Projection` clause
210-
for (projection_bound, span) in &projection_bounds {
226+
for (projection_bound, span) in projection_bounds.values() {
211227
let def_id = projection_bound.projection_def_id();
212228
let trait_ref = tcx.anonymize_bound_vars(
213229
projection_bound.map_bound(|p| p.projection_term.trait_ref(tcx)),
@@ -314,7 +330,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
314330
})
315331
});
316332

317-
let existential_projections = projection_bounds.iter().map(|(bound, _)| {
333+
let existential_projections = projection_bounds.values().map(|(bound, _)| {
318334
bound.map_bound(|mut b| {
319335
assert_eq!(b.projection_term.self_ty(), dummy_self);
320336

Diff for: compiler/rustc_hir_typeck/src/method/probe.rs

+1
Original file line numberDiff line numberDiff line change
@@ -903,6 +903,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
903903
// For trait aliases, recursively assume all explicitly named traits are relevant
904904
for expansion in traits::expand_trait_aliases(
905905
self.tcx,
906+
&mut Default::default(),
906907
iter::once((ty::Binder::dummy(trait_ref), self.span)),
907908
) {
908909
let bound_trait_ref = expansion.trait_ref();

Diff for: compiler/rustc_middle/src/ty/relate.rs

+4-12
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
}

Diff for: compiler/rustc_trait_selection/src/traits/util.rs

+24-15
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::collections::BTreeMap;
22

3-
use rustc_data_structures::fx::FxIndexMap;
3+
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
44
use rustc_errors::Diag;
55
use rustc_hir::def_id::DefId;
66
use rustc_infer::infer::InferCtxt;
@@ -25,9 +25,11 @@ use tracing::debug;
2525
/// `Read + Write + Sync + Send`.
2626
/// Expansion is done via a DFS (depth-first search), and the `visited` field
2727
/// is used to avoid cycles.
28-
pub struct TraitAliasExpander<'tcx> {
28+
pub struct TraitAliasExpander<'a, 'tcx> {
2929
tcx: TyCtxt<'tcx>,
3030
stack: Vec<TraitAliasExpansionInfo<'tcx>>,
31+
// TODO:
32+
projection_bounds: &'a mut FxIndexSet<ty::PolyProjectionPredicate<'tcx>>,
3133
}
3234

3335
/// Stores information about the expansion of a trait via a path of zero or more trait aliases.
@@ -85,16 +87,17 @@ impl<'tcx> TraitAliasExpansionInfo<'tcx> {
8587
}
8688
}
8789

88-
pub fn expand_trait_aliases<'tcx>(
90+
pub fn expand_trait_aliases<'a, 'tcx>(
8991
tcx: TyCtxt<'tcx>,
92+
projection_bounds: &'a mut FxIndexSet<ty::PolyProjectionPredicate<'tcx>>,
9093
trait_refs: impl Iterator<Item = (ty::PolyTraitRef<'tcx>, Span)>,
91-
) -> TraitAliasExpander<'tcx> {
94+
) -> TraitAliasExpander<'a, 'tcx> {
9295
let items: Vec<_> =
9396
trait_refs.map(|(trait_ref, span)| TraitAliasExpansionInfo::new(trait_ref, span)).collect();
94-
TraitAliasExpander { tcx, stack: items }
97+
TraitAliasExpander { tcx, stack: items, projection_bounds }
9598
}
9699

97-
impl<'tcx> TraitAliasExpander<'tcx> {
100+
impl<'tcx> TraitAliasExpander<'_, 'tcx> {
98101
/// If `item` is a trait alias and its predicate has not yet been visited, then expands `item`
99102
/// to the definition, pushes the resulting expansion onto `self.stack`, and returns `false`.
100103
/// Otherwise, immediately returns `true` if `item` is a regular trait, or `false` if it is a
@@ -129,20 +132,26 @@ impl<'tcx> TraitAliasExpander<'tcx> {
129132
let predicates = tcx.explicit_super_predicates_of(trait_ref.def_id());
130133
debug!(?predicates);
131134

132-
let items = predicates.skip_binder().iter().rev().filter_map(|(pred, span)| {
133-
pred.instantiate_supertrait(tcx, trait_ref)
134-
.as_trait_clause()
135-
.map(|trait_ref| item.clone_and_push(trait_ref.map_bound(|t| t.trait_ref), *span))
136-
});
137-
debug!("expand_trait_aliases: items={:?}", items.clone().collect::<Vec<_>>());
138-
139-
self.stack.extend(items);
135+
for &(pred, span) in predicates.skip_binder().iter().rev() {
136+
let pred = pred.instantiate_supertrait(tcx, trait_ref);
137+
if let Some(trait_pred) = pred.as_trait_clause() {
138+
// FIXME(negative_bounds): Polarity
139+
self.stack.push(
140+
item.clone_and_push(
141+
trait_pred.map_bound(|trait_pred| trait_pred.trait_ref),
142+
span,
143+
),
144+
);
145+
} else if let Some(proj) = pred.as_projection_clause() {
146+
self.projection_bounds.insert(self.tcx.anonymize_bound_vars(proj));
147+
}
148+
}
140149

141150
false
142151
}
143152
}
144153

145-
impl<'tcx> Iterator for TraitAliasExpander<'tcx> {
154+
impl<'tcx> Iterator for TraitAliasExpander<'_, 'tcx> {
146155
type Item = TraitAliasExpansionInfo<'tcx>;
147156

148157
fn size_hint(&self) -> (usize, Option<usize>) {

Diff for: tests/ui/associated-types/issue-59324.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@ pub trait ThriftService<Bug: NotFoo>:
2121
}
2222

2323
fn with_factory<H>(factory: dyn ThriftService<()>) {}
24-
//~^ ERROR the trait bound `(): Foo` is not satisfied
25-
//~| ERROR the trait bound `(): Foo` is not satisfied
26-
//~| ERROR cannot be known at compilation time
24+
//~^ ERROR cannot be known at compilation time
2725

2826
fn main() {}

Diff for: tests/ui/issues/issue-59326.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
//@ check-pass
21
trait Service {
32
type S;
43
}
@@ -23,4 +22,5 @@ fn make_server<F: Framing>() -> Box<dyn HttpService<F, S = F::F>> {
2322

2423
fn main() {
2524
build_server(|| make_server())
25+
//~^ ERROR mismatched types
2626
}

Diff for: tests/ui/issues/issue-59326.stderr

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/issue-59326.rs:24:21
3+
|
4+
LL | build_server(|| make_server())
5+
| ^^^^^^^^^^^^^ expected trait `HttpService<(), S = ()>`, found trait `HttpService<_>`
6+
|
7+
= note: expected struct `Box<(dyn HttpService<(), S = ()> + 'static)>`
8+
found struct `Box<(dyn HttpService<_> + 'static)>`
9+
10+
error: aborting due to 1 previous error
11+
12+
For more information about this error, try `rustc --explain E0308`.

Diff for: tests/ui/traits/alias/dont-elaborate-non-self.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
error[E0277]: the size for values of type `(dyn Fn<()> + 'static)` cannot be known at compilation time
1+
error[E0277]: the size for values of type `(dyn Fn() -> Fut + 'static)` cannot be known at compilation time
22
--> $DIR/dont-elaborate-non-self.rs:7:14
33
|
44
LL | fn f<Fut>(a: dyn F<Fut>) {}
55
| ^^^^^^^^^^ doesn't have a size known at compile-time
66
|
7-
= help: the trait `Sized` is not implemented for `(dyn Fn<()> + 'static)`
7+
= help: the trait `Sized` is not implemented for `(dyn Fn() -> Fut + 'static)`
88
= help: unsized fn params are gated as an unstable feature
99
help: you can use `impl Trait` as the argument type
1010
|

0 commit comments

Comments
 (0)