diff --git a/src/librustc_typeck/check/vtable.rs b/src/librustc_typeck/check/vtable.rs index ff16568aa63fc..8371247263987 100644 --- a/src/librustc_typeck/check/vtable.rs +++ b/src/librustc_typeck/check/vtable.rs @@ -166,11 +166,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>, method: &ty::Method<'tcx>) -> Vec { @@ -185,9 +187,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 0000000000000..d594e3e17474b --- /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 or the MIT license +// , 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 929cb9e7f1759..ed7284a835365 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(); }