Skip to content

Commit be4f9f5

Browse files
authored
Rollup merge of #110512 - compiler-errors:fix-elaboration-with-associated-type-bounds, r=spastorino
Fix elaboration with associated type bounds When computing a trait's supertrait predicates, do not add any associated type *trait* bounds to that list of supertrait predicates. This is because supertrait predicates are expected to have the same `Self` type as the trait. For example, given: ```rust trait Foo: Bar<Assoc: Send> ``` Before, we would compute that the supertrait predicates of `T: Foo` are `T: Bar` and `<T as Bar>::Assoc: Send`. However, the last bound is a trait predicate for a totally different type than `T`, and existing code that uses supertrait bounds such as vtable construction, closure fn signature deduction, etc. all rely on the invariant that we have a list of predicates for self type `T`. Fixes #76593 The reason for all the extra diagnostic noise is that we're recomputing predicates with a different filter now. These diagnostics should be deduplicated for any end-user though. --- This does bring up an interesting question -- is the predicate `<T as Bar>::Assoc: Send` an implied bound of `T: Foo`? Because currently the only bounds implied by a (non-alias) trait are its supertraits. I guess I could fix this too, but it would require even more changes, and I'm inclined to punt this question along.
2 parents f379a58 + bec7193 commit be4f9f5

26 files changed

+445
-146
lines changed

compiler/rustc_hir_analysis/src/astconv/mod.rs

+56-14
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ use std::slice;
5656
#[derive(Debug)]
5757
pub struct PathSeg(pub DefId, pub usize);
5858

59+
#[derive(Copy, Clone, Debug)]
60+
pub struct OnlySelfBounds(pub bool);
61+
5962
pub trait AstConv<'tcx> {
6063
fn tcx(&self) -> TyCtxt<'tcx>;
6164

@@ -670,6 +673,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
670673
args: &GenericArgs<'_>,
671674
infer_args: bool,
672675
self_ty: Ty<'tcx>,
676+
only_self_bounds: OnlySelfBounds,
673677
) -> GenericArgCountResult {
674678
let (substs, arg_count) = self.create_substs_for_ast_path(
675679
trait_ref_span,
@@ -706,6 +710,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
706710
&mut dup_bindings,
707711
binding_span.unwrap_or(binding.span),
708712
constness,
713+
only_self_bounds,
709714
);
710715
// Okay to ignore `Err` because of `ErrorGuaranteed` (see above).
711716
}
@@ -741,6 +746,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
741746
self_ty: Ty<'tcx>,
742747
bounds: &mut Bounds<'tcx>,
743748
speculative: bool,
749+
only_self_bounds: OnlySelfBounds,
744750
) -> GenericArgCountResult {
745751
let hir_id = trait_ref.hir_ref_id;
746752
let binding_span = None;
@@ -766,6 +772,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
766772
args,
767773
infer_args,
768774
self_ty,
775+
only_self_bounds,
769776
)
770777
}
771778

@@ -777,6 +784,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
777784
args: &GenericArgs<'_>,
778785
self_ty: Ty<'tcx>,
779786
bounds: &mut Bounds<'tcx>,
787+
only_self_bounds: OnlySelfBounds,
780788
) {
781789
let binding_span = Some(span);
782790
let constness = ty::BoundConstness::NotConst;
@@ -799,6 +807,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
799807
args,
800808
infer_args,
801809
self_ty,
810+
only_self_bounds,
802811
);
803812
}
804813

@@ -947,6 +956,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
947956
ast_bounds: I,
948957
bounds: &mut Bounds<'tcx>,
949958
bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
959+
only_self_bounds: OnlySelfBounds,
950960
) {
951961
for ast_bound in ast_bounds {
952962
match ast_bound {
@@ -964,11 +974,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
964974
param_ty,
965975
bounds,
966976
false,
977+
only_self_bounds,
967978
);
968979
}
969980
&hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => {
970981
self.instantiate_lang_item_trait_ref(
971-
lang_item, span, hir_id, args, param_ty, bounds,
982+
lang_item,
983+
span,
984+
hir_id,
985+
args,
986+
param_ty,
987+
bounds,
988+
only_self_bounds,
972989
);
973990
}
974991
hir::GenericBound::Outlives(lifetime) => {
@@ -1006,8 +1023,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
10061023
&self,
10071024
param_ty: Ty<'tcx>,
10081025
ast_bounds: &[hir::GenericBound<'_>],
1026+
only_self_bounds: OnlySelfBounds,
10091027
) -> Bounds<'tcx> {
1010-
self.compute_bounds_inner(param_ty, ast_bounds)
1028+
let mut bounds = Bounds::default();
1029+
self.add_bounds(
1030+
param_ty,
1031+
ast_bounds.iter(),
1032+
&mut bounds,
1033+
ty::List::empty(),
1034+
only_self_bounds,
1035+
);
1036+
debug!(?bounds);
1037+
1038+
bounds
10111039
}
10121040

10131041
/// Convert the bounds in `ast_bounds` that refer to traits which define an associated type
@@ -1029,17 +1057,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
10291057
}
10301058
}
10311059

1032-
self.compute_bounds_inner(param_ty, &result)
1033-
}
1034-
1035-
fn compute_bounds_inner(
1036-
&self,
1037-
param_ty: Ty<'tcx>,
1038-
ast_bounds: &[hir::GenericBound<'_>],
1039-
) -> Bounds<'tcx> {
10401060
let mut bounds = Bounds::default();
1041-
1042-
self.add_bounds(param_ty, ast_bounds.iter(), &mut bounds, ty::List::empty());
1061+
self.add_bounds(
1062+
param_ty,
1063+
result.iter(),
1064+
&mut bounds,
1065+
ty::List::empty(),
1066+
OnlySelfBounds(true),
1067+
);
10431068
debug!(?bounds);
10441069

10451070
bounds
@@ -1062,6 +1087,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
10621087
dup_bindings: &mut FxHashMap<DefId, Span>,
10631088
path_span: Span,
10641089
constness: ty::BoundConstness,
1090+
only_self_bounds: OnlySelfBounds,
10651091
) -> Result<(), ErrorGuaranteed> {
10661092
// Given something like `U: SomeTrait<T = X>`, we want to produce a
10671093
// predicate like `<U as SomeTrait>::T = X`. This is somewhat
@@ -1361,8 +1387,20 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
13611387
//
13621388
// Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty`
13631389
// parameter to have a skipped binder.
1364-
let param_ty = tcx.mk_alias(ty::Projection, projection_ty.skip_binder());
1365-
self.add_bounds(param_ty, ast_bounds.iter(), bounds, projection_ty.bound_vars());
1390+
//
1391+
// NOTE: If `only_self_bounds` is true, do NOT expand this associated
1392+
// type bound into a trait predicate, since we only want to add predicates
1393+
// for the `Self` type.
1394+
if !only_self_bounds.0 {
1395+
let param_ty = tcx.mk_alias(ty::Projection, projection_ty.skip_binder());
1396+
self.add_bounds(
1397+
param_ty,
1398+
ast_bounds.iter(),
1399+
bounds,
1400+
projection_ty.bound_vars(),
1401+
only_self_bounds,
1402+
);
1403+
}
13661404
}
13671405
}
13681406
Ok(())
@@ -1403,6 +1441,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
14031441
dummy_self,
14041442
&mut bounds,
14051443
false,
1444+
// FIXME: This should be `true`, but we don't really handle
1445+
// associated type bounds or type aliases in objects in a way
1446+
// that makes this meaningful, I think.
1447+
OnlySelfBounds(false),
14061448
) {
14071449
potential_assoc_types.extend(cur_potential_assoc_types);
14081450
}

compiler/rustc_hir_analysis/src/collect/item_bounds.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::ItemCtxt;
2-
use crate::astconv::AstConv;
2+
use crate::astconv::{AstConv, OnlySelfBounds};
33
use rustc_hir as hir;
44
use rustc_infer::traits::util;
55
use rustc_middle::ty::subst::InternalSubsts;
@@ -26,7 +26,7 @@ fn associated_type_bounds<'tcx>(
2626
);
2727

2828
let icx = ItemCtxt::new(tcx, assoc_item_def_id);
29-
let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds);
29+
let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, OnlySelfBounds(false));
3030
// Associated types are implicitly sized unless a `?Sized` bound is found
3131
icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span);
3232

@@ -67,7 +67,7 @@ fn opaque_type_bounds<'tcx>(
6767
) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
6868
ty::print::with_no_queries!({
6969
let icx = ItemCtxt::new(tcx, opaque_def_id);
70-
let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds);
70+
let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, OnlySelfBounds(false));
7171
// Opaque types are implicitly sized unless a `?Sized` bound is found
7272
icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span);
7373
debug!(?bounds);

compiler/rustc_hir_analysis/src/collect/predicates_of.rs

+50-55
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::astconv::AstConv;
1+
use crate::astconv::{AstConv, OnlySelfBounds};
22
use crate::bounds::Bounds;
33
use crate::collect::ItemCtxt;
44
use crate::constrained_generic_params as cgp;
@@ -14,9 +14,6 @@ use rustc_middle::ty::{GenericPredicates, ToPredicate};
1414
use rustc_span::symbol::{sym, Ident};
1515
use rustc_span::{Span, DUMMY_SP};
1616

17-
#[derive(Debug)]
18-
struct OnlySelfBounds(bool);
19-
2017
/// Returns a list of all type predicates (explicit and implicit) for the definition with
2118
/// ID `def_id`. This includes all predicates returned by `predicates_defined_on`, plus
2219
/// `Self: Trait` predicates for traits.
@@ -99,8 +96,9 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
9996
| ItemKind::Struct(_, generics)
10097
| ItemKind::Union(_, generics) => generics,
10198

102-
ItemKind::Trait(_, _, generics, ..) | ItemKind::TraitAlias(generics, _) => {
103-
is_trait = Some(ty::TraitRef::identity(tcx, def_id.to_def_id()));
99+
ItemKind::Trait(_, _, generics, self_bounds, ..)
100+
| ItemKind::TraitAlias(generics, self_bounds) => {
101+
is_trait = Some(self_bounds);
104102
generics
105103
}
106104
ItemKind::OpaqueTy(OpaqueTy { generics, .. }) => generics,
@@ -122,10 +120,14 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
122120

123121
// Below we'll consider the bounds on the type parameters (including `Self`)
124122
// and the explicit where-clauses, but to get the full set of predicates
125-
// on a trait we need to add in the supertrait bounds and bounds found on
126-
// associated types.
127-
if let Some(_trait_ref) = is_trait {
128-
predicates.extend(tcx.implied_predicates_of(def_id).predicates.iter().cloned());
123+
// on a trait we must also consider the bounds that follow the trait's name,
124+
// like `trait Foo: A + B + C`.
125+
if let Some(self_bounds) = is_trait {
126+
predicates.extend(
127+
icx.astconv()
128+
.compute_bounds(tcx.types.self_param, self_bounds, OnlySelfBounds(false))
129+
.predicates(),
130+
);
129131
}
130132

131133
// In default impls, we can assume that the self type implements
@@ -225,7 +227,13 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
225227
}
226228

227229
let mut bounds = Bounds::default();
228-
icx.astconv().add_bounds(ty, bound_pred.bounds.iter(), &mut bounds, bound_vars);
230+
icx.astconv().add_bounds(
231+
ty,
232+
bound_pred.bounds.iter(),
233+
&mut bounds,
234+
bound_vars,
235+
OnlySelfBounds(false),
236+
);
229237
predicates.extend(bounds.predicates());
230238
}
231239

@@ -608,7 +616,7 @@ pub(super) fn implied_predicates_with_filter(
608616
let (superbounds, where_bounds_that_match) = match filter {
609617
PredicateFilter::All => (
610618
// Convert the bounds that follow the colon (or equal in trait aliases)
611-
icx.astconv().compute_bounds(self_param_ty, bounds),
619+
icx.astconv().compute_bounds(self_param_ty, bounds, OnlySelfBounds(false)),
612620
// Also include all where clause bounds
613621
icx.type_parameter_bounds_in_generics(
614622
generics,
@@ -620,7 +628,7 @@ pub(super) fn implied_predicates_with_filter(
620628
),
621629
PredicateFilter::SelfOnly => (
622630
// Convert the bounds that follow the colon (or equal in trait aliases)
623-
icx.astconv().compute_bounds(self_param_ty, bounds),
631+
icx.astconv().compute_bounds(self_param_ty, bounds, OnlySelfBounds(true)),
624632
// Include where clause bounds for `Self`
625633
icx.type_parameter_bounds_in_generics(
626634
generics,
@@ -774,32 +782,35 @@ impl<'tcx> ItemCtxt<'tcx> {
774782
only_self_bounds: OnlySelfBounds,
775783
assoc_name: Option<Ident>,
776784
) -> Vec<(ty::Predicate<'tcx>, Span)> {
777-
ast_generics
778-
.predicates
779-
.iter()
780-
.filter_map(|wp| match wp {
781-
hir::WherePredicate::BoundPredicate(bp) => Some(bp),
782-
_ => None,
783-
})
784-
.flat_map(|bp| {
785-
let bt = if bp.is_param_bound(param_def_id.to_def_id()) {
786-
Some(ty)
787-
} else if !only_self_bounds.0 {
788-
Some(self.to_ty(bp.bounded_ty))
789-
} else {
790-
None
791-
};
792-
let bvars = self.tcx.late_bound_vars(bp.hir_id);
793-
794-
bp.bounds.iter().filter_map(move |b| bt.map(|bt| (bt, b, bvars))).filter(
795-
|(_, b, _)| match assoc_name {
796-
Some(assoc_name) => self.bound_defines_assoc_item(b, assoc_name),
797-
None => true,
798-
},
799-
)
800-
})
801-
.flat_map(|(bt, b, bvars)| predicates_from_bound(self, bt, b, bvars))
802-
.collect()
785+
let mut bounds = Bounds::default();
786+
787+
for predicate in ast_generics.predicates {
788+
let hir::WherePredicate::BoundPredicate(predicate) = predicate else {
789+
continue;
790+
};
791+
792+
let bound_ty = if predicate.is_param_bound(param_def_id.to_def_id()) {
793+
ty
794+
} else if !only_self_bounds.0 {
795+
self.to_ty(predicate.bounded_ty)
796+
} else {
797+
continue;
798+
};
799+
800+
let bound_vars = self.tcx.late_bound_vars(predicate.hir_id);
801+
self.astconv().add_bounds(
802+
bound_ty,
803+
predicate.bounds.iter().filter(|bound| {
804+
assoc_name
805+
.map_or(true, |assoc_name| self.bound_defines_assoc_item(bound, assoc_name))
806+
}),
807+
&mut bounds,
808+
bound_vars,
809+
only_self_bounds,
810+
);
811+
}
812+
813+
bounds.predicates().collect()
803814
}
804815

805816
#[instrument(level = "trace", skip(self))]
@@ -817,19 +828,3 @@ impl<'tcx> ItemCtxt<'tcx> {
817828
}
818829
}
819830
}
820-
821-
/// Converts a specific `GenericBound` from the AST into a set of
822-
/// predicates that apply to the self type. A vector is returned
823-
/// because this can be anywhere from zero predicates (`T: ?Sized` adds no
824-
/// predicates) to one (`T: Foo`) to many (`T: Bar<X = i32>` adds `T: Bar`
825-
/// and `<T as Bar>::X == i32`).
826-
fn predicates_from_bound<'tcx>(
827-
astconv: &dyn AstConv<'tcx>,
828-
param_ty: Ty<'tcx>,
829-
bound: &'tcx hir::GenericBound<'tcx>,
830-
bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
831-
) -> Vec<(ty::Predicate<'tcx>, Span)> {
832-
let mut bounds = Bounds::default();
833-
astconv.add_bounds(param_ty, [bound].into_iter(), &mut bounds, bound_vars);
834-
bounds.predicates().collect()
835-
}

compiler/rustc_hir_analysis/src/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode,
116116

117117
use std::ops::Not;
118118

119-
use astconv::AstConv;
119+
use astconv::{AstConv, OnlySelfBounds};
120120
use bounds::Bounds;
121121

122122
fluent_messages! { "../messages.ftl" }
@@ -531,6 +531,7 @@ pub fn hir_trait_to_predicates<'tcx>(
531531
self_ty,
532532
&mut bounds,
533533
true,
534+
OnlySelfBounds(false),
534535
);
535536

536537
bounds

0 commit comments

Comments
 (0)