Skip to content

Commit 653e9a2

Browse files
authored
Rollup merge of rust-lang#130666 - compiler-errors:super-bounds, r=fee1-dead,fmease
Assert that `explicit_super_predicates_of` and `explicit_item_super_predicates` truly only contains bounds for the type itself We distinguish _implied_ predicates (anything that is implied from elaborating a trait bound) from _super_ predicates, which are are the subset of implied predicates that share the same self type as the trait predicate we're elaborating. This was originally done in rust-lang#107614, which fixed a large class of ICEs and strange errors where the compiler expected the self type of a trait predicate not to change when elaborating super predicates. Specifically, super predicates are special for various reasons: they're the valid candidates for trait upcasting, are the only predicates we elaborate when doing closure signature inference, etc. So making sure that we get this list correct and don't accidentally "leak" any other predicates into this list is quite important. This PR adds some debug assertions that we're in fact not doing so, and it fixes an oversight in the effect desugaring rework.
2 parents c261642 + 4f3d06f commit 653e9a2

File tree

6 files changed

+85
-25
lines changed

6 files changed

+85
-25
lines changed

compiler/rustc_hir_analysis/src/bounds.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ use rustc_middle::ty::{self, Ty, TyCtxt, Upcast};
99
use rustc_span::def_id::DefId;
1010
use rustc_span::Span;
1111

12+
use crate::hir_ty_lowering::OnlySelfBounds;
13+
1214
/// Collects together a list of type bounds. These lists of bounds occur in many places
1315
/// in Rust's syntax:
1416
///
@@ -50,6 +52,7 @@ impl<'tcx> Bounds<'tcx> {
5052
span: Span,
5153
polarity: ty::PredicatePolarity,
5254
constness: ty::BoundConstness,
55+
only_self_bounds: OnlySelfBounds,
5356
) {
5457
let clause = (
5558
bound_trait_ref
@@ -66,7 +69,10 @@ impl<'tcx> Bounds<'tcx> {
6669
self.clauses.push(clause);
6770
}
6871

69-
if !tcx.features().effects {
72+
// FIXME(effects): Lift this out of `push_trait_bound`, and move it somewhere else.
73+
// Perhaps moving this into `lower_poly_trait_ref`, just like we lower associated
74+
// type bounds.
75+
if !tcx.features().effects || only_self_bounds.0 {
7076
return;
7177
}
7278
// For `T: ~const Tr` or `T: const Tr`, we need to add an additional bound on the

compiler/rustc_hir_analysis/src/collect/item_bounds.rs

+22-10
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use rustc_span::Span;
1010
use rustc_type_ir::Upcast;
1111
use tracing::{debug, instrument};
1212

13+
use super::predicates_of::assert_only_contains_predicates_from;
1314
use super::ItemCtxt;
1415
use crate::hir_ty_lowering::{HirTyLowerer, PredicateFilter};
1516

@@ -56,6 +57,9 @@ fn associated_type_bounds<'tcx>(
5657
tcx.def_path_str(assoc_item_def_id.to_def_id()),
5758
all_bounds
5859
);
60+
61+
assert_only_contains_predicates_from(filter, all_bounds, item_ty);
62+
5963
all_bounds
6064
}
6165

@@ -108,18 +112,21 @@ pub(super) fn explicit_item_bounds_with_filter(
108112
Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
109113
let item = tcx.hir_node_by_def_id(opaque_def_id.expect_local()).expect_item();
110114
let opaque_ty = item.expect_opaque_ty();
111-
return ty::EarlyBinder::bind(opaque_type_bounds(
115+
let item_ty = Ty::new_projection_from_args(
116+
tcx,
117+
def_id.to_def_id(),
118+
ty::GenericArgs::identity_for_item(tcx, def_id),
119+
);
120+
let bounds = opaque_type_bounds(
112121
tcx,
113122
opaque_def_id.expect_local(),
114123
opaque_ty.bounds,
115-
Ty::new_projection_from_args(
116-
tcx,
117-
def_id.to_def_id(),
118-
ty::GenericArgs::identity_for_item(tcx, def_id),
119-
),
124+
item_ty,
120125
item.span,
121126
filter,
122-
));
127+
);
128+
assert_only_contains_predicates_from(filter, bounds, item_ty);
129+
return ty::EarlyBinder::bind(bounds);
123130
}
124131
Some(ty::ImplTraitInTraitData::Impl { .. }) => span_bug!(
125132
tcx.def_span(def_id),
@@ -167,7 +174,9 @@ pub(super) fn explicit_item_bounds_with_filter(
167174
}) => {
168175
let args = GenericArgs::identity_for_item(tcx, def_id);
169176
let item_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args);
170-
opaque_type_bounds(tcx, def_id, bounds, item_ty, *span, filter)
177+
let bounds = opaque_type_bounds(tcx, def_id, bounds, item_ty, *span, filter);
178+
assert_only_contains_predicates_from(filter, bounds, item_ty);
179+
bounds
171180
}
172181
// Since RPITITs are lowered as projections in `<dyn HirTyLowerer>::lower_ty`, when we're
173182
// asking for the item bounds of the *opaques* in a trait's default method signature, we
@@ -184,15 +193,18 @@ pub(super) fn explicit_item_bounds_with_filter(
184193
};
185194
let args = GenericArgs::identity_for_item(tcx, def_id);
186195
let item_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args);
187-
tcx.arena.alloc_slice(
196+
let bounds = &*tcx.arena.alloc_slice(
188197
&opaque_type_bounds(tcx, def_id, bounds, item_ty, *span, filter)
189198
.to_vec()
190199
.fold_with(&mut AssocTyToOpaque { tcx, fn_def_id: fn_def_id.to_def_id() }),
191-
)
200+
);
201+
assert_only_contains_predicates_from(filter, bounds, item_ty);
202+
bounds
192203
}
193204
hir::Node::Item(hir::Item { kind: hir::ItemKind::TyAlias(..), .. }) => &[],
194205
_ => bug!("item_bounds called on {:?}", def_id),
195206
};
207+
196208
ty::EarlyBinder::bind(bounds)
197209
}
198210

compiler/rustc_hir_analysis/src/collect/predicates_of.rs

+54
Original file line numberDiff line numberDiff line change
@@ -677,9 +677,63 @@ pub(super) fn implied_predicates_with_filter<'tcx>(
677677
_ => {}
678678
}
679679

680+
assert_only_contains_predicates_from(filter, implied_bounds, tcx.types.self_param);
681+
680682
ty::EarlyBinder::bind(implied_bounds)
681683
}
682684

685+
// Make sure when elaborating supertraits, probing for associated types, etc.,
686+
// we really truly are elaborating clauses that have `Self` as their self type.
687+
// This is very important since downstream code relies on this being correct.
688+
pub(super) fn assert_only_contains_predicates_from<'tcx>(
689+
filter: PredicateFilter,
690+
bounds: &'tcx [(ty::Clause<'tcx>, Span)],
691+
ty: Ty<'tcx>,
692+
) {
693+
if !cfg!(debug_assertions) {
694+
return;
695+
}
696+
697+
match filter {
698+
PredicateFilter::SelfOnly | PredicateFilter::SelfThatDefines(_) => {
699+
for (clause, _) in bounds {
700+
match clause.kind().skip_binder() {
701+
ty::ClauseKind::Trait(trait_predicate) => {
702+
assert_eq!(
703+
trait_predicate.self_ty(),
704+
ty,
705+
"expected `Self` predicate when computing `{filter:?}` implied bounds: {clause:?}"
706+
);
707+
}
708+
ty::ClauseKind::Projection(projection_predicate) => {
709+
assert_eq!(
710+
projection_predicate.self_ty(),
711+
ty,
712+
"expected `Self` predicate when computing `{filter:?}` implied bounds: {clause:?}"
713+
);
714+
}
715+
ty::ClauseKind::TypeOutlives(outlives_predicate) => {
716+
assert_eq!(
717+
outlives_predicate.0, ty,
718+
"expected `Self` predicate when computing `{filter:?}` implied bounds: {clause:?}"
719+
);
720+
}
721+
722+
ty::ClauseKind::RegionOutlives(_)
723+
| ty::ClauseKind::ConstArgHasType(_, _)
724+
| ty::ClauseKind::WellFormed(_)
725+
| ty::ClauseKind::ConstEvaluatable(_) => {
726+
bug!(
727+
"unexpected non-`Self` predicate when computing `{filter:?}` implied bounds: {clause:?}"
728+
);
729+
}
730+
}
731+
}
732+
}
733+
PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {}
734+
}
735+
}
736+
683737
/// Returns the predicates defined on `item_def_id` of the form
684738
/// `X: Foo` where `X` is the type parameter `def_id`.
685739
#[instrument(level = "trace", skip(tcx))]

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
719719
span,
720720
polarity,
721721
constness,
722+
only_self_bounds,
722723
);
723724

724725
let mut dup_constraints = FxIndexMap::default();

tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.rs

-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ impl const Foo for NonConstAdd {
3939
#[const_trait]
4040
trait Baz {
4141
type Qux: Add;
42-
//~^ ERROR the trait bound
4342
}
4443

4544
impl const Baz for NonConstAdd {

tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr

+1-13
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,5 @@ error: using `#![feature(effects)]` without enabling next trait solver globally
1212
= note: the next trait solver must be enabled globally for the effects feature to work correctly
1313
= help: use `-Znext-solver` to enable
1414

15-
error[E0277]: the trait bound `Add::{synthetic#0}: Compat` is not satisfied
16-
--> $DIR/assoc-type.rs:41:15
17-
|
18-
LL | type Qux: Add;
19-
| ^^^ the trait `Compat` is not implemented for `Add::{synthetic#0}`
20-
|
21-
help: consider further restricting the associated type
22-
|
23-
LL | trait Baz where Add::{synthetic#0}: Compat {
24-
| ++++++++++++++++++++++++++++++++
25-
26-
error: aborting due to 2 previous errors; 1 warning emitted
15+
error: aborting due to 1 previous error; 1 warning emitted
2716

28-
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)