about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2014-12-30 16:26:11 -0800
committerAlex Crichton <alex@alexcrichton.com>2014-12-30 16:26:11 -0800
commitd058520f064ccc3fefcdbe2055c9690df8a0175c (patch)
tree4bc100cfc545fe940375aaa21618707eba694560 /src
parenta239d71729973d56221dd5a51eb987972ecc44d2 (diff)
parent69716ef607c3410722f35e31cc6419ad142b7e02 (diff)
downloadrust-d058520f064ccc3fefcdbe2055c9690df8a0175c.tar.gz
rust-d058520f064ccc3fefcdbe2055c9690df8a0175c.zip
rollup merge of #20325: nick29581/obj-safety-static
Closes #19949 and rust-lang/rfcs#428

[breaking change]

If you have traits used with objects with static methods, you'll need to move
the static methods to a different trait.

r? @cmr
Diffstat (limited to 'src')
-rw-r--r--src/librustc_typeck/check/vtable.rs14
-rw-r--r--src/test/compile-fail/trait-object-safety.rs26
-rw-r--r--src/test/run-pass/trait-object-safety.rs11
3 files changed, 40 insertions, 11 deletions
diff --git a/src/librustc_typeck/check/vtable.rs b/src/librustc_typeck/check/vtable.rs
index 23a8643aadc..f153b51c5df 100644
--- a/src/librustc_typeck/check/vtable.rs
+++ b/src/librustc_typeck/check/vtable.rs
@@ -190,11 +190,13 @@ fn check_object_safety_inner<'tcx>(tcx: &ty::ctxt<'tcx>,
         }
     }
 
-    /// Returns a vec of error messages. If hte vec is empty - no errors!
+    /// Returns a vec of error messages. If the vec is empty - no errors!
     ///
     /// There are some limitations to calling functions through an object, because (a) the self
     /// type is not known (that's the whole point of a trait instance, after all, to obscure the
-    /// self type) and (b) the call must go through a vtable and hence cannot be monomorphized.
+    /// self type), (b) the call must go through a vtable and hence cannot be monomorphized and
+    /// (c) the trait contains static methods which can't be called because we don't know the
+    /// concrete type.
     fn check_object_safety_of_method<'tcx>(tcx: &ty::ctxt<'tcx>,
                                            object_trait: &ty::PolyTraitRef<'tcx>,
                                            method: &ty::Method<'tcx>)
@@ -210,9 +212,11 @@ fn check_object_safety_inner<'tcx>(tcx: &ty::ctxt<'tcx>,
             }
 
             ty::StaticExplicitSelfCategory => {
-                // Static methods are always object-safe since they
-                // can't be called through a trait object
-                return msgs
+                // Static methods are never object safe (reason (c)).
+                msgs.push(format!("cannot call a static method (`{}`) \
+                                   through a trait object",
+                                  method_name));
+                return msgs;
             }
             ty::ByReferenceExplicitSelfCategory(..) |
             ty::ByBoxExplicitSelfCategory => {}
diff --git a/src/test/compile-fail/trait-object-safety.rs b/src/test/compile-fail/trait-object-safety.rs
new file mode 100644
index 00000000000..d594e3e1747
--- /dev/null
+++ b/src/test/compile-fail/trait-object-safety.rs
@@ -0,0 +1,26 @@
+// Copyright 2014 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.
+
+// Check that static methods are not object-safe.
+
+trait Tr {
+    fn foo();
+}
+
+struct St;
+
+impl Tr for St {
+    fn foo() {}
+}
+
+fn main() {
+    let _: &Tr = &St; //~ ERROR cannot convert to a trait object because trait `Tr` is not
+    //~^ NOTE cannot call a static method (`foo`) through a trait object
+}
diff --git a/src/test/run-pass/trait-object-safety.rs b/src/test/run-pass/trait-object-safety.rs
index 929cb9e7f17..ed7284a8353 100644
--- a/src/test/run-pass/trait-object-safety.rs
+++ b/src/test/run-pass/trait-object-safety.rs
@@ -8,20 +8,19 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Check that object-safe methods are identified as such.  Also
-// acts as a regression test for #18490
+// Check that object-safe methods are identified as such.
 
 trait Tr {
-    // Static methods are always safe regardless of other rules
-    fn new() -> Self;
+    fn foo(&self);
 }
 
 struct St;
 
 impl Tr for St {
-    fn new() -> St { St }
+    fn foo(&self) {}
 }
 
 fn main() {
-    &St as &Tr;
+    let s: &Tr = &St;
+    s.foo();
 }