Skip to content

Commit c4cf6ba

Browse files
committed
hir_analysis: add missing sizedness bounds
Default sizedness bounds were not being added to `explicit_super_predicates_of` and `explicit_implied_predicates_of` which meant that a trait bound added to a associated type projection would be missing the implied predicate of the default sizedness supertrait of that trait. An unexpected consequence of this change was that the check for multiple principals was now finding an additional `MetaSized` principal when eagerly expanding trait aliases. Instead of special-casing trait aliases as different from traits and not adding a `MetaSized` supertrait to trait aliases, filter out `MetaSized` when lowering `dyn Trait`.
1 parent e821cb8 commit c4cf6ba

File tree

13 files changed

+192
-158
lines changed

13 files changed

+192
-158
lines changed

compiler/rustc_hir_analysis/src/collect/item_bounds.rs

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ use tracing::{debug, instrument};
1212

1313
use super::ItemCtxt;
1414
use super::predicates_of::assert_only_contains_predicates_from;
15-
use crate::hir_ty_lowering::{HirTyLowerer, OverlappingAsssocItemConstraints, PredicateFilter};
15+
use crate::hir_ty_lowering::{
16+
HirTyLowerer, ImpliedBoundsContext, OverlappingAsssocItemConstraints, PredicateFilter,
17+
};
1618

1719
/// For associated types we include both bounds written on the type
1820
/// (`type X: Trait`) and predicates from the trait: `where Self::X: Trait`.
@@ -52,15 +54,20 @@ fn associated_type_bounds<'tcx>(
5254
| PredicateFilter::SelfTraitThatDefines(_)
5355
| PredicateFilter::SelfAndAssociatedTypeBounds => {
5456
// Implicit bounds are added to associated types unless a `?Trait` bound is found.
55-
icx.lowerer().add_sizedness_bounds(
57+
icx.lowerer().add_implicit_sizedness_bounds(
58+
&mut bounds,
59+
item_ty,
60+
hir_bounds,
61+
ImpliedBoundsContext::AssociatedTypeOrImplTrait,
62+
span,
63+
);
64+
icx.lowerer().add_default_traits(
5665
&mut bounds,
5766
item_ty,
5867
hir_bounds,
59-
None,
60-
None,
68+
ImpliedBoundsContext::AssociatedTypeOrImplTrait,
6169
span,
6270
);
63-
icx.lowerer().add_default_traits(&mut bounds, item_ty, hir_bounds, None, span);
6471

6572
// Also collect `where Self::Assoc: Trait` from the parent trait's where clauses.
6673
let trait_def_id = tcx.local_parent(assoc_item_def_id);
@@ -372,15 +379,20 @@ fn opaque_type_bounds<'tcx>(
372379
| PredicateFilter::SelfOnly
373380
| PredicateFilter::SelfTraitThatDefines(_)
374381
| PredicateFilter::SelfAndAssociatedTypeBounds => {
375-
icx.lowerer().add_sizedness_bounds(
382+
icx.lowerer().add_implicit_sizedness_bounds(
383+
&mut bounds,
384+
item_ty,
385+
hir_bounds,
386+
ImpliedBoundsContext::AssociatedTypeOrImplTrait,
387+
span,
388+
);
389+
icx.lowerer().add_default_traits(
376390
&mut bounds,
377391
item_ty,
378392
hir_bounds,
379-
None,
380-
None,
393+
ImpliedBoundsContext::AssociatedTypeOrImplTrait,
381394
span,
382395
);
383-
icx.lowerer().add_default_traits(&mut bounds, item_ty, hir_bounds, None, span);
384396
}
385397
//`ConstIfConst` is only interested in `[const]` bounds.
386398
PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {}

compiler/rustc_hir_analysis/src/collect/predicates_of.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ use crate::collect::ItemCtxt;
1919
use crate::constrained_generic_params as cgp;
2020
use crate::delegation::inherit_predicates_for_delegation_item;
2121
use crate::hir_ty_lowering::{
22-
HirTyLowerer, OverlappingAsssocItemConstraints, PredicateFilter, RegionInferReason,
22+
HirTyLowerer, ImpliedBoundsContext, OverlappingAsssocItemConstraints, PredicateFilter,
23+
RegionInferReason,
2324
};
2425

2526
/// Returns a list of all type predicates (explicit and implicit) for the definition with
@@ -189,12 +190,11 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
189190
PredicateFilter::All,
190191
OverlappingAsssocItemConstraints::Allowed,
191192
);
192-
icx.lowerer().add_sizedness_bounds(
193+
icx.lowerer().add_implicit_sizedness_bounds(
193194
&mut bounds,
194195
tcx.types.self_param,
195196
self_bounds,
196-
None,
197-
Some(def_id),
197+
ImpliedBoundsContext::TraitDef(def_id),
198198
span,
199199
);
200200
icx.lowerer().add_default_super_traits(
@@ -229,19 +229,18 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
229229
let param_ty = icx.lowerer().lower_ty_param(param.hir_id);
230230
let mut bounds = Vec::new();
231231
// Implicit bounds are added to type params unless a `?Trait` bound is found
232-
icx.lowerer().add_sizedness_bounds(
232+
icx.lowerer().add_implicit_sizedness_bounds(
233233
&mut bounds,
234234
param_ty,
235235
&[],
236-
Some((param.def_id, hir_generics.predicates)),
237-
None,
236+
ImpliedBoundsContext::TyParam(param.def_id, hir_generics.predicates),
238237
param.span,
239238
);
240239
icx.lowerer().add_default_traits(
241240
&mut bounds,
242241
param_ty,
243242
&[],
244-
Some((param.def_id, hir_generics.predicates)),
243+
ImpliedBoundsContext::TyParam(param.def_id, hir_generics.predicates),
245244
param.span,
246245
);
247246
trace!(?bounds);
@@ -676,6 +675,13 @@ pub(super) fn implied_predicates_with_filter<'tcx>(
676675
| PredicateFilter::SelfOnly
677676
| PredicateFilter::SelfTraitThatDefines(_)
678677
| PredicateFilter::SelfAndAssociatedTypeBounds => {
678+
icx.lowerer().add_implicit_sizedness_bounds(
679+
&mut bounds,
680+
self_param_ty,
681+
superbounds,
682+
ImpliedBoundsContext::TraitDef(trait_def_id),
683+
item.span,
684+
);
679685
icx.lowerer().add_default_super_traits(
680686
trait_def_id,
681687
&mut bounds,

compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs

Lines changed: 60 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,10 @@ use rustc_trait_selection::traits;
1818
use smallvec::SmallVec;
1919
use tracing::{debug, instrument};
2020

21-
use super::errors::GenericsArgsErrExtend;
2221
use crate::errors;
2322
use crate::hir_ty_lowering::{
24-
AssocItemQSelf, FeedConstTy, HirTyLowerer, OverlappingAsssocItemConstraints, PredicateFilter,
25-
RegionInferReason,
23+
AssocItemQSelf, FeedConstTy, GenericsArgsErrExtend, HirTyLowerer, ImpliedBoundsContext,
24+
OverlappingAsssocItemConstraints, PredicateFilter, RegionInferReason,
2625
};
2726

2827
#[derive(Debug, Default)]
@@ -62,7 +61,7 @@ impl CollectedSizednessBounds {
6261

6362
fn search_bounds_for<'tcx>(
6463
hir_bounds: &'tcx [hir::GenericBound<'tcx>],
65-
self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
64+
context: ImpliedBoundsContext<'tcx>,
6665
mut f: impl FnMut(&'tcx PolyTraitRef<'tcx>),
6766
) {
6867
let mut search_bounds = |hir_bounds: &'tcx [hir::GenericBound<'tcx>]| {
@@ -76,7 +75,7 @@ fn search_bounds_for<'tcx>(
7675
};
7776

7877
search_bounds(hir_bounds);
79-
if let Some((self_ty, where_clause)) = self_ty_where_predicates {
78+
if let ImpliedBoundsContext::TyParam(self_ty, where_clause) = context {
8079
for clause in where_clause {
8180
if let hir::WherePredicateKind::BoundPredicate(pred) = clause.kind
8281
&& pred.is_param_bound(self_ty.to_def_id())
@@ -89,10 +88,10 @@ fn search_bounds_for<'tcx>(
8988

9089
fn collect_relaxed_bounds<'tcx>(
9190
hir_bounds: &'tcx [hir::GenericBound<'tcx>],
92-
self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
91+
context: ImpliedBoundsContext<'tcx>,
9392
) -> SmallVec<[&'tcx PolyTraitRef<'tcx>; 1]> {
9493
let mut relaxed_bounds: SmallVec<[_; 1]> = SmallVec::new();
95-
search_bounds_for(hir_bounds, self_ty_where_predicates, |ptr| {
94+
search_bounds_for(hir_bounds, context, |ptr| {
9695
if matches!(ptr.modifiers.polarity, hir::BoundPolarity::Maybe(_)) {
9796
relaxed_bounds.push(ptr);
9897
}
@@ -102,11 +101,11 @@ fn collect_relaxed_bounds<'tcx>(
102101

103102
fn collect_bounds<'a, 'tcx>(
104103
hir_bounds: &'a [hir::GenericBound<'tcx>],
105-
self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
104+
context: ImpliedBoundsContext<'tcx>,
106105
target_did: DefId,
107106
) -> CollectedBound {
108107
let mut collect_into = CollectedBound::default();
109-
search_bounds_for(hir_bounds, self_ty_where_predicates, |ptr| {
108+
search_bounds_for(hir_bounds, context, |ptr| {
110109
if !matches!(ptr.trait_ref.path.res, Res::Def(DefKind::Trait, did) if did == target_did) {
111110
return;
112111
}
@@ -123,17 +122,17 @@ fn collect_bounds<'a, 'tcx>(
123122
fn collect_sizedness_bounds<'tcx>(
124123
tcx: TyCtxt<'tcx>,
125124
hir_bounds: &'tcx [hir::GenericBound<'tcx>],
126-
self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
125+
context: ImpliedBoundsContext<'tcx>,
127126
span: Span,
128127
) -> CollectedSizednessBounds {
129128
let sized_did = tcx.require_lang_item(hir::LangItem::Sized, span);
130-
let sized = collect_bounds(hir_bounds, self_ty_where_predicates, sized_did);
129+
let sized = collect_bounds(hir_bounds, context, sized_did);
131130

132131
let meta_sized_did = tcx.require_lang_item(hir::LangItem::MetaSized, span);
133-
let meta_sized = collect_bounds(hir_bounds, self_ty_where_predicates, meta_sized_did);
132+
let meta_sized = collect_bounds(hir_bounds, context, meta_sized_did);
134133

135134
let pointee_sized_did = tcx.require_lang_item(hir::LangItem::PointeeSized, span);
136-
let pointee_sized = collect_bounds(hir_bounds, self_ty_where_predicates, pointee_sized_did);
135+
let pointee_sized = collect_bounds(hir_bounds, context, pointee_sized_did);
137136

138137
CollectedSizednessBounds { sized, meta_sized, pointee_sized }
139138
}
@@ -161,13 +160,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
161160
/// bounds are present.
162161
/// - On parameters, opaque type, associated types and trait aliases, add a `MetaSized` bound if
163162
/// a `?Sized` bound is present.
164-
pub(crate) fn add_sizedness_bounds(
163+
pub(crate) fn add_implicit_sizedness_bounds(
165164
&self,
166165
bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
167166
self_ty: Ty<'tcx>,
168167
hir_bounds: &'tcx [hir::GenericBound<'tcx>],
169-
self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
170-
trait_did: Option<LocalDefId>,
168+
context: ImpliedBoundsContext<'tcx>,
171169
span: Span,
172170
) {
173171
let tcx = self.tcx();
@@ -181,33 +179,36 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
181179
let pointee_sized_did = tcx.require_lang_item(hir::LangItem::PointeeSized, span);
182180

183181
// If adding sizedness bounds to a trait, then there are some relevant early exits
184-
if let Some(trait_did) = trait_did {
185-
let trait_did = trait_did.to_def_id();
186-
// Never add a default supertrait to `PointeeSized`.
187-
if trait_did == pointee_sized_did {
188-
return;
182+
match context {
183+
ImpliedBoundsContext::TraitDef(trait_did) => {
184+
let trait_did = trait_did.to_def_id();
185+
// Never add a default supertrait to `PointeeSized`.
186+
if trait_did == pointee_sized_did {
187+
return;
188+
}
189+
// Don't add default sizedness supertraits to auto traits because it isn't possible to
190+
// relax an automatically added supertrait on the defn itself.
191+
if tcx.trait_is_auto(trait_did) {
192+
return;
193+
}
189194
}
190-
// Don't add default sizedness supertraits to auto traits because it isn't possible to
191-
// relax an automatically added supertrait on the defn itself.
192-
if tcx.trait_is_auto(trait_did) {
193-
return;
195+
ImpliedBoundsContext::TyParam(..) | ImpliedBoundsContext::AssociatedTypeOrImplTrait => {
196+
// Report invalid relaxed bounds.
197+
// FIXME: Since we only call this validation function here in this function, we only
198+
// fully validate relaxed bounds in contexts where we perform
199+
// "sized elaboration". In most cases that doesn't matter because we *usually*
200+
// reject such relaxed bounds outright during AST lowering.
201+
// However, this can easily get out of sync! Ideally, we would perform this step
202+
// where we are guaranteed to catch *all* bounds like in
203+
// `Self::lower_poly_trait_ref`. List of concrete issues:
204+
// FIXME(more_maybe_bounds): We don't call this for trait object tys, supertrait
205+
// bounds, trait alias bounds, assoc type bounds (ATB)!
206+
let bounds = collect_relaxed_bounds(hir_bounds, context);
207+
self.reject_duplicate_relaxed_bounds(bounds);
194208
}
195-
} else {
196-
// Report invalid relaxed bounds.
197-
// FIXME: Since we only call this validation function here in this function, we only
198-
// fully validate relaxed bounds in contexts where we perform
199-
// "sized elaboration". In most cases that doesn't matter because we *usually*
200-
// reject such relaxed bounds outright during AST lowering.
201-
// However, this can easily get out of sync! Ideally, we would perform this step
202-
// where we are guaranteed to catch *all* bounds like in
203-
// `Self::lower_poly_trait_ref`. List of concrete issues:
204-
// FIXME(more_maybe_bounds): We don't call this for trait object tys, supertrait
205-
// bounds, trait alias bounds, assoc type bounds (ATB)!
206-
let bounds = collect_relaxed_bounds(hir_bounds, self_ty_where_predicates);
207-
self.reject_duplicate_relaxed_bounds(bounds);
208209
}
209210

210-
let collected = collect_sizedness_bounds(tcx, hir_bounds, self_ty_where_predicates, span);
211+
let collected = collect_sizedness_bounds(tcx, hir_bounds, context, span);
211212
if (collected.sized.maybe || collected.sized.negative)
212213
&& !collected.sized.positive
213214
&& !collected.meta_sized.any()
@@ -217,15 +218,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
217218
// other explicit ones) - this can happen for trait aliases as well as bounds.
218219
add_trait_bound(tcx, bounds, self_ty, meta_sized_did, span);
219220
} else if !collected.any() {
220-
if trait_did.is_some() {
221-
// If there are no explicit sizedness bounds on a trait then add a default
222-
// `MetaSized` supertrait.
223-
add_trait_bound(tcx, bounds, self_ty, meta_sized_did, span);
224-
} else {
225-
// If there are no explicit sizedness bounds on a parameter then add a default
226-
// `Sized` bound.
227-
let sized_did = tcx.require_lang_item(hir::LangItem::Sized, span);
228-
add_trait_bound(tcx, bounds, self_ty, sized_did, span);
221+
match context {
222+
ImpliedBoundsContext::TraitDef(..) => {
223+
// If there are no explicit sizedness bounds on a trait then add a default
224+
// `MetaSized` supertrait.
225+
add_trait_bound(tcx, bounds, self_ty, meta_sized_did, span);
226+
}
227+
ImpliedBoundsContext::TyParam(..)
228+
| ImpliedBoundsContext::AssociatedTypeOrImplTrait => {
229+
// If there are no explicit sizedness bounds on a parameter then add a default
230+
// `Sized` bound.
231+
let sized_did = tcx.require_lang_item(hir::LangItem::Sized, span);
232+
add_trait_bound(tcx, bounds, self_ty, sized_did, span);
233+
}
229234
}
230235
}
231236
}
@@ -251,7 +256,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
251256
bounds,
252257
self.tcx().types.self_param,
253258
hir_bounds,
254-
Some((trait_def_id, hir_generics.predicates)),
259+
ImpliedBoundsContext::TyParam(trait_def_id, hir_generics.predicates),
255260
span,
256261
);
257262
}
@@ -261,18 +266,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
261266
bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
262267
self_ty: Ty<'tcx>,
263268
hir_bounds: &[hir::GenericBound<'tcx>],
264-
self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
269+
context: ImpliedBoundsContext<'tcx>,
265270
span: Span,
266271
) {
267272
self.tcx().default_traits().iter().for_each(|default_trait| {
268-
self.add_default_trait(
269-
*default_trait,
270-
bounds,
271-
self_ty,
272-
hir_bounds,
273-
self_ty_where_predicates,
274-
span,
275-
);
273+
self.add_default_trait(*default_trait, bounds, self_ty, hir_bounds, context, span);
276274
});
277275
}
278276

@@ -285,13 +283,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
285283
bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
286284
self_ty: Ty<'tcx>,
287285
hir_bounds: &[hir::GenericBound<'tcx>],
288-
self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
286+
context: ImpliedBoundsContext<'tcx>,
289287
span: Span,
290288
) {
291289
let tcx = self.tcx();
292290
let trait_id = tcx.lang_items().get(trait_);
293291
if let Some(trait_id) = trait_id
294-
&& self.should_add_default_traits(trait_id, hir_bounds, self_ty_where_predicates)
292+
&& self.should_add_default_traits(trait_id, hir_bounds, context)
295293
{
296294
add_trait_bound(tcx, bounds, self_ty, trait_id, span);
297295
}
@@ -302,9 +300,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
302300
&self,
303301
trait_def_id: DefId,
304302
hir_bounds: &'a [hir::GenericBound<'tcx>],
305-
self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
303+
context: ImpliedBoundsContext<'tcx>,
306304
) -> bool {
307-
let collected = collect_bounds(hir_bounds, self_ty_where_predicates, trait_def_id);
305+
let collected = collect_bounds(hir_bounds, context, trait_def_id);
308306
!self.tcx().has_attr(CRATE_DEF_ID, sym::rustc_no_implicit_bounds) && !collected.any()
309307
}
310308

0 commit comments

Comments
 (0)