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
<'tcx
>(
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
)
37 | ty
::Array(..) => return Ok(()),
39 ty
::Adt(adt
, substs
) => (adt
, substs
),
41 _
=> return Err(CopyImplementationError
::NotAnAdt
),
44 let mut infringing
= Vec
::new();
45 for variant
in &adt
.variants
{
46 for field
in &variant
.fields
{
47 let ty
= field
.ty(tcx
, substs
);
48 if ty
.references_error() {
51 let span
= tcx
.def_span(field
.did
);
52 let cause
= ObligationCause
::dummy_with_span(span
);
53 let ctx
= traits
::FulfillmentContext
::new();
54 match traits
::fully_normalize(&infcx
, ctx
, cause
, param_env
, ty
) {
56 if !infcx
.type_is_copy_modulo_regions(param_env
, ty
, span
) {
57 infringing
.push(field
);
61 infcx
.report_fulfillment_errors(&errors
, None
, false);
66 if !infringing
.is_empty() {
67 return Err(CopyImplementationError
::InfrigingFields(infringing
));
69 if adt
.has_dtor(tcx
) {
70 return Err(CopyImplementationError
::HasDestructor
);