about summary refs log tree commit diff
path: root/compiler/rustc_trait_selection/src
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2022-12-09 20:59:26 +0000
committerMichael Goulet <michael@errs.io>2023-01-13 23:06:29 +0000
commit16cfadbfe835cadd24dc65481ab3ad0b5b627c5a (patch)
tree5cc4dd2a65bc23a95e5049239a9cc756494efa95 /compiler/rustc_trait_selection/src
parent333c6bf523019fd1565a5236d3c727172ec844f2 (diff)
downloadrust-16cfadbfe835cadd24dc65481ab3ad0b5b627c5a.tar.gz
rust-16cfadbfe835cadd24dc65481ab3ad0b5b627c5a.zip
Suggest lifetime bound in illegal Copy impl
Diffstat (limited to 'compiler/rustc_trait_selection/src')
-rw-r--r--compiler/rustc_trait_selection/src/traits/misc.rs44
1 files changed, 30 insertions, 14 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs
index 46eea628a34..0de44dba0dd 100644
--- a/compiler/rustc_trait_selection/src/traits/misc.rs
+++ b/compiler/rustc_trait_selection/src/traits/misc.rs
@@ -4,21 +4,25 @@ use crate::traits::{self, ObligationCause};
 
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir as hir;
-use rustc_infer::infer::outlives::env::OutlivesEnvironment;
-use rustc_infer::infer::TyCtxtInferExt;
+use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
+use rustc_infer::{infer::outlives::env::OutlivesEnvironment, traits::FulfillmentError};
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable};
 
 use crate::traits::error_reporting::TypeErrCtxtExt;
 
 use super::outlives_bounds::InferCtxtExt;
 
-#[derive(Clone)]
 pub enum CopyImplementationError<'tcx> {
-    InfrigingFields(Vec<(&'tcx ty::FieldDef, Ty<'tcx>)>),
+    InfrigingFields(Vec<(&'tcx ty::FieldDef, Ty<'tcx>, InfringingFieldsReason<'tcx>)>),
     NotAnAdt,
     HasDestructor,
 }
 
+pub enum InfringingFieldsReason<'tcx> {
+    Fulfill(Vec<FulfillmentError<'tcx>>),
+    Regions(Vec<RegionResolutionError<'tcx>>),
+}
+
 /// Checks that the fields of the type (an ADT) all implement copy.
 ///
 /// If fields don't implement copy, return an error containing a list of
@@ -60,22 +64,27 @@ pub fn type_allowed_to_implement_copy<'tcx>(
             if ty.references_error() {
                 continue;
             }
-            let span = tcx.def_span(field.did);
+
+            let field_span = tcx.def_span(field.did);
+            let field_ty_span = match tcx.hir().get_if_local(field.did) {
+                Some(hir::Node::Field(field_def)) => field_def.ty.span,
+                _ => field_span,
+            };
+
             // FIXME(compiler-errors): This gives us better spans for bad
             // projection types like in issue-50480.
             // If the ADT has substs, point to the cause we are given.
             // If it does not, then this field probably doesn't normalize
             // to begin with, and point to the bad field's span instead.
-            let cause = if field
+            let normalization_cause = if field
                 .ty(tcx, traits::InternalSubsts::identity_for_item(tcx, adt.did()))
                 .has_non_region_param()
             {
                 parent_cause.clone()
             } else {
-                ObligationCause::dummy_with_span(span)
+                ObligationCause::dummy_with_span(field_ty_span)
             };
-
-            let ty = ocx.normalize(&cause, param_env, ty);
+            let ty = ocx.normalize(&normalization_cause, param_env, ty);
             let normalization_errors = ocx.select_where_possible();
             if !normalization_errors.is_empty() {
                 // Don't report this as a field that doesn't implement Copy,
@@ -84,9 +93,15 @@ pub fn type_allowed_to_implement_copy<'tcx>(
                 continue;
             }
 
-            ocx.register_bound(cause, param_env, ty, copy_def_id);
-            if !ocx.select_all_or_error().is_empty() {
-                infringing.push((field, ty));
+            ocx.register_bound(
+                ObligationCause::dummy_with_span(field_ty_span),
+                param_env,
+                ty,
+                copy_def_id,
+            );
+            let errors = ocx.select_all_or_error();
+            if !errors.is_empty() {
+                infringing.push((field, ty, InfringingFieldsReason::Fulfill(errors)));
             }
 
             // Check regions assuming the self type of the impl is WF
@@ -103,8 +118,9 @@ pub fn type_allowed_to_implement_copy<'tcx>(
                 outlives_env.region_bound_pairs(),
                 param_env,
             );
-            if !infcx.resolve_regions(&outlives_env).is_empty() {
-                infringing.push((field, ty));
+            let errors = infcx.resolve_regions(&outlives_env);
+            if !errors.is_empty() {
+                infringing.push((field, ty, InfringingFieldsReason::Regions(errors)));
             }
         }
     }