Skip to content

Commit 47dd709

Browse files
committed
Auto merge of #121123 - compiler-errors:item-assumptions, r=oli-obk
Split an item bounds and an item's super predicates This is the moral equivalent of #107614, but instead for predicates this applies to **item bounds**. This PR splits out the item bounds (i.e. *all* predicates that are assumed to hold for the alias) from the item *super predicates*, which are the subset of item bounds which share the same self type as the alias. ## Why? Much like #107614, there are places in the compiler where we *only* care about super-predicates, and considering predicates that possibly don't have anything to do with the alias is problematic. This includes things like closure signature inference (which is at its core searching for `Self: Fn(..)` style bounds), but also lints like `#[must_use]`, error reporting for aliases, computing type outlives predicates. Even in cases where considering all of the `item_bounds` doesn't lead to bugs, unnecessarily considering irrelevant bounds does lead to a regression (#121121) due to doing extra work in the solver. ## Example 1 - Trait Aliases This is best explored via an example: ``` type TAIT<T> = impl TraitAlias<T>; trait TraitAlias<T> = A + B where T: C; ``` The item bounds list for `Tait<T>` will include: * `Tait<T>: A` * `Tait<T>: B` * `T: C` While `item_super_predicates` query will include just the first two predicates. Side-note: You may wonder why `T: C` is included in the item bounds for `TAIT`? This is because when we elaborate `TraitAlias<T>`, we will also elaborate all the predicates on the trait. ## Example 2 - Associated Type Bounds ``` type TAIT<T> = impl Iterator<Item: A>; ``` The `item_bounds` list for `TAIT<T>` will include: * `Tait<T>: Iterator` * `<Tait<T> as Iterator>::Item: A` But the `item_super_predicates` will just include the first bound, since that's the only bound that is relevant to the *alias* itself. ## So what This leads to some diagnostics duplication just like #107614, but none of it will be user-facing. We only see it in the UI test suite because we explicitly disable diagnostic deduplication. Regarding naming, I went with `super_predicates` kind of arbitrarily; this can easily be changed, but I'd consider better names as long as we don't block this PR in perpetuity.
2 parents 6e1f7b5 + ce5f8c9 commit 47dd709

File tree

74 files changed

+757
-174
lines changed

Some content is hidden

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

74 files changed

+757
-174
lines changed

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -716,7 +716,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
716716
.copied()
717717
.find_map(find_fn_kind_from_did),
718718
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => tcx
719-
.explicit_item_bounds(def_id)
719+
.explicit_item_super_predicates(def_id)
720720
.iter_instantiated_copied(tcx, args)
721721
.find_map(|(clause, span)| find_fn_kind_from_did((clause, span))),
722722
ty::Closure(_, args) => match args.as_closure().kind() {

compiler/rustc_hir_analysis/src/check/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ fn fn_sig_suggestion<'tcx>(
431431

432432
let asyncness = if tcx.asyncness(assoc.def_id).is_async() {
433433
output = if let ty::Alias(_, alias_ty) = *output.kind() {
434-
tcx.explicit_item_bounds(alias_ty.def_id)
434+
tcx.explicit_item_super_predicates(alias_ty.def_id)
435435
.iter_instantiated_copied(tcx, alias_ty.args)
436436
.find_map(|(bound, _)| bound.as_projection_clause()?.no_bound_vars()?.term.ty())
437437
.unwrap_or_else(|| {

compiler/rustc_hir_analysis/src/collect.rs

+7
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ pub fn provide(providers: &mut Providers) {
6161
type_alias_is_lazy: type_of::type_alias_is_lazy,
6262
item_bounds: item_bounds::item_bounds,
6363
explicit_item_bounds: item_bounds::explicit_item_bounds,
64+
item_super_predicates: item_bounds::item_super_predicates,
65+
explicit_item_super_predicates: item_bounds::explicit_item_super_predicates,
66+
item_non_self_assumptions: item_bounds::item_non_self_assumptions,
6467
generics_of: generics_of::generics_of,
6568
predicates_of: predicates_of::predicates_of,
6669
predicates_defined_on,
@@ -633,7 +636,9 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
633636
tcx.ensure().generics_of(def_id);
634637
tcx.ensure().predicates_of(def_id);
635638
tcx.ensure().explicit_item_bounds(def_id);
639+
tcx.ensure().explicit_item_super_predicates(def_id);
636640
tcx.ensure().item_bounds(def_id);
641+
tcx.ensure().item_super_predicates(def_id);
637642
}
638643

639644
hir::ItemKind::TyAlias(..) => {
@@ -689,6 +694,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
689694

690695
hir::TraitItemKind::Type(_, Some(_)) => {
691696
tcx.ensure().item_bounds(def_id);
697+
tcx.ensure().item_super_predicates(def_id);
692698
tcx.ensure().type_of(def_id);
693699
// Account for `type T = _;`.
694700
let mut visitor = HirPlaceholderCollector::default();
@@ -698,6 +704,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
698704

699705
hir::TraitItemKind::Type(_, None) => {
700706
tcx.ensure().item_bounds(def_id);
707+
tcx.ensure().item_super_predicates(def_id);
701708
// #74612: Visit and try to find bad placeholders
702709
// even if there is no concrete type.
703710
let mut visitor = HirPlaceholderCollector::default();

compiler/rustc_hir_analysis/src/collect/item_bounds.rs

+49-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use super::ItemCtxt;
22
use crate::astconv::{AstConv, PredicateFilter};
3+
use rustc_data_structures::fx::FxIndexSet;
34
use rustc_hir as hir;
45
use rustc_infer::traits::util;
56
use rustc_middle::ty::GenericArgs;
@@ -19,6 +20,7 @@ fn associated_type_bounds<'tcx>(
1920
assoc_item_def_id: LocalDefId,
2021
ast_bounds: &'tcx [hir::GenericBound<'tcx>],
2122
span: Span,
23+
filter: PredicateFilter,
2224
) -> &'tcx [(ty::Clause<'tcx>, Span)] {
2325
let item_ty = Ty::new_projection(
2426
tcx,
@@ -27,7 +29,7 @@ fn associated_type_bounds<'tcx>(
2729
);
2830

2931
let icx = ItemCtxt::new(tcx, assoc_item_def_id);
30-
let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, PredicateFilter::All);
32+
let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, filter);
3133
// Associated types are implicitly sized unless a `?Sized` bound is found
3234
icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span);
3335

@@ -63,10 +65,11 @@ fn opaque_type_bounds<'tcx>(
6365
ast_bounds: &'tcx [hir::GenericBound<'tcx>],
6466
item_ty: Ty<'tcx>,
6567
span: Span,
68+
filter: PredicateFilter,
6669
) -> &'tcx [(ty::Clause<'tcx>, Span)] {
6770
ty::print::with_reduced_queries!({
6871
let icx = ItemCtxt::new(tcx, opaque_def_id);
69-
let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, PredicateFilter::All);
72+
let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, filter);
7073
// Opaque types are implicitly sized unless a `?Sized` bound is found
7174
icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span);
7275
debug!(?bounds);
@@ -78,6 +81,21 @@ fn opaque_type_bounds<'tcx>(
7881
pub(super) fn explicit_item_bounds(
7982
tcx: TyCtxt<'_>,
8083
def_id: LocalDefId,
84+
) -> ty::EarlyBinder<&'_ [(ty::Clause<'_>, Span)]> {
85+
explicit_item_bounds_with_filter(tcx, def_id, PredicateFilter::All)
86+
}
87+
88+
pub(super) fn explicit_item_super_predicates(
89+
tcx: TyCtxt<'_>,
90+
def_id: LocalDefId,
91+
) -> ty::EarlyBinder<&'_ [(ty::Clause<'_>, Span)]> {
92+
explicit_item_bounds_with_filter(tcx, def_id, PredicateFilter::SelfOnly)
93+
}
94+
95+
pub(super) fn explicit_item_bounds_with_filter(
96+
tcx: TyCtxt<'_>,
97+
def_id: LocalDefId,
98+
filter: PredicateFilter,
8199
) -> ty::EarlyBinder<&'_ [(ty::Clause<'_>, Span)]> {
82100
match tcx.opt_rpitit_info(def_id.to_def_id()) {
83101
// RPITIT's bounds are the same as opaque type bounds, but with
@@ -95,6 +113,7 @@ pub(super) fn explicit_item_bounds(
95113
ty::GenericArgs::identity_for_item(tcx, def_id),
96114
),
97115
item.span,
116+
filter,
98117
));
99118
}
100119
Some(ty::ImplTraitInTraitData::Impl { .. }) => span_bug!(
@@ -109,15 +128,15 @@ pub(super) fn explicit_item_bounds(
109128
kind: hir::TraitItemKind::Type(bounds, _),
110129
span,
111130
..
112-
}) => associated_type_bounds(tcx, def_id, bounds, *span),
131+
}) => associated_type_bounds(tcx, def_id, bounds, *span, filter),
113132
hir::Node::Item(hir::Item {
114133
kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, in_trait: false, .. }),
115134
span,
116135
..
117136
}) => {
118137
let args = GenericArgs::identity_for_item(tcx, def_id);
119138
let item_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args);
120-
opaque_type_bounds(tcx, def_id, bounds, item_ty, *span)
139+
opaque_type_bounds(tcx, def_id, bounds, item_ty, *span, filter)
121140
}
122141
// Since RPITITs are astconv'd as projections in `ast_ty_to_ty`, when we're asking
123142
// for the item bounds of the *opaques* in a trait's default method signature, we
@@ -135,7 +154,7 @@ pub(super) fn explicit_item_bounds(
135154
let args = GenericArgs::identity_for_item(tcx, def_id);
136155
let item_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args);
137156
tcx.arena.alloc_slice(
138-
&opaque_type_bounds(tcx, def_id, bounds, item_ty, *span)
157+
&opaque_type_bounds(tcx, def_id, bounds, item_ty, *span, filter)
139158
.to_vec()
140159
.fold_with(&mut AssocTyToOpaque { tcx, fn_def_id: fn_def_id.to_def_id() }),
141160
)
@@ -155,6 +174,31 @@ pub(super) fn item_bounds(
155174
})
156175
}
157176

177+
pub(super) fn item_super_predicates(
178+
tcx: TyCtxt<'_>,
179+
def_id: DefId,
180+
) -> ty::EarlyBinder<&'_ ty::List<ty::Clause<'_>>> {
181+
tcx.explicit_item_super_predicates(def_id).map_bound(|bounds| {
182+
tcx.mk_clauses_from_iter(
183+
util::elaborate(tcx, bounds.iter().map(|&(bound, _span)| bound)).filter_only_self(),
184+
)
185+
})
186+
}
187+
188+
pub(super) fn item_non_self_assumptions(
189+
tcx: TyCtxt<'_>,
190+
def_id: DefId,
191+
) -> ty::EarlyBinder<&'_ ty::List<ty::Clause<'_>>> {
192+
let all_bounds: FxIndexSet<_> = tcx.item_bounds(def_id).skip_binder().iter().collect();
193+
let own_bounds: FxIndexSet<_> =
194+
tcx.item_super_predicates(def_id).skip_binder().iter().collect();
195+
if all_bounds.len() == own_bounds.len() {
196+
ty::EarlyBinder::bind(ty::List::empty())
197+
} else {
198+
ty::EarlyBinder::bind(tcx.mk_clauses_from_iter(all_bounds.difference(&own_bounds).copied()))
199+
}
200+
}
201+
158202
struct AssocTyToOpaque<'tcx> {
159203
tcx: TyCtxt<'tcx>,
160204
fn_def_id: DefId,

compiler/rustc_hir_typeck/src/_match.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -645,7 +645,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
645645
for ty in [first_ty, second_ty] {
646646
for (clause, _) in self
647647
.tcx
648-
.explicit_item_bounds(rpit_def_id)
648+
.explicit_item_super_predicates(rpit_def_id)
649649
.iter_instantiated_copied(self.tcx, args)
650650
{
651651
let pred = clause.kind().rebind(match clause.kind().skip_binder() {

compiler/rustc_hir_typeck/src/closure.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
329329
expected_ty,
330330
closure_kind,
331331
self.tcx
332-
.explicit_item_bounds(def_id)
332+
.explicit_item_super_predicates(def_id)
333333
.iter_instantiated_copied(self.tcx, args)
334334
.map(|(c, s)| (c.as_predicate(), s)),
335335
),
@@ -906,7 +906,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
906906
}
907907
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => self
908908
.tcx
909-
.explicit_item_bounds(def_id)
909+
.explicit_item_super_predicates(def_id)
910910
.iter_instantiated_copied(self.tcx, args)
911911
.find_map(|(p, s)| get_future_output(p.as_predicate(), s))?,
912912
ty::Error(_) => return Some(ret_ty),

compiler/rustc_infer/src/infer/error_reporting/mod.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -403,8 +403,10 @@ impl<'tcx> InferCtxt<'tcx> {
403403
let future_trait = self.tcx.require_lang_item(LangItem::Future, None);
404404
let item_def_id = self.tcx.associated_item_def_ids(future_trait)[0];
405405

406-
self.tcx.explicit_item_bounds(def_id).iter_instantiated_copied(self.tcx, args).find_map(
407-
|(predicate, _)| {
406+
self.tcx
407+
.explicit_item_super_predicates(def_id)
408+
.iter_instantiated_copied(self.tcx, args)
409+
.find_map(|(predicate, _)| {
408410
predicate
409411
.kind()
410412
.map_bound(|kind| match kind {
@@ -417,8 +419,7 @@ impl<'tcx> InferCtxt<'tcx> {
417419
})
418420
.no_bound_vars()
419421
.flatten()
420-
},
421-
)
422+
})
422423
}
423424
}
424425

compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -299,17 +299,19 @@ impl<T> Trait<T> for X {
299299
}
300300
(ty::Dynamic(t, _, ty::DynKind::Dyn), ty::Alias(ty::Opaque, alias))
301301
if let Some(def_id) = t.principal_def_id()
302-
&& tcx.explicit_item_bounds(alias.def_id).skip_binder().iter().any(
303-
|(pred, _span)| match pred.kind().skip_binder() {
302+
&& tcx
303+
.explicit_item_super_predicates(alias.def_id)
304+
.skip_binder()
305+
.iter()
306+
.any(|(pred, _span)| match pred.kind().skip_binder() {
304307
ty::ClauseKind::Trait(trait_predicate)
305308
if trait_predicate.polarity
306309
== ty::ImplPolarity::Positive =>
307310
{
308311
trait_predicate.def_id() == def_id
309312
}
310313
_ => false,
311-
},
312-
) =>
314+
}) =>
313315
{
314316
diag.help(format!(
315317
"you can box the `{}` to coerce it to `Box<{}>`, but you'll have to \
@@ -412,7 +414,7 @@ impl<T> Trait<T> for X {
412414
ty::Alias(..) => values.expected,
413415
_ => values.found,
414416
};
415-
let preds = tcx.explicit_item_bounds(opaque_ty.def_id);
417+
let preds = tcx.explicit_item_super_predicates(opaque_ty.def_id);
416418
for (pred, _span) in preds.skip_binder() {
417419
let ty::ClauseKind::Trait(trait_predicate) = pred.kind().skip_binder()
418420
else {

compiler/rustc_infer/src/infer/outlives/verify.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
300300
alias_ty: ty::AliasTy<'tcx>,
301301
) -> impl Iterator<Item = ty::Region<'tcx>> {
302302
let tcx = self.tcx;
303-
let bounds = tcx.item_bounds(alias_ty.def_id);
303+
let bounds = tcx.item_super_predicates(alias_ty.def_id);
304304
trace!("{:#?}", bounds.skip_binder());
305305
bounds
306306
.iter_instantiated(tcx, alias_ty.args)

compiler/rustc_lint/src/unused.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,9 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
295295
ty::Alias(ty::Opaque | ty::Projection, ty::AliasTy { def_id: def, .. }) => {
296296
elaborate(
297297
cx.tcx,
298-
cx.tcx.explicit_item_bounds(def).instantiate_identity_iter_copied(),
298+
cx.tcx
299+
.explicit_item_super_predicates(def)
300+
.instantiate_identity_iter_copied(),
299301
)
300302
// We only care about self bounds for the impl-trait
301303
.filter_only_self()

compiler/rustc_metadata/src/rmeta/decoder.rs

+14
Original file line numberDiff line numberDiff line change
@@ -1063,6 +1063,20 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
10631063
ty::EarlyBinder::bind(&*output)
10641064
}
10651065

1066+
fn get_explicit_item_super_predicates(
1067+
self,
1068+
index: DefIndex,
1069+
tcx: TyCtxt<'tcx>,
1070+
) -> ty::EarlyBinder<&'tcx [(ty::Clause<'tcx>, Span)]> {
1071+
let lazy = self.root.tables.explicit_item_super_predicates.get(self, index);
1072+
let output = if lazy.is_default() {
1073+
&mut []
1074+
} else {
1075+
tcx.arena.alloc_from_iter(lazy.decode((self, tcx)))
1076+
};
1077+
ty::EarlyBinder::bind(&*output)
1078+
}
1079+
10661080
fn get_variant(
10671081
self,
10681082
kind: DefKind,

compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs

+1
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ impl IntoArgs for (CrateNum, SimplifiedType) {
206206

207207
provide! { tcx, def_id, other, cdata,
208208
explicit_item_bounds => { cdata.get_explicit_item_bounds(def_id.index, tcx) }
209+
explicit_item_super_predicates => { cdata.get_explicit_item_super_predicates(def_id.index, tcx) }
209210
explicit_predicates_of => { table }
210211
generics_of => { table }
211212
inferred_outlives_of => { table_defaulted_array }

compiler/rustc_metadata/src/rmeta/encoder.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1491,6 +1491,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
14911491
}
14921492
if let DefKind::OpaqueTy = def_kind {
14931493
self.encode_explicit_item_bounds(def_id);
1494+
self.encode_explicit_item_super_predicates(def_id);
14941495
self.tables
14951496
.is_type_alias_impl_trait
14961497
.set(def_id.index, self.tcx.is_type_alias_impl_trait(def_id));
@@ -1599,6 +1600,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
15991600
record_defaulted_array!(self.tables.explicit_item_bounds[def_id] <- bounds);
16001601
}
16011602

1603+
fn encode_explicit_item_super_predicates(&mut self, def_id: DefId) {
1604+
debug!("EncodeContext::encode_explicit_item_super_predicates({:?})", def_id);
1605+
let bounds = self.tcx.explicit_item_super_predicates(def_id).skip_binder();
1606+
record_defaulted_array!(self.tables.explicit_item_super_predicates[def_id] <- bounds);
1607+
}
1608+
16021609
#[instrument(level = "debug", skip(self))]
16031610
fn encode_info_for_assoc_item(&mut self, def_id: DefId) {
16041611
let tcx = self.tcx;
@@ -1611,6 +1618,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
16111618
AssocItemContainer::TraitContainer => {
16121619
if let ty::AssocKind::Type = item.kind {
16131620
self.encode_explicit_item_bounds(def_id);
1621+
self.encode_explicit_item_super_predicates(def_id);
16141622
}
16151623
}
16161624
AssocItemContainer::ImplContainer => {

compiler/rustc_metadata/src/rmeta/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,7 @@ define_tables! {
387387
// corresponding DefPathHash.
388388
def_path_hashes: Table<DefIndex, u64>,
389389
explicit_item_bounds: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>,
390+
explicit_item_super_predicates: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>,
390391
inferred_outlives_of: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>,
391392
inherent_impls: Table<DefIndex, LazyArray<DefIndex>>,
392393
associated_types_for_impl_traits_in_associated_fn: Table<DefIndex, LazyArray<DefId>>,

0 commit comments

Comments
 (0)