Skip to content

Commit be9ac56

Browse files
author
Lukas Markeffsky
committed
make Thin a supertrait of Sized
1 parent 5abfbaa commit be9ac56

19 files changed

+235
-108
lines changed

compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs

+4-16
Original file line numberDiff line numberDiff line change
@@ -555,22 +555,6 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
555555
.instantiate(tcx, &[ty::GenericArg::from(goal.predicate.self_ty())])
556556
}
557557

558-
ty::Alias(_, _) | ty::Param(_) | ty::Placeholder(..) => {
559-
// This is the "fallback impl" for type parameters, unnormalizable projections
560-
// and opaque types: If the `self_ty` is `Sized`, then the metadata is `()`.
561-
// FIXME(ptr_metadata): This impl overlaps with the other impls and shouldn't
562-
// exist. Instead, `Pointee<Metadata = ()>` should be a supertrait of `Sized`.
563-
let sized_predicate = ty::TraitRef::from_lang_item(
564-
tcx,
565-
LangItem::Sized,
566-
DUMMY_SP,
567-
[ty::GenericArg::from(goal.predicate.self_ty())],
568-
);
569-
// FIXME(-Znext-solver=coinductive): Should this be `GoalSource::ImplWhereBound`?
570-
ecx.add_goal(GoalSource::Misc, goal.with(tcx, sized_predicate));
571-
tcx.types.unit
572-
}
573-
574558
ty::Adt(def, args) if def.is_struct() => match def.non_enum_variant().tail_opt() {
575559
None => tcx.types.unit,
576560
Some(tail_def) => {
@@ -585,6 +569,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
585569
Some(&tail_ty) => Ty::new_projection(tcx, metadata_def_id, [tail_ty]),
586570
},
587571

572+
// The metadata of these types can only be known from param env or alias bound
573+
// candidates.
574+
ty::Alias(_, _) | ty::Param(_) | ty::Placeholder(..) => return Err(NoSolution),
575+
588576
ty::Infer(
589577
ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_),
590578
)

compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs

+18-4
Original file line numberDiff line numberDiff line change
@@ -123,17 +123,31 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
123123
})
124124
.collect();
125125

126+
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
127+
enum ErrorOrd {
128+
Default,
129+
Sized,
130+
Metadata,
131+
Coerce,
132+
WellFormed,
133+
}
134+
126135
// Ensure `T: Sized` and `T: WF` obligations come last. This lets us display diagnostics
127136
// with more relevant type information and hide redundant E0282 ("type annotations needed") errors.
128137
errors.sort_by_key(|e| match e.obligation.predicate.kind().skip_binder() {
129138
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred))
130139
if Some(pred.def_id()) == self.tcx.lang_items().sized_trait() =>
131140
{
132-
1
141+
ErrorOrd::Sized
142+
}
143+
ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred))
144+
if Some(pred.def_id()) == self.tcx.lang_items().metadata_type() =>
145+
{
146+
ErrorOrd::Metadata
133147
}
134-
ty::PredicateKind::Coerce(_) => 2,
135-
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => 3,
136-
_ => 0,
148+
ty::PredicateKind::Coerce(_) => ErrorOrd::Coerce,
149+
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => ErrorOrd::WellFormed,
150+
_ => ErrorOrd::Default,
137151
});
138152

139153
for (index, error) in errors.iter().enumerate() {

compiler/rustc_trait_selection/src/traits/project.rs

+35-46
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
2323
use crate::infer::{BoundRegionConversionTime, InferOk};
2424
use crate::traits::normalize::normalize_with_depth;
2525
use crate::traits::normalize::normalize_with_depth_to;
26-
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
2726
use crate::traits::select::ProjectionMatchesProjection;
2827
use rustc_data_structures::sso::SsoHashSet;
2928
use rustc_data_structures::stack::ensure_sufficient_stack;
@@ -975,9 +974,12 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
975974
//
976975
// NOTE: This should be kept in sync with the similar code in
977976
// `rustc_ty_utils::instance::resolve_associated_item()`.
978-
let node_item =
979-
specialization_graph::assoc_def(selcx.tcx(), impl_data.impl_def_id, obligation.predicate.def_id)
980-
.map_err(|ErrorGuaranteed { .. }| ())?;
977+
let node_item = specialization_graph::assoc_def(
978+
selcx.tcx(),
979+
impl_data.impl_def_id,
980+
obligation.predicate.def_id,
981+
)
982+
.map_err(|ErrorGuaranteed { .. }| ())?;
981983

982984
if node_item.is_final() {
983985
// Non-specializable items are always projectable.
@@ -1020,7 +1022,8 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
10201022
lang_items.async_fn_trait(),
10211023
lang_items.async_fn_mut_trait(),
10221024
lang_items.async_fn_once_trait(),
1023-
].contains(&Some(trait_ref.def_id))
1025+
]
1026+
.contains(&Some(trait_ref.def_id))
10241027
{
10251028
true
10261029
} else if lang_items.async_fn_kind_helper() == Some(trait_ref.def_id) {
@@ -1033,7 +1036,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
10331036
true
10341037
} else {
10351038
obligation.predicate.args.type_at(0).to_opt_closure_kind().is_some()
1036-
&& obligation.predicate.args.type_at(1).to_opt_closure_kind().is_some()
1039+
&& obligation.predicate.args.type_at(1).to_opt_closure_kind().is_some()
10371040
}
10381041
} else if lang_items.discriminant_kind_trait() == Some(trait_ref.def_id) {
10391042
match self_ty.kind() {
@@ -1116,34 +1119,28 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
11161119
// If returned by `struct_tail_without_normalization` this is the empty tuple.
11171120
| ty::Tuple(..)
11181121
// Integers and floats are always Sized, and so have unit type metadata.
1119-
| ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..)) => true,
1122+
| ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..))
1123+
// `{type error}` is sized, so its metadata must be the unit type.
1124+
| ty::Error(_) => true,
11201125

1121-
// We normalize from `Wrapper<Tail>::Metadata` to `Tail::Metadata` if able.
1122-
// Otherwise, type parameters, opaques, and unnormalized projections have
1123-
// unit metadata if they're known (e.g. by the param_env) to be sized.
1124-
ty::Param(_) | ty::Alias(..)
1125-
if self_ty != tail || selcx.infcx.predicate_must_hold_modulo_regions(
1126-
&obligation.with(
1127-
selcx.tcx(),
1128-
ty::TraitRef::from_lang_item(selcx.tcx(), LangItem::Sized, obligation.cause.span(),[self_ty]),
1129-
),
1130-
) =>
1131-
{
1132-
true
1133-
}
1126+
// We normalize from `Wrapper<Tail>::Metadata` to `Tail::Metadata`.
1127+
ty::Param(_) | ty::Alias(..) => self_ty != tail,
11341128

1135-
// FIXME(compiler-errors): are Bound and Placeholder types ever known sized?
1136-
ty::Param(_)
1137-
| ty::Alias(..)
1138-
| ty::Bound(..)
1139-
| ty::Placeholder(..)
1140-
| ty::Infer(..)
1141-
| ty::Error(_) => {
1142-
if tail.has_infer_types() {
1143-
candidate_set.mark_ambiguous();
1144-
}
1129+
// FIXME: These should probably project to the tail as well.
1130+
ty::Bound(..) | ty::Placeholder(..) => false,
1131+
1132+
ty::Infer(ty::TyVar(_)) => {
1133+
candidate_set.mark_ambiguous();
11451134
false
11461135
}
1136+
1137+
ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
1138+
span_bug!(
1139+
obligation.cause.span,
1140+
"unexpected self ty `{self_ty:?}` when normalizing \
1141+
`<T as Pointee>::Metadata`",
1142+
)
1143+
}
11471144
}
11481145
} else {
11491146
bug!("unexpected builtin trait with associated type: {trait_ref:?}")
@@ -1190,7 +1187,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
11901187
obligation.cause.span,
11911188
format!("Cannot project an associated type from `{impl_source:?}`"),
11921189
);
1193-
return Err(())
1190+
return Err(());
11941191
}
11951192
};
11961193

@@ -1510,23 +1507,15 @@ fn confirm_builtin_candidate<'cx, 'tcx>(
15101507
};
15111508
let metadata_ty = self_ty.ptr_metadata_ty_or_tail(tcx, normalize).unwrap_or_else(|tail| {
15121509
if tail == self_ty {
1513-
// This is the "fallback impl" for type parameters, unnormalizable projections
1514-
// and opaque types: If the `self_ty` is `Sized`, then the metadata is `()`.
1515-
// FIXME(ptr_metadata): This impl overlaps with the other impls and shouldn't
1516-
// exist. Instead, `Pointee<Metadata = ()>` should be a supertrait of `Sized`.
1517-
let sized_predicate = ty::TraitRef::from_lang_item(
1518-
tcx,
1519-
LangItem::Sized,
1520-
obligation.cause.span(),
1521-
[self_ty],
1510+
span_bug!(
1511+
obligation.cause.span,
1512+
"`<{self_ty:?} as Pointee>::Metadata` projection candidate assembled, \
1513+
but we cannot project further",
15221514
);
1523-
obligations.push(obligation.with(tcx, sized_predicate));
1524-
tcx.types.unit
1525-
} else {
1526-
// We know that `self_ty` has the same metadata as `tail`. This allows us
1527-
// to prove predicates like `Wrapper<Tail>::Metadata == Tail::Metadata`.
1528-
Ty::new_projection(tcx, metadata_def_id, [tail])
15291515
}
1516+
// We know that `self_ty` has the same metadata as `tail`. This allows us
1517+
// to prove predicates like `Wrapper<Tail>::Metadata == Tail::Metadata`.
1518+
Ty::new_projection(tcx, metadata_def_id, [tail])
15301519
});
15311520
(metadata_ty.into(), obligations)
15321521
} else {

library/core/src/marker.rs

+13
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,19 @@ unsafe impl<T: Sync + ?Sized> Send for &T {}
142142
#[rustc_specialization_trait]
143143
#[rustc_deny_explicit_impl(implement_via_object = false)]
144144
#[rustc_coinductive]
145+
#[cfg(not(bootstrap))]
146+
pub trait Sized: crate::ptr::Thin {
147+
// Empty.
148+
}
149+
150+
#[stable(feature = "rust1", since = "1.0.0")]
151+
#[lang = "sized"]
152+
#[fundamental]
153+
#[rustc_specialization_trait]
154+
#[rustc_deny_explicit_impl(implement_via_object = false)]
155+
#[rustc_coinductive]
156+
#[cfg(bootstrap)]
157+
#[allow(missing_docs)]
145158
pub trait Sized {
146159
// Empty.
147160
}

tests/ui/feature-gates/feature-gate-trivial_bounds.rs

+1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ struct TwoStrs(str, str) where str: Sized; //~ ERROR
5353

5454

5555
fn unsized_local() where Dst<dyn A>: Sized { //~ ERROR
56+
//~^ ERROR type mismatch resolving `<Dst<dyn A> as Pointee>::Metadata == ()`
5657
let x: Dst<dyn A> = *(Box::new(Dst { x: 1 }) as Box<Dst<dyn A>>);
5758
}
5859

tests/ui/feature-gates/feature-gate-trivial_bounds.stderr

+13-3
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,17 @@ LL | struct Dst<X: ?Sized> {
102102
= help: see issue #48214
103103
= help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
104104

105+
error[E0271]: type mismatch resolving `<Dst<dyn A> as Pointee>::Metadata == ()`
106+
--> $DIR/feature-gate-trivial_bounds.rs:55:26
107+
|
108+
LL | fn unsized_local() where Dst<dyn A>: Sized {
109+
| ^^^^^^^^^^^^^^^^^ expected `DynMetadata<(dyn A + 'static)>`, found `()`
110+
|
111+
= help: see issue #48214
112+
= help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
113+
105114
error[E0277]: the size for values of type `str` cannot be known at compilation time
106-
--> $DIR/feature-gate-trivial_bounds.rs:59:30
115+
--> $DIR/feature-gate-trivial_bounds.rs:60:30
107116
|
108117
LL | fn return_str() -> str where str: Sized {
109118
| ^^^^^^^^^^ doesn't have a size known at compile-time
@@ -112,6 +121,7 @@ LL | fn return_str() -> str where str: Sized {
112121
= help: see issue #48214
113122
= help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
114123

115-
error: aborting due to 11 previous errors
124+
error: aborting due to 12 previous errors
116125

117-
For more information about this error, try `rustc --explain E0277`.
126+
Some errors have detailed explanations: E0271, E0277.
127+
For more information about an error, try `rustc --explain E0271`.

tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,5 @@ where
2929

3030
fn main() {
3131
let mut list = RcNode::<i32>::new();
32-
//~^ ERROR the size for values of type `Node<i32, RcFamily>` cannot be known at compilation time
32+
//~^ ERROR trait bounds were not satisfied
3333
}

tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.stderr

+7-2
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@ help: consider relaxing the implicit `Sized` restriction
1515
LL | type Pointer<T>: Deref<Target = T> + ?Sized;
1616
| ++++++++
1717

18-
error[E0599]: the size for values of type `Node<i32, RcFamily>` cannot be known at compilation time
18+
error[E0599]: the variant or associated item `new` exists for enum `Node<i32, RcFamily>`, but its trait bounds were not satisfied
1919
--> $DIR/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs:31:35
2020
|
2121
LL | enum Node<T, P: PointerFamily> {
2222
| ------------------------------ variant or associated item `new` not found for this enum because it doesn't satisfy `Node<i32, RcFamily>: Sized`
2323
...
2424
LL | let mut list = RcNode::<i32>::new();
25-
| ^^^ doesn't have a size known at compile-time
25+
| ^^^ variant or associated item cannot be called on `Node<i32, RcFamily>` due to unsatisfied trait bounds
2626
|
2727
note: trait bound `Node<i32, RcFamily>: Sized` was not satisfied
2828
--> $DIR/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs:4:18
@@ -37,6 +37,11 @@ LL | impl<T, P: PointerFamily> Node<T, P>
3737
LL | where
3838
LL | P::Pointer<Node<T, P>>: Sized,
3939
| ^^^^^ unsatisfied trait bound introduced here
40+
= note: the following trait bounds were not satisfied:
41+
`(dyn Deref<Target = Node<i32, RcFamily>> + 'static): Thin`
42+
which is required by `(dyn Deref<Target = Node<i32, RcFamily>> + 'static): Sized`
43+
`<(dyn Deref<Target = Node<i32, RcFamily>> + 'static) as Pointee>::Metadata = ()`
44+
which is required by `(dyn Deref<Target = Node<i32, RcFamily>> + 'static): Sized`
4045
note: the trait `Sized` must be implemented
4146
--> $SRC_DIR/core/src/marker.rs:LL:COL
4247

tests/ui/layout/layout-cycle.rs

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use std::mem;
88

99
pub struct S<T: Tr> {
1010
pub f: <T as Tr>::I,
11+
_tail: (), // without this, we get "reached the recursion limit finding the struct tail" instead
1112
}
1213

1314
pub trait Tr {

tests/ui/sized/recursive-type-coercion-from-never.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ impl A for () {
99
type Assoc = Foo<()>;
1010
}
1111

12-
struct Foo<T: A>(T::Assoc);
12+
struct Foo<T: A>(T::Assoc, ());
1313

1414
fn main() {
15-
Foo::<()>(todo!());
15+
Foo::<()>(todo!(), ());
1616
}

tests/ui/sized/recursive-type-pass.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ impl A for () {
55
// FIXME: it would be nice for this to at least cause a warning.
66
type Assoc = Foo<()>;
77
}
8-
struct Foo<T: A>(T::Assoc);
8+
struct Foo<T: A>(T::Assoc, ());
99

1010
fn main() {}

tests/ui/sized/recursive-type-tail.rs

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//@ check-fail
2+
//@ error-pattern: reached the recursion limit finding the struct tail
3+
4+
trait A { type Assoc; }
5+
6+
impl A for () {
7+
type Assoc = Foo<()>;
8+
}
9+
struct Foo<T: A>(T::Assoc);
10+
11+
fn main() {}
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error: reached the recursion limit finding the struct tail for `<() as A>::Assoc`
2+
|
3+
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]`
4+
5+
error: reached the recursion limit finding the struct tail for `<() as A>::Assoc`
6+
|
7+
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]`
8+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
9+
10+
error: reached the recursion limit finding the struct tail for `<() as A>::Assoc`
11+
|
12+
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]`
13+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
14+
15+
error: reached the recursion limit finding the struct tail for `<() as A>::Assoc`
16+
|
17+
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]`
18+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
19+
20+
error: aborting due to 4 previous errors
21+

tests/ui/trait-bounds/unsized-bound.rs

+3
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,17 @@ trait Trait<A> {}
22
impl<A, B> Trait<(A, B)> for (A, B) where A: ?Sized, B: ?Sized, {}
33
//~^ ERROR E0277
44
//~| ERROR E0277
5+
//~| ERROR type mismatch resolving `<(A, B) as Pointee>::Metadata == ()` [E0271]
56
impl<A, B: ?Sized, C: ?Sized> Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {}
67
//~^ ERROR E0277
78
//~| ERROR E0277
89
//~| ERROR E0277
10+
//~| ERROR type mismatch resolving `<(A, B, C) as Pointee>::Metadata == ()` [E0271]
911
trait Trait2<A> {}
1012
impl<A: ?Sized, B: ?Sized> Trait2<(A, B)> for (A, B) {}
1113
//~^ ERROR E0277
1214
//~| ERROR E0277
15+
//~| ERROR type mismatch resolving `<(A, B) as Pointee>::Metadata == ()` [E0271]
1316
trait Trait3<A> {}
1417
impl<A> Trait3<A> for A where A: ?Sized {}
1518
//~^ ERROR E0277

0 commit comments

Comments
 (0)