about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2016-10-22 03:33:36 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2016-10-26 20:55:16 +0300
commit811a2b91de8fe0c6bbd8d49186d0d5be192f644e (patch)
tree8a61d61dca4b85375f6423bc0e67823dc1a8b650
parenta6b3b01b5f7f5a9d7d340dacf7dbf72be29e2c07 (diff)
downloadrust-811a2b91de8fe0c6bbd8d49186d0d5be192f644e.tar.gz
rust-811a2b91de8fe0c6bbd8d49186d0d5be192f644e.zip
Prohibit patterns in trait methods without bodies
-rw-r--r--src/doc/reference.md6
-rw-r--r--src/librustc/lint/builtin.rs9
-rw-r--r--src/librustc_lint/lib.rs4
-rw-r--r--src/librustc_passes/ast_validation.rs10
-rw-r--r--src/test/compile-fail/no-patterns-in-args-2.rs23
-rw-r--r--src/test/incremental/hashes/trait_defs.rs8
-rw-r--r--src/test/run-pass/by-value-self-in-mut-slot.rs2
-rw-r--r--src/test/run-pass/uniq-self-in-mut-slot.rs2
8 files changed, 53 insertions, 11 deletions
diff --git a/src/doc/reference.md b/src/doc/reference.md
index 84f459bf872..94b45570985 100644
--- a/src/doc/reference.md
+++ b/src/doc/reference.md
@@ -4023,9 +4023,9 @@ Methods that take either `self` or `Box<Self>` can optionally place them in a
 mutable variable by prefixing them with `mut` (similar to regular arguments):
 
 ```
-trait Changer {
-    fn change(mut self) -> Self;
-    fn modify(mut self: Box<Self>) -> Box<Self>;
+trait Changer: Sized {
+    fn change(mut self) {}
+    fn modify(mut self: Box<Self>) {}
 }
 ```
 
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 7fc3f638979..d7ec544c954 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -192,6 +192,12 @@ declare_lint! {
     "safe access to extern statics was erroneously allowed"
 }
 
+declare_lint! {
+    pub PATTERNS_IN_FNS_WITHOUT_BODY,
+    Warn,
+    "patterns in functions without body were erroneously allowed"
+}
+
 /// Does nothing as a lint pass, but registers some `Lint`s
 /// which are used by other parts of the compiler.
 #[derive(Copy, Clone)]
@@ -228,7 +234,8 @@ impl LintPass for HardwiredLints {
             SUPER_OR_SELF_IN_GLOBAL_PATH,
             HR_LIFETIME_IN_ASSOC_TYPE,
             LIFETIME_UNDERSCORE,
-            SAFE_EXTERN_STATICS
+            SAFE_EXTERN_STATICS,
+            PATTERNS_IN_FNS_WITHOUT_BODY
         )
     }
 }
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index 74483b89cea..ef7bab8de8c 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -212,6 +212,10 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
             id: LintId::of(SAFE_EXTERN_STATICS),
             reference: "issue 36247 <https://github.com/rust-lang/rust/issues/35112>",
         },
+        FutureIncompatibleInfo {
+            id: LintId::of(PATTERNS_IN_FNS_WITHOUT_BODY),
+            reference: "issue #35203 <https://github.com/rust-lang/rust/issues/35203>",
+        },
         ]);
 
     // Register renamed and removed lints
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index 5096a574e2b..828efbf3731 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -190,8 +190,16 @@ impl<'a> Visitor for AstValidator<'a> {
             }
             ItemKind::Trait(.., ref trait_items) => {
                 for trait_item in trait_items {
-                    if let TraitItemKind::Method(ref sig, _) = trait_item.node {
+                    if let TraitItemKind::Method(ref sig, ref block) = trait_item.node {
                         self.check_trait_fn_not_const(sig.constness);
+                        if block.is_none() {
+                            self.check_decl_no_pat(&sig.decl, |span, _| {
+                                self.session.add_lint(lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY,
+                                                      trait_item.id, span,
+                                                      "patterns aren't allowed in methods \
+                                                       without bodies".to_string());
+                            });
+                        }
                     }
                 }
             }
diff --git a/src/test/compile-fail/no-patterns-in-args-2.rs b/src/test/compile-fail/no-patterns-in-args-2.rs
new file mode 100644
index 00000000000..385d012cade
--- /dev/null
+++ b/src/test/compile-fail/no-patterns-in-args-2.rs
@@ -0,0 +1,23 @@
+// 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.
+
+#![deny(patterns_in_fns_without_body)]
+
+trait Tr {
+    fn f1(mut arg: u8); //~ ERROR patterns aren't allowed in methods without bodies
+                        //~^ WARN was previously accepted
+    fn f2(&arg: u8); //~ ERROR patterns aren't allowed in methods without bodies
+                     //~^ WARN was previously accepted
+    fn g1(arg: u8); // OK
+    fn g2(_: u8); // OK
+    fn g3(u8); // OK
+}
+
+fn main() {}
diff --git a/src/test/incremental/hashes/trait_defs.rs b/src/test/incremental/hashes/trait_defs.rs
index 937f053e320..391c2e75ba4 100644
--- a/src/test/incremental/hashes/trait_defs.rs
+++ b/src/test/incremental/hashes/trait_defs.rs
@@ -264,8 +264,8 @@ trait TraitChangeModeSelfRefToMut {
 
 
 #[cfg(cfail1)]
-trait TraitChangeModeSelfOwnToMut {
-    fn method(self);
+trait TraitChangeModeSelfOwnToMut: Sized {
+    fn method(self) {}
 }
 
 #[cfg(not(cfail1))]
@@ -273,8 +273,8 @@ trait TraitChangeModeSelfOwnToMut {
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-trait TraitChangeModeSelfOwnToMut {
-    fn method(mut self);
+trait TraitChangeModeSelfOwnToMut: Sized {
+    fn method(mut self) {}
 }
 
 
diff --git a/src/test/run-pass/by-value-self-in-mut-slot.rs b/src/test/run-pass/by-value-self-in-mut-slot.rs
index 5bbdec95b15..846b695c35b 100644
--- a/src/test/run-pass/by-value-self-in-mut-slot.rs
+++ b/src/test/run-pass/by-value-self-in-mut-slot.rs
@@ -14,7 +14,7 @@ struct X {
 }
 
 trait Changer {
-    fn change(mut self) -> Self;
+    fn change(self) -> Self;
 }
 
 impl Changer for X {
diff --git a/src/test/run-pass/uniq-self-in-mut-slot.rs b/src/test/run-pass/uniq-self-in-mut-slot.rs
index baca157a488..7910380abee 100644
--- a/src/test/run-pass/uniq-self-in-mut-slot.rs
+++ b/src/test/run-pass/uniq-self-in-mut-slot.rs
@@ -17,7 +17,7 @@ struct X {
 }
 
 trait Changer {
-    fn change(mut self: Box<Self>) -> Box<Self>;
+    fn change(self: Box<Self>) -> Box<Self>;
 }
 
 impl Changer for X {