Auto merge of #105102 - compiler-errors:copy-impl-considering-regions, r=lcnr
Check ADT fields for copy implementations considering regions Fixes #88901 r? `@ghost`
This commit is contained in:
commit
94a300b9b8
10 changed files with 217 additions and 101 deletions
|
@ -7,13 +7,15 @@ use rustc_hir as hir;
|
|||
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;
|
||||
|
@ -79,7 +81,7 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
|
|||
};
|
||||
|
||||
let cause = traits::ObligationCause::misc(span, impl_hir_id);
|
||||
match can_type_implement_copy(tcx, param_env, self_type, cause) {
|
||||
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 +96,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,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue