1 //! Miscellaneous type-system utilities that are too small to deserve their own modules.
3 use crate::traits::{self, ObligationCause};
4 use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
9 pub enum CopyImplementationError<'tcx> {
10 InfrigingFields(Vec<&'tcx ty::FieldDef>),
15 pub fn can_type_implement_copy(
17 param_env: ty::ParamEnv<'tcx>,
19 ) -> Result<(), CopyImplementationError<'tcx>> {
20 // FIXME: (@jroesch) float this code up
21 tcx.infer_ctxt().enter(|infcx| {
22 let (adt, substs) = match self_type.kind {
23 // These types used to have a builtin impl.
24 // Now libcore provides that impl.
32 | ty::Ref(_, _, hir::Mutability::Not) => return Ok(()),
34 ty::Adt(adt, substs) => (adt, substs),
36 _ => return Err(CopyImplementationError::NotAnAdt),
39 let mut infringing = Vec::new();
40 for variant in &adt.variants {
41 for field in &variant.fields {
42 let ty = field.ty(tcx, substs);
43 if ty.references_error() {
46 let span = tcx.def_span(field.did);
47 let cause = ObligationCause { span, ..ObligationCause::dummy() };
48 let ctx = traits::FulfillmentContext::new();
49 match traits::fully_normalize(&infcx, ctx, cause, param_env, &ty) {
51 if !infcx.type_is_copy_modulo_regions(param_env, ty, span) {
52 infringing.push(field);
56 infcx.report_fulfillment_errors(&errors, None, false);
61 if !infringing.is_empty() {
62 return Err(CopyImplementationError::InfrigingFields(infringing));
64 if adt.has_dtor(tcx) {
65 return Err(CopyImplementationError::HasDestructor);