Skip to content

Commit c74e11c

Browse files
committed
HIR ty lowering: Validate PointeeSized bounds
1 parent c6380f2 commit c74e11c

File tree

4 files changed

+128
-52
lines changed

4 files changed

+128
-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::{CRATE_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
@@ -193,8 +175,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
193175
return;
194176
}
195177

196-
let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, span);
197-
let pointee_sized_did = tcx.require_lang_item(LangItem::PointeeSized, span);
178+
let meta_sized_did = tcx.require_lang_item(hir::LangItem::MetaSized, span);
179+
let pointee_sized_did = tcx.require_lang_item(hir::LangItem::PointeeSized, span);
198180

199181
// If adding sizedness bounds to a trait, then there are some relevant early exits
200182
if let Some(trait_did) = trait_did {
@@ -244,7 +226,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
244226
} else {
245227
// If there are no explicit sizedness bounds on a parameter then add a default
246228
// `Sized` bound.
247-
let sized_did = tcx.require_lang_item(LangItem::Sized, span);
229+
let sized_did = tcx.require_lang_item(hir::LangItem::Sized, span);
248230
add_trait_bound(tcx, bounds, self_ty, sized_did, span);
249231
}
250232
}
@@ -476,10 +458,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
476458
'tcx: 'hir,
477459
{
478460
for hir_bound in hir_bounds {
479-
if self.should_skip_sizedness_bound(hir_bound) {
480-
continue;
481-
}
482-
483461
// In order to avoid cycles, when we're lowering `SelfTraitThatDefines`,
484462
// we skip over any traits that don't define the given associated type.
485463
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: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
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 T where (): 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+
12+
const fn test<T, U>() where T: const PointeeSized, U: [const] PointeeSized {}
13+
//~^ ERROR `const` can only be applied to `#[const_trait]` traits
14+
//~| ERROR `const` can only be applied to `#[const_trait]` traits
15+
//~| ERROR const trait impls are experimental
16+
//~| ERROR `[const]` can only be applied to `#[const_trait]` traits
17+
//~| ERROR `[const]` can only be applied to `#[const_trait]` traits
18+
//~| ERROR const trait impls are experimental
19+
20+
fn main() {}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
error[E0658]: const trait impls are experimental
2+
--> $DIR/pointee-validation.rs:12:32
3+
|
4+
LL | const fn test<T, U>() where T: const PointeeSized, U: [const] PointeeSized {}
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[E0658]: const trait impls are experimental
12+
--> $DIR/pointee-validation.rs:12:53
13+
|
14+
LL | const fn test<T, U>() where T: const PointeeSized, U: [const] PointeeSized {}
15+
| ^^^^^^^^^
16+
|
17+
= note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
18+
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
19+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
20+
21+
error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
22+
--> $DIR/pointee-validation.rs:8:20
23+
|
24+
LL | struct T where (): PointeeSized<(), Undefined = ()>;
25+
| ^^^^^^^^^^^^-------------------- help: remove the unnecessary generics
26+
| |
27+
| expected 0 generic arguments
28+
29+
error[E0220]: associated type `Undefined` not found for `PointeeSized`
30+
--> $DIR/pointee-validation.rs:8:37
31+
|
32+
LL | struct T where (): PointeeSized<(), Undefined = ()>;
33+
| ^^^^^^^^^ associated type `Undefined` not found
34+
35+
error: `const` can only be applied to `#[const_trait]` traits
36+
--> $DIR/pointee-validation.rs:12:32
37+
|
38+
LL | const fn test<T, U>() where T: const PointeeSized, U: [const] PointeeSized {}
39+
| ^^^^^ can't be applied to `PointeeSized`
40+
|
41+
note: `PointeeSized` can't be used with `const` because it isn't annotated with `#[const_trait]`
42+
--> $SRC_DIR/core/src/marker.rs:LL:COL
43+
44+
error: `[const]` can only be applied to `#[const_trait]` traits
45+
--> $DIR/pointee-validation.rs:12:53
46+
|
47+
LL | const fn test<T, U>() where T: const PointeeSized, U: [const] PointeeSized {}
48+
| ^^^^^^^^^ can't be applied to `PointeeSized`
49+
|
50+
note: `PointeeSized` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
51+
--> $SRC_DIR/core/src/marker.rs:LL:COL
52+
53+
error: `const` can only be applied to `#[const_trait]` traits
54+
--> $DIR/pointee-validation.rs:12:32
55+
|
56+
LL | const fn test<T, U>() where T: const PointeeSized, U: [const] PointeeSized {}
57+
| ^^^^^ can't be applied to `PointeeSized`
58+
|
59+
note: `PointeeSized` can't be used with `const` because it isn't annotated with `#[const_trait]`
60+
--> $SRC_DIR/core/src/marker.rs:LL:COL
61+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
62+
63+
error: `[const]` can only be applied to `#[const_trait]` traits
64+
--> $DIR/pointee-validation.rs:12:53
65+
|
66+
LL | const fn test<T, U>() where T: const PointeeSized, U: [const] PointeeSized {}
67+
| ^^^^^^^^^ can't be applied to `PointeeSized`
68+
|
69+
note: `PointeeSized` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
70+
--> $SRC_DIR/core/src/marker.rs:LL:COL
71+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
72+
73+
error: aborting due to 8 previous errors
74+
75+
Some errors have detailed explanations: E0107, E0220, E0658.
76+
For more information about an error, try `rustc --explain E0107`.

0 commit comments

Comments
 (0)