1 //! Miscellaneous type-system utilities that are too small to deserve their own modules.
3 use crate::infer
::InferCtxtExt
as _
;
4 use crate::traits
::{self, ObligationCause}
;
7 use rustc_infer
::infer
::TyCtxtInferExt
;
8 use rustc_middle
::ty
::{self, Ty, TyCtxt, TypeFoldable}
;
10 use crate::traits
::error_reporting
::InferCtxtExt
;
13 pub enum CopyImplementationError
<'tcx
> {
14 InfrigingFields(Vec
<&'tcx ty
::FieldDef
>),
19 pub fn can_type_implement_copy(
21 param_env
: ty
::ParamEnv
<'tcx
>,
23 ) -> Result
<(), CopyImplementationError
<'tcx
>> {
24 // FIXME: (@jroesch) float this code up
25 tcx
.infer_ctxt().enter(|infcx
| {
26 let (adt
, substs
) = match self_type
.kind
{
27 // These types used to have a builtin impl.
28 // Now libcore provides that impl.
36 | ty
::Ref(_
, _
, hir
::Mutability
::Not
) => return Ok(()),
38 ty
::Adt(adt
, substs
) => (adt
, substs
),
40 _
=> return Err(CopyImplementationError
::NotAnAdt
),
43 let mut infringing
= Vec
::new();
44 for variant
in &adt
.variants
{
45 for field
in &variant
.fields
{
46 let ty
= field
.ty(tcx
, substs
);
47 if ty
.references_error() {
50 let span
= tcx
.def_span(field
.did
);
51 let cause
= ObligationCause
::dummy_with_span(span
);
52 let ctx
= traits
::FulfillmentContext
::new();
53 match traits
::fully_normalize(&infcx
, ctx
, cause
, param_env
, &ty
) {
55 if !infcx
.type_is_copy_modulo_regions(param_env
, ty
, span
) {
56 infringing
.push(field
);
60 infcx
.report_fulfillment_errors(&errors
, None
, false);
65 if !infringing
.is_empty() {
66 return Err(CopyImplementationError
::InfrigingFields(infringing
));
68 if adt
.has_dtor(tcx
) {
69 return Err(CopyImplementationError
::HasDestructor
);