Skip to content

Commit

Permalink
Rollup merge of #93714 - compiler-errors:can-type-impl-copy-error-spa…
Browse files Browse the repository at this point in the history
…n, 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
  • Loading branch information
Dylan-DPC committed Feb 24, 2022
2 parents 6ba167a + ee98dc8 commit 7f99536
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 5 deletions.
11 changes: 9 additions & 2 deletions compiler/rustc_lint/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down Expand Up @@ -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 \
Expand Down
15 changes: 14 additions & 1 deletion compiler/rustc_trait_selection/src/traits/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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| {
Expand Down Expand Up @@ -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) => {
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_typeck/src/coherence/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
25 changes: 25 additions & 0 deletions src/test/ui/traits/copy-impl-cannot-normalize.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 14 additions & 0 deletions src/test/ui/traits/copy-impl-cannot-normalize.stderr
Original file line number Diff line number Diff line change
@@ -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`.
Original file line number Diff line number Diff line change
Expand Up @@ -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`");
}
}
Expand Down

0 comments on commit 7f99536

Please sign in to comment.