Rollup merge of #93714 - compiler-errors:can-type-impl-copy-error-span, r=jackh726
better ObligationCause for normalization errors in `can_type_implement_copy` Some logic is needed so we can point to the field when given totally nonsense types like `struct Foo(<u32 as Iterator>::Item);` Fixes #93687
This commit is contained in:
commit
7f99536915
@ -51,7 +51,7 @@ use rustc_span::source_map::Spanned;
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::{BytePos, InnerSpan, MultiSpan, Span};
|
||||
use rustc_target::abi::VariantIdx;
|
||||
use rustc_trait_selection::traits::misc::can_type_implement_copy;
|
||||
use rustc_trait_selection::traits::{self, misc::can_type_implement_copy};
|
||||
|
||||
use crate::nonstandard_style::{method_context, MethodLateContext};
|
||||
|
||||
@ -764,7 +764,14 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
|
||||
if ty.is_copy_modulo_regions(cx.tcx.at(item.span), param_env) {
|
||||
return;
|
||||
}
|
||||
if can_type_implement_copy(cx.tcx, param_env, ty).is_ok() {
|
||||
if can_type_implement_copy(
|
||||
cx.tcx,
|
||||
param_env,
|
||||
ty,
|
||||
traits::ObligationCause::misc(item.span, item.hir_id()),
|
||||
)
|
||||
.is_ok()
|
||||
{
|
||||
cx.struct_span_lint(MISSING_COPY_IMPLEMENTATIONS, item.span, |lint| {
|
||||
lint.build(
|
||||
"type could implement `Copy`; consider adding `impl \
|
||||
|
@ -20,6 +20,7 @@ pub fn can_type_implement_copy<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
self_type: Ty<'tcx>,
|
||||
cause: ObligationCause<'tcx>,
|
||||
) -> Result<(), CopyImplementationError<'tcx>> {
|
||||
// FIXME: (@jroesch) float this code up
|
||||
tcx.infer_ctxt().enter(|infcx| {
|
||||
@ -49,7 +50,19 @@ pub fn can_type_implement_copy<'tcx>(
|
||||
continue;
|
||||
}
|
||||
let span = tcx.def_span(field.did);
|
||||
let cause = ObligationCause::dummy_with_span(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
|
||||
.ty(tcx, traits::InternalSubsts::identity_for_item(tcx, adt.did))
|
||||
.has_param_types_or_consts()
|
||||
{
|
||||
cause.clone()
|
||||
} else {
|
||||
ObligationCause::dummy_with_span(span)
|
||||
};
|
||||
let ctx = traits::FulfillmentContext::new();
|
||||
match traits::fully_normalize(&infcx, ctx, cause, param_env, ty) {
|
||||
Ok(ty) => {
|
||||
|
@ -74,7 +74,8 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
|
||||
|
||||
debug!("visit_implementation_of_copy: self_type={:?} (free)", self_type);
|
||||
|
||||
match can_type_implement_copy(tcx, param_env, self_type) {
|
||||
let cause = traits::ObligationCause::misc(span, impl_hir_id);
|
||||
match can_type_implement_copy(tcx, param_env, self_type, cause) {
|
||||
Ok(()) => {}
|
||||
Err(CopyImplementationError::InfrigingFields(fields)) => {
|
||||
let item = tcx.hir().expect_item(impl_did);
|
||||
|
25
src/test/ui/traits/copy-impl-cannot-normalize.rs
Normal file
25
src/test/ui/traits/copy-impl-cannot-normalize.rs
Normal file
@ -0,0 +1,25 @@
|
||||
trait TraitFoo {
|
||||
type Bar;
|
||||
}
|
||||
|
||||
struct Foo<T>
|
||||
where
|
||||
T: TraitFoo,
|
||||
{
|
||||
inner: T::Bar,
|
||||
}
|
||||
|
||||
impl<T> Clone for Foo<T>
|
||||
where
|
||||
T: TraitFoo,
|
||||
T::Bar: Clone,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
Self { inner: self.inner.clone() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Copy for Foo<T> {}
|
||||
//~^ ERROR the trait bound `T: TraitFoo` is not satisfied
|
||||
|
||||
fn main() {}
|
14
src/test/ui/traits/copy-impl-cannot-normalize.stderr
Normal file
14
src/test/ui/traits/copy-impl-cannot-normalize.stderr
Normal file
@ -0,0 +1,14 @@
|
||||
error[E0277]: the trait bound `T: TraitFoo` is not satisfied
|
||||
--> $DIR/copy-impl-cannot-normalize.rs:22:1
|
||||
|
|
||||
LL | impl<T> Copy for Foo<T> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TraitFoo` is not implemented for `T`
|
||||
|
|
||||
help: consider restricting type parameter `T`
|
||||
|
|
||||
LL | impl<T: TraitFoo> Copy for Foo<T> {}
|
||||
| ++++++++++
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -199,7 +199,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
|
||||
let sugg = |diag: &mut DiagnosticBuilder<'_>| {
|
||||
if let ty::Adt(def, ..) = ty.kind() {
|
||||
if let Some(span) = cx.tcx.hir().span_if_local(def.did) {
|
||||
if can_type_implement_copy(cx.tcx, cx.param_env, ty).is_ok() {
|
||||
if can_type_implement_copy(cx.tcx, cx.param_env, ty, traits::ObligationCause::dummy_with_span(span)).is_ok() {
|
||||
diag.span_help(span, "consider marking this type as `Copy`");
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user