Skip to content

Commit 2bbd469

Browse files
committed
HIR ty lowering: Validate PointeeSized bounds
1 parent 30deea3 commit 2bbd469

File tree

10 files changed

+133
-78
lines changed

10 files changed

+133
-78
lines changed

compiler/rustc_hir_analysis/messages.ftl

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -445,8 +445,6 @@ hir_analysis_parenthesized_fn_trait_expansion =
445445
hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind}
446446
.label = not allowed in type signatures
447447
448-
hir_analysis_pointee_sized_trait_object = `PointeeSized` cannot be used with trait objects
449-
450448
hir_analysis_precise_capture_self_alias = `Self` can't be captured in `use<...>` precise captures list, since it is an alias
451449
.label = `Self` is not a generic argument, but an alias to the type of the {$what}
452450

compiler/rustc_hir_analysis/src/errors.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -311,13 +311,6 @@ pub(crate) struct TraitObjectDeclaredWithNoTraits {
311311
pub trait_alias_span: Option<Span>,
312312
}
313313

314-
#[derive(Diagnostic)]
315-
#[diag(hir_analysis_pointee_sized_trait_object)]
316-
pub(crate) struct PointeeSizedTraitObject {
317-
#[primary_span]
318-
pub span: Span,
319-
}
320-
321314
#[derive(Diagnostic)]
322315
#[diag(hir_analysis_ambiguous_lifetime_bound, code = E0227)]
323316
pub(crate) struct AmbiguousLifetimeBound {

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/dyn_compatibility.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
22
use rustc_errors::codes::*;
33
use rustc_errors::struct_span_code_err;
44
use rustc_hir as hir;
5-
use rustc_hir::LangItem;
65
use rustc_hir::def::{DefKind, Res};
76
use rustc_lint_defs::builtin::UNUSED_ASSOCIATED_TYPE_BOUNDS;
87
use rustc_middle::ty::elaborate::ClauseWithSupertraitSpan;
@@ -70,13 +69,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
7069
let guar = self.report_trait_object_addition_traits(&regular_traits);
7170
return Ty::new_error(tcx, guar);
7271
}
73-
// We don't support `PointeeSized` principals
74-
let pointee_sized_did = tcx.require_lang_item(LangItem::PointeeSized, span);
75-
if regular_traits.iter().any(|(pred, _)| pred.def_id() == pointee_sized_did) {
76-
let guar = self.report_pointee_sized_trait_object(span);
77-
return Ty::new_error(tcx, guar);
78-
}
79-
8072
// Don't create a dyn trait if we have errors in the principal.
8173
if let Err(guar) = regular_traits.error_reported() {
8274
return Ty::new_error(tcx, guar);

compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use tracing::debug;
2929
use super::InherentAssocCandidate;
3030
use crate::errors::{
3131
self, AssocItemConstraintsNotAllowedHere, ManualImplementation, MissingTypeParams,
32-
ParenthesizedFnTraitExpansion, PointeeSizedTraitObject, TraitObjectDeclaredWithNoTraits,
32+
ParenthesizedFnTraitExpansion, TraitObjectDeclaredWithNoTraits,
3333
};
3434
use crate::fluent_generated as fluent;
3535
use crate::hir_ty_lowering::{AssocItemQSelf, HirTyLowerer};
@@ -1405,10 +1405,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
14051405

14061406
self.dcx().emit_err(TraitObjectDeclaredWithNoTraits { span, trait_alias_span })
14071407
}
1408-
1409-
pub(super) fn report_pointee_sized_trait_object(&self, span: Span) -> ErrorGuaranteed {
1410-
self.dcx().emit_err(PointeeSizedTraitObject { span })
1411-
}
14121408
}
14131409

14141410
/// Emit an error for the given associated item constraint.

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -758,13 +758,36 @@ 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+
rustc_ast::BoundPolarity::Maybe(_) => {
787+
(ty::PredicatePolarity::Positive, &mut Vec::new())
788+
}
789+
};
790+
768791
let trait_segment = trait_ref.path.segments.last().unwrap();
769792

770793
let _ = self.prohibit_generic_args(
@@ -781,7 +804,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
781804
Some(self_ty),
782805
);
783806

784-
let tcx = self.tcx();
785807
let bound_vars = tcx.late_bound_vars(trait_ref.hir_ref_id);
786808
debug!(?bound_vars);
787809

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

793815
debug!(?poly_trait_ref);
794816

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-
816817
// We deal with const conditions later.
817818
match predicate_filter {
818819
PredicateFilter::All
@@ -915,7 +916,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
915916
// Don't register any associated item constraints for negative bounds,
916917
// since we should have emitted an error for them earlier, and they
917918
// would not be well-formed!
918-
if polarity != ty::PredicatePolarity::Positive {
919+
if polarity == ty::PredicatePolarity::Negative {
919920
self.dcx().span_delayed_bug(
920921
constraint.span,
921922
"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`.

tests/ui/sized-hierarchy/reject-dyn-pointeesized.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use std::marker::PointeeSized;
44

55
type Foo = dyn PointeeSized;
6-
//~^ ERROR `PointeeSized` cannot be used with trait objects
6+
//~^ ERROR at least one trait is required for an object type
77

88
fn foo(f: &Foo) {}
99

@@ -12,5 +12,5 @@ fn main() {
1212

1313
let x = main;
1414
let y: Box<dyn PointeeSized> = x;
15-
//~^ ERROR `PointeeSized` cannot be used with trait objects
15+
//~^ ERROR at least one trait is required for an object type
1616
}
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
1-
error: `PointeeSized` cannot be used with trait objects
1+
error[E0224]: at least one trait is required for an object type
22
--> $DIR/reject-dyn-pointeesized.rs:5:12
33
|
44
LL | type Foo = dyn PointeeSized;
55
| ^^^^^^^^^^^^^^^^
66

7-
error: `PointeeSized` cannot be used with trait objects
7+
error[E0224]: at least one trait is required for an object type
88
--> $DIR/reject-dyn-pointeesized.rs:14:16
99
|
1010
LL | let y: Box<dyn PointeeSized> = x;
1111
| ^^^^^^^^^^^^^^^^
1212

1313
error: aborting due to 2 previous errors
1414

15+
For more information about this error, try `rustc --explain E0224`.

0 commit comments

Comments
 (0)