about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAriel Ben-Yehuda <ariel.byd@gmail.com>2016-12-04 02:04:08 +0200
committerAriel Ben-Yehuda <ariel.byd@gmail.com>2017-01-03 21:50:18 +0200
commit243e45aac3fccf9403ad1bed162073f4f314b270 (patch)
treeafdef54647a35f536925171971399d58a43ae21a
parentd938ba47699a1539b00cbc59e6fc647010df340a (diff)
downloadrust-243e45aac3fccf9403ad1bed162073f4f314b270.tar.gz
rust-243e45aac3fccf9403ad1bed162073f4f314b270.zip
normalize field types in copy implementations
Fixes #34377.
-rw-r--r--src/librustc/ty/util.rs52
-rw-r--r--src/test/run-pass/issue-33187.rs27
2 files changed, 56 insertions, 23 deletions
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index 0b45ff94a93..34c07d442e3 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -147,34 +147,40 @@ impl<'tcx> ParameterEnvironment<'tcx> {
                                        self_type: Ty<'tcx>, span: Span)
                                        -> Result<(),CopyImplementationError> {
         // FIXME: (@jroesch) float this code up
-        tcx.infer_ctxt(None, Some(self.clone()), Reveal::ExactMatch).enter(|infcx| {
-            let adt = match self_type.sty {
-                ty::TyAdt(adt, substs) => match adt.adt_kind() {
-                    AdtKind::Struct | AdtKind::Union => {
-                        for field in adt.all_fields() {
-                            let field_ty = field.ty(tcx, substs);
-                            if infcx.type_moves_by_default(field_ty, span) {
-                                return Err(CopyImplementationError::InfrigingField(
-                                    field.name))
-                            }
+        tcx.infer_ctxt(None, Some(self.clone()), Reveal::NotSpecializable).enter(|infcx| {
+            let (adt, substs) = match self_type.sty {
+                ty::TyAdt(adt, substs) => (adt, substs),
+                _ => return Err(CopyImplementationError::NotAnAdt)
+            };
+
+            let field_implements_copy = |field: &ty::FieldDef| {
+                let cause = traits::ObligationCause::dummy();
+                match traits::fully_normalize(&infcx, cause, &field.ty(tcx, substs)) {
+                    Ok(ty) => !infcx.type_moves_by_default(ty, span),
+                    Err(..) => false
+                }
+            };
+
+            match adt.adt_kind() {
+                AdtKind::Struct | AdtKind::Union => {
+                    for field in adt.all_fields() {
+                        if !field_implements_copy(field) {
+                            return Err(CopyImplementationError::InfrigingField(
+                                field.name))
                         }
-                        adt
                     }
-                    AdtKind::Enum => {
-                        for variant in &adt.variants {
-                            for field in &variant.fields {
-                                let field_ty = field.ty(tcx, substs);
-                                if infcx.type_moves_by_default(field_ty, span) {
-                                    return Err(CopyImplementationError::InfrigingVariant(
-                                        variant.name))
-                                }
+                }
+                AdtKind::Enum => {
+                    for variant in &adt.variants {
+                        for field in &variant.fields {
+                            if !field_implements_copy(field) {
+                                return Err(CopyImplementationError::InfrigingVariant(
+                                    variant.name))
                             }
                         }
-                        adt
                     }
-                },
-                _ => return Err(CopyImplementationError::NotAnAdt)
-            };
+                }
+            }
 
             if adt.has_dtor() {
                 return Err(CopyImplementationError::HasDestructor);
diff --git a/src/test/run-pass/issue-33187.rs b/src/test/run-pass/issue-33187.rs
new file mode 100644
index 00000000000..477112ab3c5
--- /dev/null
+++ b/src/test/run-pass/issue-33187.rs
@@ -0,0 +1,27 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Foo<A: Repr>(<A as Repr>::Data);
+
+impl<A> Copy for Foo<A> where <A as Repr>::Data: Copy { }
+impl<A> Clone for Foo<A> where <A as Repr>::Data: Clone {
+    fn clone(&self) -> Self { Foo(self.0.clone()) }
+}
+
+trait Repr {
+    type Data;
+}
+
+impl<A> Repr for A {
+    type Data = u32;
+}
+
+fn main() {
+}