]> git.proxmox.com Git - rustc.git/blame - src/librustc_trait_selection/traits/misc.rs
New upstream version 1.47.0+dfsg1
[rustc.git] / src / librustc_trait_selection / traits / misc.rs
CommitLineData
74b04a01
XL
1//! Miscellaneous type-system utilities that are too small to deserve their own modules.
2
ba9703b0 3use crate::infer::InferCtxtExt as _;
74b04a01
XL
4use crate::traits::{self, ObligationCause};
5
74b04a01 6use rustc_hir as hir;
ba9703b0
XL
7use rustc_infer::infer::TyCtxtInferExt;
8use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
9
10use crate::traits::error_reporting::InferCtxtExt;
74b04a01
XL
11
12#[derive(Clone)]
13pub enum CopyImplementationError<'tcx> {
14 InfrigingFields(Vec<&'tcx ty::FieldDef>),
15 NotAnAdt,
16 HasDestructor,
17}
18
19pub 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);
f035d41b 51 let cause = ObligationCause::dummy_with_span(span);
74b04a01
XL
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}