about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_lint/src/builtin.rs11
-rw-r--r--compiler/rustc_trait_selection/src/traits/misc.rs4
-rw-r--r--compiler/rustc_typeck/src/coherence/builtin.rs3
-rw-r--r--src/test/ui/issues/issue-50480.rs4
-rw-r--r--src/test/ui/issues/issue-50480.stderr30
-rw-r--r--src/test/ui/traits/copy-impl-cannot-normalize.rs25
-rw-r--r--src/test/ui/traits/copy-impl-cannot-normalize.stderr14
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs2
8 files changed, 71 insertions, 22 deletions
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 30b5f9b34d0..0a218c2d255 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -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 \
diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs
index b23dce8a581..dc72945af24 100644
--- a/compiler/rustc_trait_selection/src/traits/misc.rs
+++ b/compiler/rustc_trait_selection/src/traits/misc.rs
@@ -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,9 +50,8 @@ pub fn can_type_implement_copy<'tcx>(
                     continue;
                 }
                 let span = tcx.def_span(field.did);
-                let cause = ObligationCause::dummy_with_span(span);
                 let ctx = traits::FulfillmentContext::new();
-                match traits::fully_normalize(&infcx, ctx, cause, param_env, ty) {
+                match traits::fully_normalize(&infcx, ctx, cause.clone(), param_env, ty) {
                     Ok(ty) => {
                         if !infcx.type_is_copy_modulo_regions(param_env, ty, span) {
                             infringing.push(field);
diff --git a/compiler/rustc_typeck/src/coherence/builtin.rs b/compiler/rustc_typeck/src/coherence/builtin.rs
index 401ba188728..a43f7f87116 100644
--- a/compiler/rustc_typeck/src/coherence/builtin.rs
+++ b/compiler/rustc_typeck/src/coherence/builtin.rs
@@ -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);
diff --git a/src/test/ui/issues/issue-50480.rs b/src/test/ui/issues/issue-50480.rs
index 10597caf5b2..ca81db023ec 100644
--- a/src/test/ui/issues/issue-50480.rs
+++ b/src/test/ui/issues/issue-50480.rs
@@ -1,17 +1,17 @@
 #[derive(Clone, Copy)]
 //~^ ERROR the trait `Copy` may not be implemented for this type
+//~| ERROR `i32` is not an iterator
 struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
 //~^ ERROR cannot find type `NotDefined` in this scope
 //~| ERROR cannot find type `NotDefined` in this scope
 //~| ERROR cannot find type `N` in this scope
 //~| ERROR cannot find type `N` in this scope
-//~| ERROR `i32` is not an iterator
 
 #[derive(Clone, Copy)]
 //~^ ERROR the trait `Copy` may not be implemented for this type
+//~| ERROR `i32` is not an iterator
 struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
 //~^ ERROR cannot find type `NotDefined` in this scope
 //~| ERROR cannot find type `N` in this scope
-//~| ERROR `i32` is not an iterator
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-50480.stderr b/src/test/ui/issues/issue-50480.stderr
index 0bb1f9ae035..48ec4aa434c 100644
--- a/src/test/ui/issues/issue-50480.stderr
+++ b/src/test/ui/issues/issue-50480.stderr
@@ -1,5 +1,5 @@
 error[E0412]: cannot find type `N` in this scope
-  --> $DIR/issue-50480.rs:3:12
+  --> $DIR/issue-50480.rs:4:12
    |
 LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
    |           -^ not found in this scope
@@ -7,13 +7,13 @@ LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
    |           help: you might be missing a type parameter: `<N>`
 
 error[E0412]: cannot find type `NotDefined` in this scope
-  --> $DIR/issue-50480.rs:3:15
+  --> $DIR/issue-50480.rs:4:15
    |
 LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
    |               ^^^^^^^^^^ not found in this scope
 
 error[E0412]: cannot find type `N` in this scope
-  --> $DIR/issue-50480.rs:3:12
+  --> $DIR/issue-50480.rs:4:12
    |
 LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
    |           -^ not found in this scope
@@ -21,7 +21,7 @@ LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
    |           help: you might be missing a type parameter: `<N>`
 
 error[E0412]: cannot find type `NotDefined` in this scope
-  --> $DIR/issue-50480.rs:3:15
+  --> $DIR/issue-50480.rs:4:15
    |
 LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
    |           -   ^^^^^^^^^^ not found in this scope
@@ -29,7 +29,7 @@ LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
    |           help: you might be missing a type parameter: `<NotDefined>`
 
 error[E0412]: cannot find type `N` in this scope
-  --> $DIR/issue-50480.rs:12:18
+  --> $DIR/issue-50480.rs:13:18
    |
 LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
    |            -     ^
@@ -46,26 +46,27 @@ LL | struct Bar<T, N>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, Strin
    |             +++
 
 error[E0412]: cannot find type `NotDefined` in this scope
-  --> $DIR/issue-50480.rs:12:21
+  --> $DIR/issue-50480.rs:13:21
    |
 LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
    |                     ^^^^^^^^^^ not found in this scope
 
 error[E0277]: `i32` is not an iterator
-  --> $DIR/issue-50480.rs:3:27
+  --> $DIR/issue-50480.rs:1:17
    |
-LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
-   |                           ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator
+LL | #[derive(Clone, Copy)]
+   |                 ^^^^ `i32` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `i32`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+   = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0204]: the trait `Copy` may not be implemented for this type
   --> $DIR/issue-50480.rs:1:17
    |
 LL | #[derive(Clone, Copy)]
    |                 ^^^^
-LL |
+...
 LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
    |                                                    --------  ------ this field does not implement `Copy`
    |                                                    |
@@ -74,20 +75,21 @@ LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
    = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: `i32` is not an iterator
-  --> $DIR/issue-50480.rs:12:33
+  --> $DIR/issue-50480.rs:10:17
    |
-LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
-   |                                 ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator
+LL | #[derive(Clone, Copy)]
+   |                 ^^^^ `i32` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `i32`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+   = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0204]: the trait `Copy` may not be implemented for this type
   --> $DIR/issue-50480.rs:10:17
    |
 LL | #[derive(Clone, Copy)]
    |                 ^^^^
-LL |
+...
 LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
    |                                                          --------  ------ this field does not implement `Copy`
    |                                                          |
diff --git a/src/test/ui/traits/copy-impl-cannot-normalize.rs b/src/test/ui/traits/copy-impl-cannot-normalize.rs
new file mode 100644
index 00000000000..a78ff046e97
--- /dev/null
+++ b/src/test/ui/traits/copy-impl-cannot-normalize.rs
@@ -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() {}
diff --git a/src/test/ui/traits/copy-impl-cannot-normalize.stderr b/src/test/ui/traits/copy-impl-cannot-normalize.stderr
new file mode 100644
index 00000000000..cc540ea905a
--- /dev/null
+++ b/src/test/ui/traits/copy-impl-cannot-normalize.stderr
@@ -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`.
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
index ebd4fb0bf51..d27e1383d01 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
@@ -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`");
                                 }
                             }