Skip to content

Commit 9aabb55

Browse files
move maybe sized check into coherence
1 parent e55e437 commit 9aabb55

File tree

9 files changed

+175
-125
lines changed

9 files changed

+175
-125
lines changed

compiler/rustc_builtin_macros/messages.ftl

-4
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,6 @@ builtin_macros_cfg_accessible_literal_path = `cfg_accessible` path cannot be a l
9595
builtin_macros_cfg_accessible_multiple_paths = multiple `cfg_accessible` paths are specified
9696
builtin_macros_cfg_accessible_unspecified_path = `cfg_accessible` path is not specified
9797
98-
builtin_macros_coerce_pointee_requires_maybe_sized = `derive(CoercePointee)` requires `{$name}` to be marked `?Sized`
99-
100-
builtin_macros_coerce_pointee_requires_one_field = `CoercePointee` can only be derived on `struct`s with at least one field
101-
10298
builtin_macros_coerce_pointee_requires_one_generic = `CoercePointee` can only be derived on `struct`s that are generic over at least one type
10399
104100
builtin_macros_coerce_pointee_requires_one_pointee = exactly one generic type parameter must be marked as `#[pointee]` to derive `CoercePointee` traits

compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs

+3-29
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use rustc_ast::mut_visit::MutVisitor;
44
use rustc_ast::visit::BoundKind;
55
use rustc_ast::{
66
self as ast, GenericArg, GenericBound, GenericParamKind, Generics, ItemKind, MetaItem,
7-
TraitBoundModifiers, TyAlias, VariantData, WherePredicate,
7+
TraitBoundModifiers, TyAlias, WherePredicate,
88
};
99
use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
1010
use rustc_errors::E0802;
@@ -30,16 +30,8 @@ pub(crate) fn expand_deriving_coerce_pointee(
3030
item.visit_with(&mut DetectNonGenericPointeeAttr { cx });
3131

3232
let (name_ident, generics) = if let Annotatable::Item(aitem) = item
33-
&& let ItemKind::Struct(struct_data, g) = &aitem.kind
33+
&& let ItemKind::Struct(_struct_data, g) = &aitem.kind
3434
{
35-
if !matches!(
36-
struct_data,
37-
VariantData::Struct { fields, recovered: _ } | VariantData::Tuple(fields, _)
38-
if !fields.is_empty())
39-
{
40-
cx.dcx().emit_err(RequireOneField { span });
41-
return;
42-
}
4335
(aitem.ident, g)
4436
} else {
4537
cx.dcx().emit_err(RequireTransparent { span });
@@ -206,10 +198,7 @@ pub(crate) fn expand_deriving_coerce_pointee(
206198
pointee_ty_ident.name,
207199
)
208200
{
209-
cx.dcx().emit_err(RequiresMaybeSized {
210-
span: pointee_ty_ident.span,
211-
name: pointee_ty_ident,
212-
});
201+
cx.dcx().span_delayed_bug(pointee_ty_ident.span, "?Sized should be checked");
213202
return;
214203
}
215204
let arg = GenericArg::Type(s_ty.clone());
@@ -487,13 +476,6 @@ struct RequireTransparent {
487476
span: Span,
488477
}
489478

490-
#[derive(Diagnostic)]
491-
#[diag(builtin_macros_coerce_pointee_requires_one_field, code = E0802)]
492-
struct RequireOneField {
493-
#[primary_span]
494-
span: Span,
495-
}
496-
497479
#[derive(Diagnostic)]
498480
#[diag(builtin_macros_coerce_pointee_requires_one_generic, code = E0802)]
499481
struct RequireOneGeneric {
@@ -516,11 +498,3 @@ struct TooManyPointees {
516498
#[label]
517499
another: Span,
518500
}
519-
520-
#[derive(Diagnostic)]
521-
#[diag(builtin_macros_coerce_pointee_requires_maybe_sized, code = E0802)]
522-
struct RequiresMaybeSized {
523-
#[primary_span]
524-
span: Span,
525-
name: Ident,
526-
}

compiler/rustc_codegen_cranelift/example/mini_core.rs

+7
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,13 @@ pub trait Unsize<T: ?Sized> {}
2929
#[lang = "coerce_unsized"]
3030
pub trait CoerceUnsized<T> {}
3131

32+
#[lang = "coerce_pointee_validated"]
33+
pub trait CoercePointeeValidated {
34+
/* compiler built-in */
35+
#[lang = "coerce_pointee_validated_pointee"]
36+
type Pointee: ?Sized;
37+
}
38+
3239
impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
3340
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {}
3441
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *const T {}

compiler/rustc_codegen_gcc/example/mini_core.rs

+39-14
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
#![feature(
2-
no_core, lang_items, intrinsics, unboxed_closures, extern_types,
3-
decl_macro, rustc_attrs, transparent_unions, auto_traits, freeze_impls,
2+
no_core,
3+
lang_items,
4+
intrinsics,
5+
unboxed_closures,
6+
extern_types,
7+
decl_macro,
8+
rustc_attrs,
9+
transparent_unions,
10+
auto_traits,
11+
freeze_impls,
412
thread_local
513
)]
614
#![no_core]
@@ -26,6 +34,13 @@ pub trait Unsize<T: ?Sized> {}
2634
#[lang = "coerce_unsized"]
2735
pub trait CoerceUnsized<T> {}
2836

37+
#[lang = "coerce_pointee_validated"]
38+
pub trait CoercePointeeValidated {
39+
/* compiler built-in */
40+
#[lang = "coerce_pointee_validated_pointee"]
41+
type Pointee: ?Sized;
42+
}
43+
2944
impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
3045
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {}
3146
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *const T {}
@@ -35,13 +50,13 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
3550
pub trait DispatchFromDyn<T> {}
3651

3752
// &T -> &U
38-
impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {}
53+
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {}
3954
// &mut T -> &mut U
40-
impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<&'a mut U> for &'a mut T {}
55+
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<&'a mut U> for &'a mut T {}
4156
// *const T -> *const U
42-
impl<T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<*const U> for *const T {}
57+
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<*const U> for *const T {}
4358
// *mut T -> *mut U
44-
impl<T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<*mut U> for *mut T {}
59+
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<*mut U> for *mut T {}
4560
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Box<U, ()>> for Box<T, ()> {}
4661

4762
#[lang = "legacy_receiver"]
@@ -289,7 +304,6 @@ impl PartialEq for u32 {
289304
}
290305
}
291306

292-
293307
impl PartialEq for u64 {
294308
fn eq(&self, other: &u64) -> bool {
295309
(*self) == (*other)
@@ -476,7 +490,11 @@ fn panic_in_cleanup() -> ! {
476490
#[track_caller]
477491
fn panic_bounds_check(index: usize, len: usize) -> ! {
478492
unsafe {
479-
libc::printf("index out of bounds: the len is %d but the index is %d\n\0" as *const str as *const i8, len, index);
493+
libc::printf(
494+
"index out of bounds: the len is %d but the index is %d\n\0" as *const str as *const i8,
495+
len,
496+
index,
497+
);
480498
intrinsics::abort();
481499
}
482500
}
@@ -504,8 +522,7 @@ pub trait Deref {
504522
fn deref(&self) -> &Self::Target;
505523
}
506524

507-
pub trait Allocator {
508-
}
525+
pub trait Allocator {}
509526

510527
impl Allocator for () {}
511528

@@ -699,19 +716,27 @@ pub struct VaList<'a>(&'a mut VaListImpl);
699716

700717
#[rustc_builtin_macro]
701718
#[rustc_macro_transparency = "semitransparent"]
702-
pub macro stringify($($t:tt)*) { /* compiler built-in */ }
719+
pub macro stringify($($t:tt)*) {
720+
/* compiler built-in */
721+
}
703722

704723
#[rustc_builtin_macro]
705724
#[rustc_macro_transparency = "semitransparent"]
706-
pub macro file() { /* compiler built-in */ }
725+
pub macro file() {
726+
/* compiler built-in */
727+
}
707728

708729
#[rustc_builtin_macro]
709730
#[rustc_macro_transparency = "semitransparent"]
710-
pub macro line() { /* compiler built-in */ }
731+
pub macro line() {
732+
/* compiler built-in */
733+
}
711734

712735
#[rustc_builtin_macro]
713736
#[rustc_macro_transparency = "semitransparent"]
714-
pub macro cfg() { /* compiler built-in */ }
737+
pub macro cfg() {
738+
/* compiler built-in */
739+
}
715740

716741
pub static A_STATIC: u8 = 42;
717742

compiler/rustc_hir_analysis/messages.ftl

+2
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ hir_analysis_cmse_output_stack_spill =
8585
.note1 = functions with the `"{$abi_name}"` ABI must pass their result via the available return registers
8686
.note2 = the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
8787
88+
hir_analysis_coerce_pointee_missing_maybe_sized = `derive(CoercePointee)` requires the `#[pointee]` to be `?Sized`
89+
8890
hir_analysis_coerce_pointee_multiple_derive = `derive(CoercePointee)` is derived multiple times
8991
.label = another derivation originates from here
9092

compiler/rustc_hir_analysis/src/coherence/builtin.rs

+76-33
Original file line numberDiff line numberDiff line change
@@ -328,12 +328,19 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<()
328328
.collect::<Vec<_>>();
329329

330330
if coerced_fields.is_empty() {
331-
// `CoercePointeeValidated` will report a more specific error
332-
res = Err(tcx.dcx().emit_err(errors::DispatchFromDynSingle {
333-
span,
334-
trait_name: "DispatchFromDyn",
335-
note: true,
336-
}));
331+
if coerce_pointee_data.is_some() {
332+
// `CoercePointeeValidated` will report a more specific error
333+
res = Err(tcx.dcx().span_delayed_bug(
334+
span,
335+
"a more specific error from CoercePointee is expected",
336+
))
337+
} else {
338+
res = Err(tcx.dcx().emit_err(errors::DispatchFromDynSingle {
339+
span,
340+
trait_name: "DispatchFromDyn",
341+
note: true,
342+
}));
343+
}
337344
} else if coerced_fields.len() > 1 {
338345
if coerce_pointee_data.is_some() {
339346
let spans =
@@ -405,6 +412,9 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<()
405412
}
406413
res
407414
}
415+
(&Adt(def, _), _) if tcx.coerce_pointee_data(()).contains_key(&def.did()) => {
416+
Err(tcx.dcx().span_delayed_bug(span, "a specific error for CoercePointee is expected"))
417+
}
408418
_ => Err(tcx
409419
.dcx()
410420
.emit_err(errors::CoerceUnsizedMay { span, trait_name: "DispatchFromDyn" })),
@@ -898,23 +908,44 @@ fn visit_implementation_of_coerce_pointee_validity(
898908
checker: &Checker<'_>,
899909
) -> Result<(), ErrorGuaranteed> {
900910
let tcx = checker.tcx;
901-
let self_ty = tcx.impl_trait_ref(checker.impl_def_id).unwrap().instantiate_identity().self_ty();
902-
let span = tcx.def_span(checker.impl_def_id);
903-
if !tcx.is_builtin_derived(checker.impl_def_id.into()) {
911+
let impl_did = checker.impl_def_id;
912+
let self_ty = tcx.impl_trait_ref(impl_did).unwrap().instantiate_identity().self_ty();
913+
let span = tcx.def_span(impl_did);
914+
if !tcx.is_builtin_derived(impl_did.into()) {
904915
return Err(tcx.dcx().emit_err(errors::CoercePointeeNoUserValidityAssertion { span }));
905916
}
906-
let ty::Adt(def, _args) = self_ty.kind() else {
917+
let ty::Adt(def, args) = self_ty.kind() else {
907918
return Err(tcx.dcx().emit_err(errors::CoercePointeeNotConcreteType { span }));
908919
};
909920
let did = def.did();
910921
let Some(info) = tcx.coerce_pointee_data(()).get(&did) else {
911922
return Err(tcx.dcx().emit_err(errors::CoercePointeeNoUserValidityAssertion { span }));
912923
};
913-
if let &ty::CoercePointeeInfo::Duplicated { impls } = info {
914-
return Err(tcx.dcx().emit_err(errors::CoercePointeePointeeMultipleDerive {
915-
spans: impls.iter().copied().map(|did| tcx.def_span(did)).collect(),
916-
}));
917-
}
924+
let pointee_idx = match info {
925+
&ty::CoercePointeeInfo::Validated { pointee_index_in_args, .. } => pointee_index_in_args,
926+
ty::CoercePointeeInfo::PointeeUnnormalized { ty, .. } => {
927+
return Err(tcx.dcx().emit_err(errors::CoercePointeePointeeNotGenericPointee {
928+
span,
929+
got: ty.to_string(),
930+
}));
931+
}
932+
ty::CoercePointeeInfo::PointeeIsConst { konst, .. } => {
933+
return Err(tcx.dcx().emit_err(errors::CoercePointeePointeeNotGenericPointee {
934+
span,
935+
got: konst.to_string(),
936+
}));
937+
}
938+
ty::CoercePointeeInfo::Duplicated { impls } => {
939+
return Err(tcx.dcx().emit_err(errors::CoercePointeePointeeMultipleDerive {
940+
spans: impls.iter().copied().map(|did| tcx.def_span(did)).collect(),
941+
}));
942+
}
943+
ty::CoercePointeeInfo::PointeeNotFound { ty, .. } => {
944+
return Err(tcx
945+
.dcx()
946+
.emit_err(errors::CoercePointeeNoPointee { span, ty: ty.to_string() }));
947+
}
948+
};
918949
// Now get a more precise span of the `struct`.
919950
let span = tcx.def_span(did);
920951
if !def.is_struct() {
@@ -926,8 +957,28 @@ fn visit_implementation_of_coerce_pointee_validity(
926957
return Err(tcx.dcx().emit_err(errors::CoercePointeeNotTransparent { span }));
927958
}
928959
if def.all_fields().next().is_none() {
929-
return Err(tcx.dcx().emit_err(errors::CoercePointeeNoField { span }));
960+
return Err(tcx.dcx().span_delayed_bug(
961+
span,
962+
"a specific error from CoercePointee is expected in CoerceUnsized coherence check",
963+
));
930964
}
965+
966+
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
967+
let param_env = tcx.param_env(impl_did);
968+
let ocx = ObligationCtxt::new(&infcx);
969+
let cause = ObligationCause::misc(span, impl_did);
970+
let pointee_ty = args.type_at(pointee_idx);
971+
let obligation = Obligation::new(
972+
tcx,
973+
cause,
974+
param_env,
975+
ty::TraitRef::new(tcx, tcx.require_lang_item(LangItem::Sized, None), [pointee_ty]),
976+
);
977+
ocx.register_obligation(obligation);
978+
if ocx.select_all_or_error().is_empty() {
979+
return Err(tcx.dcx().emit_err(errors::CoercePointeePointeeMissingMaybeSized { span }));
980+
}
981+
931982
Ok(())
932983
}
933984

@@ -937,24 +988,16 @@ fn try_extract_coerce_pointee_data<'tcx>(
937988
info: &ty::CoercePointeeInfo<'tcx>,
938989
) -> Result<(usize, DefId), ErrorGuaranteed> {
939990
match info {
940-
ty::CoercePointeeInfo::PointeeUnnormalized { ty, .. } => Err(tcx
941-
.dcx()
942-
.emit_err(errors::CoercePointeePointeeNotGenericPointee { span, got: ty.to_string() })),
943-
ty::CoercePointeeInfo::PointeeIsConst { konst, .. } => {
944-
Err(tcx.dcx().emit_err(errors::CoercePointeePointeeNotGenericPointee {
945-
span,
946-
got: konst.to_string(),
947-
}))
948-
}
949-
ty::CoercePointeeInfo::Validated { pointee_index_in_args, impl_def_id } => {
950-
Ok((*pointee_index_in_args, *impl_def_id))
951-
}
952-
ty::CoercePointeeInfo::Duplicated { .. } => Err(tcx
953-
.dcx()
954-
.span_delayed_bug(span, "a special error for duplicated CoercePointee is expected")),
955-
ty::CoercePointeeInfo::PointeeNotFound { ty, .. } => {
956-
Err(tcx.dcx().emit_err(errors::CoercePointeeNoPointee { span, ty: ty.to_string() }))
991+
&ty::CoercePointeeInfo::Validated { pointee_index_in_args, impl_def_id } => {
992+
Ok((pointee_index_in_args, impl_def_id))
957993
}
994+
ty::CoercePointeeInfo::PointeeUnnormalized { .. }
995+
| ty::CoercePointeeInfo::PointeeIsConst { .. }
996+
| ty::CoercePointeeInfo::PointeeNotFound { .. }
997+
| ty::CoercePointeeInfo::Duplicated { .. } => Err(tcx.dcx().span_delayed_bug(
998+
span,
999+
"a more specific error for malformed CoercePointee is expected",
1000+
)),
9581001
}
9591002
}
9601003

compiler/rustc_hir_analysis/src/errors.rs

+7
Original file line numberDiff line numberDiff line change
@@ -1247,6 +1247,13 @@ pub(crate) struct CoercePointeePointeeMultipleDerive {
12471247
pub spans: Vec<Span>,
12481248
}
12491249

1250+
#[derive(Diagnostic)]
1251+
#[diag(hir_analysis_coerce_pointee_missing_maybe_sized, code = E0802)]
1252+
pub(crate) struct CoercePointeePointeeMissingMaybeSized {
1253+
#[primary_span]
1254+
pub span: Span,
1255+
}
1256+
12501257
#[derive(Diagnostic)]
12511258
#[diag(hir_analysis_inherent_ty_outside_relevant, code = E0390)]
12521259
#[help]

0 commit comments

Comments
 (0)