]> git.lizzy.rs Git - rust.git/blob - src/librustc_trait_selection/traits/misc.rs
Rollup merge of #70038 - DutchGhost:const-forget-tests, r=RalfJung
[rust.git] / src / librustc_trait_selection / traits / misc.rs
1 //! Miscellaneous type-system utilities that are too small to deserve their own modules.
2
3 use crate::infer::InferCtxtExt as _;
4 use crate::traits::{self, ObligationCause};
5
6 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
7 use rustc_hir as hir;
8 use rustc_infer::infer::TyCtxtInferExt;
9
10 use crate::traits::error_reporting::InferCtxtExt;
11
12 #[derive(Clone)]
13 pub enum CopyImplementationError<'tcx> {
14     InfrigingFields(Vec<&'tcx ty::FieldDef>),
15     NotAnAdt,
16     HasDestructor,
17 }
18
19 pub fn can_type_implement_copy(
20     tcx: TyCtxt<'tcx>,
21     param_env: ty::ParamEnv<'tcx>,
22     self_type: Ty<'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.
29             ty::Uint(_)
30             | ty::Int(_)
31             | ty::Bool
32             | ty::Float(_)
33             | ty::Char
34             | ty::RawPtr(..)
35             | ty::Never
36             | ty::Ref(_, _, hir::Mutability::Not) => return Ok(()),
37
38             ty::Adt(adt, substs) => (adt, substs),
39
40             _ => return Err(CopyImplementationError::NotAnAdt),
41         };
42
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() {
48                     continue;
49                 }
50                 let span = tcx.def_span(field.did);
51                 let cause = ObligationCause { span, ..ObligationCause::dummy() };
52                 let ctx = traits::FulfillmentContext::new();
53                 match traits::fully_normalize(&infcx, ctx, cause, param_env, &ty) {
54                     Ok(ty) => {
55                         if !infcx.type_is_copy_modulo_regions(param_env, ty, span) {
56                             infringing.push(field);
57                         }
58                     }
59                     Err(errors) => {
60                         infcx.report_fulfillment_errors(&errors, None, false);
61                     }
62                 };
63             }
64         }
65         if !infringing.is_empty() {
66             return Err(CopyImplementationError::InfrigingFields(infringing));
67         }
68         if adt.has_dtor(tcx) {
69             return Err(CopyImplementationError::HasDestructor);
70         }
71
72         Ok(())
73     })
74 }