about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJared Roesch <roeschinc@gmail.com>2016-08-18 11:29:35 -0700
committerJared Roesch <roeschinc@gmail.com>2016-09-02 11:58:02 -0700
commit90d1a535510dfa098c908a76234d7b0db72eadf8 (patch)
tree5893ae4ebbfe8d95541bbc2575424223f1cd430c
parent352fac95ad5305bf8b0e482b8255b2b0057adf09 (diff)
downloadrust-90d1a535510dfa098c908a76234d7b0db72eadf8.tar.gz
rust-90d1a535510dfa098c908a76234d7b0db72eadf8.zip
Address feedback, and remove invalid tests
-rw-r--r--src/librustc/ty/mod.rs10
-rw-r--r--src/librustc_typeck/check/wfcheck.rs95
-rw-r--r--src/test/compile-fail/traits-inductive-overflow-auto-normal-auto.rs32
-rw-r--r--src/test/compile-fail/traits-inductive-overflow-supertrait-oibit.rs4
-rw-r--r--src/test/compile-fail/typeck-auto-trait-no-supertraits-2.rs (renamed from src/test/compile-fail/issue-29859.rs)2
-rw-r--r--src/test/compile-fail/typeck-auto-trait-no-supertraits.rs49
-rw-r--r--src/test/compile-fail/typeck-auto-trait-no-typeparams.rs (renamed from src/test/compile-fail/issue-29859-2.rs)2
-rw-r--r--src/test/compile-fail/typeck-default-trait-impl-superregion.rs27
-rw-r--r--src/test/compile-fail/typeck-default-trait-impl-supertrait.rs29
-rw-r--r--src/test/compile-fail/typeck-default-trait-impl-trait-where-clause-2.rs36
-rw-r--r--src/test/compile-fail/typeck-default-trait-impl-trait-where-clause.rs36
11 files changed, 108 insertions, 214 deletions
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 414e7b71f7c..e9c01f5bad6 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -762,16 +762,6 @@ pub struct GenericPredicates<'tcx> {
 }
 
 impl<'a, 'gcx, 'tcx> GenericPredicates<'tcx> {
-    pub fn empty() -> GenericPredicates<'tcx> {
-        GenericPredicates {
-            predicates: VecPerParamSpace::empty(),
-        }
-    }
-
-    pub fn is_empty(&self) -> bool {
-        self.predicates.is_empty()
-    }
-
     pub fn instantiate(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: &Substs<'tcx>)
                        -> InstantiatedPredicates<'tcx> {
         let mut instantiated = InstantiatedPredicates::empty();
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 0117dfa6730..4576fc9ffdc 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -252,33 +252,71 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
     }
 
     fn check_auto_trait(&mut self,
-                                   trait_def_id: DefId,
-                                   span: Span)
+                        trait_def_id: DefId,
+                        items: &[hir::TraitItem],
+                        span: Span)
     {
+        // We want to ensure:
+        //
+        // 1) that there are no items contained within
+        // the trait defintion
+        //
+        // 2) that the definition doesn't violate the no-super trait rule
+        // for auto traits.
+        //
+        // 3) that the trait definition does not have any type parameters
+
         let predicates = self.tcx().lookup_predicates(trait_def_id);
 
-        // If we must exclude the Self : Trait predicate contained by all
+        // We must exclude the Self : Trait predicate contained by all
         // traits.
-        let no_refl_predicates : Vec<_> =
-            predicates.predicates.iter().filter(|predicate| {
-                match *predicate {
-                    &ty::Predicate::Trait(ref poly_trait_ref) =>
-                        poly_trait_ref.def_id() != trait_def_id,
+        let has_predicates =
+            predicates.predicates.iter().any(|predicate| {
+                match predicate {
+                    &ty::Predicate::Trait(ref poly_trait_ref) => {
+                        let self_ty = poly_trait_ref.0.self_ty();
+                        !(self_ty.is_self() && poly_trait_ref.def_id() == trait_def_id)
+                    },
                     _ => true,
-            }
-            }).collect();
+                }
+            });
 
         let trait_def = self.tcx().lookup_trait_def(trait_def_id);
 
+        let has_ty_params =
+            trait_def.generics
+                      .types
+                      .len() > 1;
+
         // We use an if-else here, since the generics will also trigger
         // an extraneous error message when we find predicates like
         // `T : Sized` for a trait like: `trait Magic<T>`.
-        if !trait_def.generics.types.get_slice(ParamSpace::TypeSpace).is_empty() {
-            error_566(self.ccx, span);
-        } else if !no_refl_predicates.is_empty() {
-            error_565(self.ccx, span);
+        //
+        // We also put the check on the number of items here,
+        // as it seems confusing to report an error about
+        // extraneous predicates created by things like
+        // an associated type inside the trait.
+
+        if !items.is_empty() {
+            error_380(self.ccx, span);
+        } else if has_ty_params {
+            span_err!(self.tcx().sess, span, E0566,
+                "traits with auto impls (`e.g. unsafe impl \
+                    Trait for ..`) can not have type parameters")
+        } else if has_predicates {
+            span_err!(self.tcx().sess, span, E0565,
+                "traits with auto impls (`e.g. unsafe impl \
+                    Trait for ..`) can not have predicates")
         }
 
+        // Finally if either of the above conditions apply we should add a note
+        // indicating that this error is the result of a recent soundness fix.
+        if has_ty_params || has_predicates {
+            self.tcx().sess.span_note_without_error(
+                span,
+                "the new auto trait rules are the result of a \
+                    recent soundness fix; see #29859 for more details")
+        }
     }
 
     fn check_trait(&mut self,
@@ -287,19 +325,10 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
     {
         let trait_def_id = self.tcx().map.local_def_id(item.id);
 
+        // TODO: in a second pass, globally rename to auto_trait,
+        // from default_impl.
         if self.tcx().trait_has_default_impl(trait_def_id) {
-            // We want to both ensure:
-            // 1) that there are no items contained within
-            // the trait defintion
-            //
-            // 2) that the definition doesn't violate the no-super trait rule
-            // for auto traits.
-
-            if !items.is_empty() {
-                error_380(self.ccx, item.span);
-            }
-
-            self.check_auto_trait(trait_def_id, item.span);
+            self.check_auto_trait(trait_def_id, items, item.span);
         }
 
         self.for_item(item).with_fcx(|fcx, this| {
@@ -311,8 +340,6 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
         });
     }
 
-
-
     fn check_item_fn(&mut self,
                      item: &hir::Item,
                      body: &hir::Block)
@@ -678,18 +705,6 @@ fn error_380(ccx: &CrateCtxt, span: Span) {
                Trait for ..`) must have no methods or associated items")
 }
 
-fn error_565(ccx: &CrateCtxt, span: Span) {
-    span_err!(ccx.tcx.sess, span, E0565,
-              "traits with default impls (`e.g. unsafe impl \
-               Trait for ..`) can not have predicates")
-}
-
-fn error_566(ccx: &CrateCtxt, span: Span) {
-    span_err!(ccx.tcx.sess, span, E0566,
-              "traits with default impls (`e.g. unsafe impl \
-               Trait for ..`) can not have type parameters")
-}
-
 fn error_392<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, span: Span, param_name: ast::Name)
                        -> DiagnosticBuilder<'tcx> {
     let mut err = struct_span_err!(ccx.tcx.sess, span, E0392,
diff --git a/src/test/compile-fail/traits-inductive-overflow-auto-normal-auto.rs b/src/test/compile-fail/traits-inductive-overflow-auto-normal-auto.rs
deleted file mode 100644
index cdf4b405fd8..00000000000
--- a/src/test/compile-fail/traits-inductive-overflow-auto-normal-auto.rs
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2015 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.
-
-// Test for a potential corner case in current impl where you have an
-// auto trait (Magic1) that depends on a normal trait (Magic2) which
-// in turn depends on the auto trait (Magic1). This was incorrectly
-// being considered coinductive, but because of the normal trait
-// interfering, it should not be.
-
-#![feature(optin_builtin_traits)]
-
-trait Magic1: Magic2 { }
-impl Magic1 for .. {}
-
-trait Magic2 { }
-impl<T: Magic1> Magic2 for T { }
-
-fn is_magic1<T: Magic1>() { }
-
-#[derive(Debug)]
-struct NoClone;
-
-fn main() {
-    is_magic1::<NoClone>(); //~ ERROR E0275
-}
diff --git a/src/test/compile-fail/traits-inductive-overflow-supertrait-oibit.rs b/src/test/compile-fail/traits-inductive-overflow-supertrait-oibit.rs
index ec8db996600..168148b92fe 100644
--- a/src/test/compile-fail/traits-inductive-overflow-supertrait-oibit.rs
+++ b/src/test/compile-fail/traits-inductive-overflow-supertrait-oibit.rs
@@ -14,7 +14,7 @@
 
 #![feature(optin_builtin_traits)]
 
-trait Magic: Copy {}
+trait Magic: Copy {} //~ ERROR E0565
 impl Magic for .. {}
 
 fn copy<T: Magic>(x: T) -> (T, T) { (x, x) }
@@ -23,6 +23,6 @@ fn copy<T: Magic>(x: T) -> (T, T) { (x, x) }
 struct NoClone;
 
 fn main() {
-    let (a, b) = copy(NoClone); //~ ERROR E0277
+    let (a, b) = copy(NoClone);
     println!("{:?} {:?}", a, b);
 }
diff --git a/src/test/compile-fail/issue-29859.rs b/src/test/compile-fail/typeck-auto-trait-no-supertraits-2.rs
index 3419e66af13..60da647f682 100644
--- a/src/test/compile-fail/issue-29859.rs
+++ b/src/test/compile-fail/typeck-auto-trait-no-supertraits-2.rs
@@ -10,7 +10,7 @@
 
 #![feature(optin_builtin_traits)]
 
-trait Magic: Copy {} //~ ERROR E0565
+trait Magic : Sized where Option<Self> : Magic {} //~ ERROR E0565
 impl Magic for .. {} 
 impl<T:Magic> Magic for T {}
 
diff --git a/src/test/compile-fail/typeck-auto-trait-no-supertraits.rs b/src/test/compile-fail/typeck-auto-trait-no-supertraits.rs
new file mode 100644
index 00000000000..177d594da18
--- /dev/null
+++ b/src/test/compile-fail/typeck-auto-trait-no-supertraits.rs
@@ -0,0 +1,49 @@
+// 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.
+
+// This test is for #29859, we need to ensure auto traits,
+// (also known previously as default traits), do not have
+// supertraits. Since the compiler synthesizes these
+// instances on demand, we are essentially enabling
+// users to write axioms if we view trait selection,
+// as a proof system.
+//
+// For example the below test allows us to add the rule:
+//  forall (T : Type), T : Copy
+//
+// Providing a copy instance for *any* type, which
+// is most definitely unsound. Imagine copying a
+// type that contains a mutable reference, enabling
+// mutable aliasing.
+//
+// You can imagine an even more dangerous test, 
+// which currently compiles on nightly.
+//
+// fn main() {
+//    let mut i = 10;
+//    let (a, b) = copy(&mut i);
+//    println!("{:?} {:?}", a, b);
+// }
+
+#![feature(optin_builtin_traits)]
+
+trait Magic: Copy {} //~ ERROR E0565
+impl Magic for .. {} 
+impl<T:Magic> Magic for T {}
+
+fn copy<T: Magic>(x: T) -> (T, T) { (x, x) }
+
+#[derive(Debug)]
+struct NoClone;
+
+fn main() {
+    let (a, b) = copy(NoClone);
+    println!("{:?} {:?}", a, b);
+}
diff --git a/src/test/compile-fail/issue-29859-2.rs b/src/test/compile-fail/typeck-auto-trait-no-typeparams.rs
index 258aafb15ba..f2841a413db 100644
--- a/src/test/compile-fail/issue-29859-2.rs
+++ b/src/test/compile-fail/typeck-auto-trait-no-typeparams.rs
@@ -10,5 +10,5 @@
 
 #![feature(optin_builtin_traits)]
 
-trait Magic<T> {} //~ E0566
+trait Magic<T> {} //~ ERROR E0566
 impl Magic<isize> for .. {}
diff --git a/src/test/compile-fail/typeck-default-trait-impl-superregion.rs b/src/test/compile-fail/typeck-default-trait-impl-superregion.rs
deleted file mode 100644
index aa918119fbc..00000000000
--- a/src/test/compile-fail/typeck-default-trait-impl-superregion.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2015 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.
-
-// Test that when a `..` impl applies, we also check that any
-// supertrait conditions are met.
-
-#![feature(optin_builtin_traits)]
-
-trait MyTrait : 'static {}
-
-impl MyTrait for .. {}
-
-fn foo<T:MyTrait>() { }
-
-fn bar<'a>() {
-    foo::<&'a ()>(); //~ ERROR does not fulfill the required lifetime
-}
-
-fn main() {
-}
diff --git a/src/test/compile-fail/typeck-default-trait-impl-supertrait.rs b/src/test/compile-fail/typeck-default-trait-impl-supertrait.rs
deleted file mode 100644
index 0b071a9acd0..00000000000
--- a/src/test/compile-fail/typeck-default-trait-impl-supertrait.rs
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2015 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.
-
-// Test that when a `..` impl applies, we also check that any
-// supertrait conditions are met.
-
-#![feature(optin_builtin_traits)]
-
-trait NotImplemented { }
-
-trait MyTrait : NotImplemented {}
-
-impl MyTrait for .. {}
-
-fn foo<T:MyTrait>() { bar::<T>() }
-
-fn bar<T:NotImplemented>() { }
-
-fn main() {
-    foo::<i32>(); //~ ERROR `i32: NotImplemented` is not satisfied
-    bar::<i64>(); //~ ERROR `i64: NotImplemented` is not satisfied
-}
diff --git a/src/test/compile-fail/typeck-default-trait-impl-trait-where-clause-2.rs b/src/test/compile-fail/typeck-default-trait-impl-trait-where-clause-2.rs
deleted file mode 100644
index 3085f45a83d..00000000000
--- a/src/test/compile-fail/typeck-default-trait-impl-trait-where-clause-2.rs
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2015 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.
-
-// ignore-tidy-linelength
-
-// Test that when a `..` impl applies, we also check that any
-// supertrait conditions are met.
-
-#![feature(optin_builtin_traits)]
-
-trait NotImplemented { }
-
-trait MyTrait: Sized
-    where Option<Self> : NotImplemented
-{}
-
-impl NotImplemented for i32 {}
-
-impl MyTrait for .. {}
-
-fn bar<T:NotImplemented>() { }
-
-fn test() {
-    bar::<Option<i32>>();
-    //~^ ERROR `std::option::Option<i32>: NotImplemented` is not satisfied
-}
-
-fn main() {
-}
diff --git a/src/test/compile-fail/typeck-default-trait-impl-trait-where-clause.rs b/src/test/compile-fail/typeck-default-trait-impl-trait-where-clause.rs
deleted file mode 100644
index 47e87c09d12..00000000000
--- a/src/test/compile-fail/typeck-default-trait-impl-trait-where-clause.rs
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2015 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.
-
-// ignore-tidy-linelength
-
-// Test that when a `..` impl applies, we also check that any
-// supertrait conditions are met.
-
-#![feature(optin_builtin_traits)]
-
-trait NotImplemented { }
-
-trait MyTrait: Sized
-    where Option<Self> : NotImplemented
-{}
-
-impl NotImplemented for i32 {}
-
-impl MyTrait for .. {}
-
-fn foo<T:MyTrait>() {
-    //~^ ERROR `std::option::Option<T>: NotImplemented` is not satisfied
-    // This should probably typecheck. This is #20671.
-}
-
-fn bar<T:NotImplemented>() { }
-
-fn main() {
-}