]> git.lizzy.rs Git - rust.git/blobdiff - compiler/rustc_hir_analysis/src/coherence/builtin.rs
Rollup merge of #106946 - dtolnay:hashlinecolumn, r=m-ou-se
[rust.git] / compiler / rustc_hir_analysis / src / coherence / builtin.rs
index 55de68f83f28413c1522fb23c7a9ffef99f9c75b..76668f7e9ac4b0379a5ff9db80e6a20ebe42e003 100644 (file)
@@ -7,13 +7,15 @@
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::ItemKind;
-use rustc_infer::infer;
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::infer::TyCtxtInferExt;
+use rustc_infer::infer::{self, RegionResolutionError};
 use rustc_middle::ty::adjustment::CoerceUnsizedInfo;
 use rustc_middle::ty::{self, suggest_constraining_type_params, Ty, TyCtxt, TypeVisitable};
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
-use rustc_trait_selection::traits::misc::{can_type_implement_copy, CopyImplementationError};
+use rustc_trait_selection::traits::misc::{
+    type_allowed_to_implement_copy, CopyImplementationError, InfringingFieldsReason,
+};
 use rustc_trait_selection::traits::predicate_for_trait_def;
 use rustc_trait_selection::traits::{self, ObligationCause};
 use std::collections::BTreeMap;
@@ -62,8 +64,6 @@ fn visit_implementation_of_drop(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
 fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
     debug!("visit_implementation_of_copy: impl_did={:?}", impl_did);
 
-    let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_did);
-
     let self_type = tcx.type_of(impl_did);
     debug!("visit_implementation_of_copy: self_type={:?} (bound)", self_type);
 
@@ -78,8 +78,8 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
         _ => bug!("expected Copy impl item"),
     };
 
-    let cause = traits::ObligationCause::misc(span, impl_hir_id);
-    match can_type_implement_copy(tcx, param_env, self_type, cause) {
+    let cause = traits::ObligationCause::misc(span, impl_did);
+    match type_allowed_to_implement_copy(tcx, param_env, self_type, cause) {
         Ok(()) => {}
         Err(CopyImplementationError::InfrigingFields(fields)) => {
             let mut err = struct_span_err!(
@@ -94,50 +94,70 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
             let mut errors: BTreeMap<_, Vec<_>> = Default::default();
             let mut bounds = vec![];
 
-            for (field, ty) in fields {
+            for (field, ty, reason) in fields {
                 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,
-                };
                 err.span_label(field_span, "this field does not implement `Copy`");
-                // Spin up a new FulfillmentContext, so we can get the _precise_ reason
-                // why this field does not implement Copy. This is useful because sometimes
-                // it is not immediately clear why Copy is not implemented for a field, since
-                // all we point at is the field itself.
-                let infcx = tcx.infer_ctxt().ignoring_regions().build();
-                for error in traits::fully_solve_bound(
-                    &infcx,
-                    traits::ObligationCause::dummy_with_span(field_ty_span),
-                    param_env,
-                    ty,
-                    tcx.require_lang_item(LangItem::Copy, Some(span)),
-                ) {
-                    let error_predicate = error.obligation.predicate;
-                    // Only note if it's not the root obligation, otherwise it's trivial and
-                    // should be self-explanatory (i.e. a field literally doesn't implement Copy).
-
-                    // FIXME: This error could be more descriptive, especially if the error_predicate
-                    // contains a foreign type or if it's a deeply nested type...
-                    if error_predicate != error.root_obligation.predicate {
-                        errors
-                            .entry((ty.to_string(), error_predicate.to_string()))
-                            .or_default()
-                            .push(error.obligation.cause.span);
+
+                match reason {
+                    InfringingFieldsReason::Fulfill(fulfillment_errors) => {
+                        for error in fulfillment_errors {
+                            let error_predicate = error.obligation.predicate;
+                            // Only note if it's not the root obligation, otherwise it's trivial and
+                            // should be self-explanatory (i.e. a field literally doesn't implement Copy).
+
+                            // FIXME: This error could be more descriptive, especially if the error_predicate
+                            // contains a foreign type or if it's a deeply nested type...
+                            if error_predicate != error.root_obligation.predicate {
+                                errors
+                                    .entry((ty.to_string(), error_predicate.to_string()))
+                                    .or_default()
+                                    .push(error.obligation.cause.span);
+                            }
+                            if let ty::PredicateKind::Clause(ty::Clause::Trait(
+                                ty::TraitPredicate {
+                                    trait_ref,
+                                    polarity: ty::ImplPolarity::Positive,
+                                    ..
+                                },
+                            )) = error_predicate.kind().skip_binder()
+                            {
+                                let ty = trait_ref.self_ty();
+                                if let ty::Param(_) = ty.kind() {
+                                    bounds.push((
+                                        format!("{ty}"),
+                                        trait_ref.print_only_trait_path().to_string(),
+                                        Some(trait_ref.def_id),
+                                    ));
+                                }
+                            }
+                        }
                     }
-                    if let ty::PredicateKind::Clause(ty::Clause::Trait(ty::TraitPredicate {
-                        trait_ref,
-                        polarity: ty::ImplPolarity::Positive,
-                        ..
-                    })) = error_predicate.kind().skip_binder()
-                    {
-                        let ty = trait_ref.self_ty();
-                        if let ty::Param(_) = ty.kind() {
-                            bounds.push((
-                                format!("{ty}"),
-                                trait_ref.print_only_trait_path().to_string(),
-                                Some(trait_ref.def_id),
-                            ));
+                    InfringingFieldsReason::Regions(region_errors) => {
+                        for error in region_errors {
+                            let ty = ty.to_string();
+                            match error {
+                                RegionResolutionError::ConcreteFailure(origin, a, b) => {
+                                    let predicate = format!("{b}: {a}");
+                                    errors
+                                        .entry((ty.clone(), predicate.clone()))
+                                        .or_default()
+                                        .push(origin.span());
+                                    if let ty::RegionKind::ReEarlyBound(ebr) = *b && ebr.has_name() {
+                                        bounds.push((b.to_string(), a.to_string(), None));
+                                    }
+                                }
+                                RegionResolutionError::GenericBoundFailure(origin, a, b) => {
+                                    let predicate = format!("{a}: {b}");
+                                    errors
+                                        .entry((ty.clone(), predicate.clone()))
+                                        .or_default()
+                                        .push(origin.span());
+                                    if let infer::region_constraints::GenericKind::Param(_) = a {
+                                        bounds.push((a.to_string(), b.to_string(), None));
+                                    }
+                                }
+                                _ => continue,
+                            }
                         }
                     }
                 }
@@ -202,7 +222,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
     let create_err = |msg: &str| struct_span_err!(tcx.sess, span, E0378, "{}", msg);
 
     let infcx = tcx.infer_ctxt().build();
-    let cause = ObligationCause::misc(span, impl_hir_id);
+    let cause = ObligationCause::misc(span, impl_did);
 
     use rustc_type_ir::sty::TyKind::*;
     match (source.kind(), target.kind()) {
@@ -364,8 +384,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
     debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (free)", source, target);
 
     let infcx = tcx.infer_ctxt().build();
-    let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_did);
-    let cause = ObligationCause::misc(span, impl_hir_id);
+    let cause = ObligationCause::misc(span, impl_did);
     let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>,
                        mt_b: ty::TypeAndMut<'tcx>,
                        mk_ptr: &dyn Fn(Ty<'tcx>) -> Ty<'tcx>| {
@@ -553,7 +572,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
     };
 
     // Register an obligation for `A: Trait<B>`.
-    let cause = traits::ObligationCause::misc(span, impl_hir_id);
+    let cause = traits::ObligationCause::misc(span, impl_did);
     let predicate =
         predicate_for_trait_def(tcx, param_env, cause, trait_def_id, 0, [source, target]);
     let errors = traits::fully_solve_obligation(&infcx, predicate);