Skip to content

Commit 04dad4e

Browse files
committed
HIR ty lowering: Validate PointeeSized bounds
1 parent e6cadca commit 04dad4e

File tree

4 files changed

+83
-52
lines changed

4 files changed

+83
-52
lines changed

compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs

Lines changed: 7 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use rustc_errors::struct_span_code_err;
66
use rustc_hir as hir;
77
use rustc_hir::def::{DefKind, Res};
88
use rustc_hir::def_id::{DefId, LocalDefId};
9-
use rustc_hir::{AmbigArg, LangItem, PolyTraitRef};
9+
use rustc_hir::{AmbigArg, PolyTraitRef};
1010
use rustc_middle::bug;
1111
use rustc_middle::ty::{
1212
self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
@@ -124,13 +124,13 @@ fn collect_sizedness_bounds<'tcx>(
124124
self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
125125
span: Span,
126126
) -> CollectedSizednessBounds {
127-
let sized_did = tcx.require_lang_item(LangItem::Sized, span);
127+
let sized_did = tcx.require_lang_item(hir::LangItem::Sized, span);
128128
let sized = collect_bounds(hir_bounds, self_ty_where_predicates, sized_did);
129129

130-
let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, span);
130+
let meta_sized_did = tcx.require_lang_item(hir::LangItem::MetaSized, span);
131131
let meta_sized = collect_bounds(hir_bounds, self_ty_where_predicates, meta_sized_did);
132132

133-
let pointee_sized_did = tcx.require_lang_item(LangItem::PointeeSized, span);
133+
let pointee_sized_did = tcx.require_lang_item(hir::LangItem::PointeeSized, span);
134134
let pointee_sized = collect_bounds(hir_bounds, self_ty_where_predicates, pointee_sized_did);
135135

136136
CollectedSizednessBounds { sized, meta_sized, pointee_sized }
@@ -151,24 +151,6 @@ fn add_trait_bound<'tcx>(
151151
}
152152

153153
impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
154-
/// Skip `PointeeSized` bounds.
155-
///
156-
/// `PointeeSized` is a "fake bound" insofar as anywhere a `PointeeSized` bound exists, there
157-
/// is actually the absence of any bounds. This avoids limitations around non-global where
158-
/// clauses being preferred over item bounds (where `PointeeSized` bounds would be
159-
/// proven) - which can result in errors when a `PointeeSized` supertrait/bound/predicate is
160-
/// added to some items.
161-
pub(crate) fn should_skip_sizedness_bound<'hir>(
162-
&self,
163-
bound: &'hir hir::GenericBound<'tcx>,
164-
) -> bool {
165-
bound
166-
.trait_ref()
167-
.and_then(|tr| tr.trait_def_id())
168-
.map(|did| self.tcx().is_lang_item(did, LangItem::PointeeSized))
169-
.unwrap_or(false)
170-
}
171-
172154
/// Adds sizedness bounds to a trait, trait alias, parameter, opaque type or associated type.
173155
///
174156
/// - On parameters, opaque type and associated types, add default `Sized` bound if no explicit
@@ -188,8 +170,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
188170
) {
189171
let tcx = self.tcx();
190172

191-
let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, span);
192-
let pointee_sized_did = tcx.require_lang_item(LangItem::PointeeSized, span);
173+
let meta_sized_did = tcx.require_lang_item(hir::LangItem::MetaSized, span);
174+
let pointee_sized_did = tcx.require_lang_item(hir::LangItem::PointeeSized, span);
193175

194176
// If adding sizedness bounds to a trait, then there are some relevant early exits
195177
if let Some(trait_did) = trait_did {
@@ -230,7 +212,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
230212
} else {
231213
// If there are no explicit sizedness bounds on a parameter then add a default
232214
// `Sized` bound.
233-
let sized_did = tcx.require_lang_item(LangItem::Sized, span);
215+
let sized_did = tcx.require_lang_item(hir::LangItem::Sized, span);
234216
add_trait_bound(tcx, bounds, self_ty, sized_did, span);
235217
}
236218
}
@@ -465,10 +447,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
465447
'tcx: 'hir,
466448
{
467449
for hir_bound in hir_bounds {
468-
if self.should_skip_sizedness_bound(hir_bound) {
469-
continue;
470-
}
471-
472450
// In order to avoid cycles, when we're lowering `SelfTraitThatDefines`,
473451
// we skip over any traits that don't define the given associated type.
474452
if let PredicateFilter::SelfTraitThatDefines(assoc_ident) = predicate_filter {

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -758,13 +758,37 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
758758
bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
759759
predicate_filter: PredicateFilter,
760760
) -> GenericArgCountResult {
761+
let tcx = self.tcx();
762+
761763
// We use the *resolved* bound vars later instead of the HIR ones since the former
762764
// also include the bound vars of the overarching predicate if applicable.
763765
let hir::PolyTraitRef { bound_generic_params: _, modifiers, ref trait_ref, span } =
764766
*poly_trait_ref;
765767
let hir::TraitBoundModifiers { constness, polarity } = modifiers;
766768

767769
let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise());
770+
771+
let (polarity, bounds) = match polarity {
772+
rustc_ast::BoundPolarity::Positive
773+
if tcx.is_lang_item(trait_def_id, hir::LangItem::PointeeSized) =>
774+
{
775+
// Skip `PointeeSized` bounds.
776+
//
777+
// `PointeeSized` is a "fake bound" insofar as anywhere a `PointeeSized` bound exists, there
778+
// is actually the absence of any bounds. This avoids limitations around non-global where
779+
// clauses being preferred over item bounds (where `PointeeSized` bounds would be
780+
// proven) - which can result in errors when a `PointeeSized` supertrait/bound/predicate is
781+
// added to some items.
782+
(ty::PredicatePolarity::Positive, &mut Vec::new())
783+
}
784+
rustc_ast::BoundPolarity::Positive => (ty::PredicatePolarity::Positive, bounds),
785+
rustc_ast::BoundPolarity::Negative(_) => (ty::PredicatePolarity::Negative, bounds),
786+
// FIXME(fmease): This is super hacky! `Option<Polarity>` is also sad.
787+
rustc_ast::BoundPolarity::Maybe(_) => {
788+
(ty::PredicatePolarity::Positive, &mut Vec::new())
789+
}
790+
};
791+
768792
let trait_segment = trait_ref.path.segments.last().unwrap();
769793

770794
let _ = self.prohibit_generic_args(
@@ -781,7 +805,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
781805
Some(self_ty),
782806
);
783807

784-
let tcx = self.tcx();
785808
let bound_vars = tcx.late_bound_vars(trait_ref.hir_ref_id);
786809
debug!(?bound_vars);
787810

@@ -792,27 +815,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
792815

793816
debug!(?poly_trait_ref);
794817

795-
let polarity = match polarity {
796-
rustc_ast::BoundPolarity::Positive => ty::PredicatePolarity::Positive,
797-
rustc_ast::BoundPolarity::Negative(_) => ty::PredicatePolarity::Negative,
798-
rustc_ast::BoundPolarity::Maybe(_) => {
799-
// Validate associated type at least. We may want to reject these
800-
// outright in the future...
801-
for constraint in trait_segment.args().constraints {
802-
let _ = self.lower_assoc_item_constraint(
803-
trait_ref.hir_ref_id,
804-
poly_trait_ref,
805-
constraint,
806-
&mut Default::default(),
807-
&mut Default::default(),
808-
constraint.span,
809-
predicate_filter,
810-
);
811-
}
812-
return arg_count;
813-
}
814-
};
815-
816818
// We deal with const conditions later.
817819
match predicate_filter {
818820
PredicateFilter::All
@@ -915,7 +917,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
915917
// Don't register any associated item constraints for negative bounds,
916918
// since we should have emitted an error for them earlier, and they
917919
// would not be well-formed!
918-
if polarity != ty::PredicatePolarity::Positive {
920+
if polarity == ty::PredicatePolarity::Negative {
919921
self.dcx().span_delayed_bug(
920922
constraint.span,
921923
"negative trait bounds should not have assoc item constraints",
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Test that despite us dropping `PointeeSized` bounds during HIR ty lowering
2+
// we still validate it first.
3+
// issue: <https://github.com/rust-lang/rust/issues/142718>
4+
#![feature(sized_hierarchy)]
5+
6+
use std::marker::PointeeSized;
7+
8+
struct Test where (): const PointeeSized<(), Undefined = ()>;
9+
//~^ ERROR trait takes 0 generic arguments but 1 generic argument was supplied
10+
//~| ERROR associated type `Undefined` not found for `PointeeSized`
11+
//~| ERROR `const` can only be applied to `#[const_trait]` traits
12+
//~| ERROR const trait impls are experimental
13+
14+
fn main() {}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
error[E0658]: const trait impls are experimental
2+
--> $DIR/pointee-validation.rs:8:23
3+
|
4+
LL | struct Test where (): const PointeeSized<(), Undefined = ()>;
5+
| ^^^^^
6+
|
7+
= note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
8+
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
9+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
10+
11+
error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
12+
--> $DIR/pointee-validation.rs:8:29
13+
|
14+
LL | struct Test where (): const PointeeSized<(), Undefined = ()>;
15+
| ^^^^^^^^^^^^-------------------- help: remove the unnecessary generics
16+
| |
17+
| expected 0 generic arguments
18+
19+
error: `const` can only be applied to `#[const_trait]` traits
20+
--> $DIR/pointee-validation.rs:8:23
21+
|
22+
LL | struct Test where (): const PointeeSized<(), Undefined = ()>;
23+
| ^^^^^ can't be applied to `PointeeSized`
24+
|
25+
note: `PointeeSized` can't be used with `const` because it isn't annotated with `#[const_trait]`
26+
--> $SRC_DIR/core/src/marker.rs:LL:COL
27+
28+
error[E0220]: associated type `Undefined` not found for `PointeeSized`
29+
--> $DIR/pointee-validation.rs:8:46
30+
|
31+
LL | struct Test where (): const PointeeSized<(), Undefined = ()>;
32+
| ^^^^^^^^^ associated type `Undefined` not found
33+
34+
error: aborting due to 4 previous errors
35+
36+
Some errors have detailed explanations: E0107, E0220, E0658.
37+
For more information about an error, try `rustc --explain E0107`.

0 commit comments

Comments
 (0)