]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_trait_selection/src/traits/misc.rs
New upstream version 1.66.0+dfsg1
[rustc.git] / compiler / rustc_trait_selection / src / 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 7use rustc_infer::infer::TyCtxtInferExt;
064997fb 8use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable};
ba9703b0 9
2b03887a 10use crate::traits::error_reporting::TypeErrCtxtExt;
74b04a01
XL
11
12#[derive(Clone)]
13pub enum CopyImplementationError<'tcx> {
5e7ed085 14 InfrigingFields(Vec<(&'tcx ty::FieldDef, Ty<'tcx>)>),
74b04a01
XL
15 NotAnAdt,
16 HasDestructor,
17}
18
a2a8927a 19pub fn can_type_implement_copy<'tcx>(
74b04a01
XL
20 tcx: TyCtxt<'tcx>,
21 param_env: ty::ParamEnv<'tcx>,
22 self_type: Ty<'tcx>,
923072b8 23 parent_cause: ObligationCause<'tcx>,
74b04a01
XL
24) -> Result<(), CopyImplementationError<'tcx>> {
25 // FIXME: (@jroesch) float this code up
2b03887a
FG
26 let infcx = tcx.infer_ctxt().build();
27 let (adt, substs) = match self_type.kind() {
28 // These types used to have a builtin impl.
29 // Now libcore provides that impl.
30 ty::Uint(_)
31 | ty::Int(_)
32 | ty::Bool
33 | ty::Float(_)
34 | ty::Char
35 | ty::RawPtr(..)
36 | ty::Never
37 | ty::Ref(_, _, hir::Mutability::Not)
38 | ty::Array(..) => return Ok(()),
74b04a01 39
2b03887a 40 ty::Adt(adt, substs) => (adt, substs),
74b04a01 41
2b03887a
FG
42 _ => return Err(CopyImplementationError::NotAnAdt),
43 };
74b04a01 44
2b03887a
FG
45 let mut infringing = Vec::new();
46 for variant in adt.variants() {
47 for field in &variant.fields {
48 let ty = field.ty(tcx, substs);
49 if ty.references_error() {
50 continue;
74b04a01 51 }
2b03887a
FG
52 let span = tcx.def_span(field.did);
53 // FIXME(compiler-errors): This gives us better spans for bad
54 // projection types like in issue-50480.
55 // If the ADT has substs, point to the cause we are given.
56 // If it does not, then this field probably doesn't normalize
57 // to begin with, and point to the bad field's span instead.
58 let cause = if field
59 .ty(tcx, traits::InternalSubsts::identity_for_item(tcx, adt.did()))
60 .has_non_region_param()
61 {
62 parent_cause.clone()
63 } else {
64 ObligationCause::dummy_with_span(span)
65 };
66 match traits::fully_normalize(&infcx, cause, param_env, ty) {
67 Ok(ty) => {
68 if !infcx.type_is_copy_modulo_regions(param_env, ty, span) {
69 infringing.push((field, ty));
70 }
71 }
72 Err(errors) => {
73 infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
74 }
75 };
74b04a01 76 }
2b03887a
FG
77 }
78 if !infringing.is_empty() {
79 return Err(CopyImplementationError::InfrigingFields(infringing));
80 }
81 if adt.has_dtor(tcx) {
82 return Err(CopyImplementationError::HasDestructor);
83 }
74b04a01 84
2b03887a 85 Ok(())
74b04a01 86}