Rollup merge of #136107 - dingxiangfei2009:coerce-pointee-wellformed, r=compiler-errors
Introduce CoercePointeeWellformed for coherence checks at typeck stage Fix #135206 This is the first PR to introduce the "wellformedness" check for `derive(CoercePointee)`. This patch introduces a new error code to cover all the prerequisites of the said macro. The checks that is enforced with this patch is whether the data is indeed `struct` and whether the layout is set to `repr(transparent)`. A following series of patch will arrive later to address the following concern. 1. #135217 so that we would only admit one single coercion on one type parameter, and leave the rest for future consideration in tandem of development of other coercion rules. 1. Enforcement of data field requirements. **An open question** is whether there is a good schema to encode the `#[pointee]` as well, so that we could also check if the `#[pointee]` type parameter is indeed `?Sized`. ``@rustbot`` label F-derive_coerce_pointee
This commit is contained in:
commit
af3c51d849
15 changed files with 385 additions and 54 deletions
|
@ -85,6 +85,16 @@ hir_analysis_cmse_output_stack_spill =
|
|||
.note1 = functions with the `"{$abi_name}"` ABI must pass their result via the available return registers
|
||||
.note2 = the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
|
||||
|
||||
hir_analysis_coerce_pointee_no_field = `CoercePointee` can only be derived on `struct`s with at least one field
|
||||
|
||||
hir_analysis_coerce_pointee_no_user_validity_assertion = asserting applicability of `derive(CoercePointee)` on a target data is forbidden
|
||||
|
||||
hir_analysis_coerce_pointee_not_concrete_ty = `derive(CoercePointee)` is only applicable to `struct`
|
||||
|
||||
hir_analysis_coerce_pointee_not_struct = `derive(CoercePointee)` is only applicable to `struct`, instead of `{$kind}`
|
||||
|
||||
hir_analysis_coerce_pointee_not_transparent = `derive(CoercePointee)` is only applicable to `struct` with `repr(transparent)` layout
|
||||
|
||||
hir_analysis_coerce_unsized_may = the trait `{$trait_name}` may only be implemented for a coercion between structures
|
||||
|
||||
hir_analysis_coerce_unsized_multi = implementing the trait `CoerceUnsized` requires multiple coercions
|
||||
|
|
|
@ -48,6 +48,10 @@ pub(super) fn check_trait<'tcx>(
|
|||
checker
|
||||
.check(lang_items.dispatch_from_dyn_trait(), visit_implementation_of_dispatch_from_dyn)?;
|
||||
checker.check(lang_items.pointer_like(), visit_implementation_of_pointer_like)?;
|
||||
checker.check(
|
||||
lang_items.coerce_pointee_validated_trait(),
|
||||
visit_implementation_of_coerce_pointee_validity,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -783,3 +787,32 @@ fn visit_implementation_of_pointer_like(checker: &Checker<'_>) -> Result<(), Err
|
|||
.with_note(why_disqualified)
|
||||
.emit())
|
||||
}
|
||||
|
||||
fn visit_implementation_of_coerce_pointee_validity(
|
||||
checker: &Checker<'_>,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let tcx = checker.tcx;
|
||||
let self_ty = tcx.impl_trait_ref(checker.impl_def_id).unwrap().instantiate_identity().self_ty();
|
||||
let span = tcx.def_span(checker.impl_def_id);
|
||||
if !tcx.is_builtin_derived(checker.impl_def_id.into()) {
|
||||
return Err(tcx.dcx().emit_err(errors::CoercePointeeNoUserValidityAssertion { span }));
|
||||
}
|
||||
let ty::Adt(def, _args) = self_ty.kind() else {
|
||||
return Err(tcx.dcx().emit_err(errors::CoercePointeeNotConcreteType { span }));
|
||||
};
|
||||
let did = def.did();
|
||||
// Now get a more precise span of the `struct`.
|
||||
let span = tcx.def_span(did);
|
||||
if !def.is_struct() {
|
||||
return Err(tcx
|
||||
.dcx()
|
||||
.emit_err(errors::CoercePointeeNotStruct { span, kind: def.descr().into() }));
|
||||
}
|
||||
if !def.repr().transparent() {
|
||||
return Err(tcx.dcx().emit_err(errors::CoercePointeeNotTransparent { span }));
|
||||
}
|
||||
if def.all_fields().next().is_none() {
|
||||
return Err(tcx.dcx().emit_err(errors::CoercePointeeNoField { span }));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1180,6 +1180,42 @@ pub(crate) struct DispatchFromDynRepr {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_coerce_pointee_not_struct, code = E0802)]
|
||||
pub(crate) struct CoercePointeeNotStruct {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub kind: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_coerce_pointee_not_concrete_ty, code = E0802)]
|
||||
pub(crate) struct CoercePointeeNotConcreteType {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_coerce_pointee_no_user_validity_assertion, code = E0802)]
|
||||
pub(crate) struct CoercePointeeNoUserValidityAssertion {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_coerce_pointee_not_transparent, code = E0802)]
|
||||
pub(crate) struct CoercePointeeNotTransparent {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_coerce_pointee_no_field, code = E0802)]
|
||||
pub(crate) struct CoercePointeeNoField {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_inherent_ty_outside_relevant, code = E0390)]
|
||||
#[help]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue