Skip to content

Commit d058520

Browse files
committed
rollup merge of rust-lang#20325: nick29581/obj-safety-static
Closes rust-lang#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
2 parents a239d71 + 69716ef commit d058520

File tree

3 files changed

+40
-11
lines changed

3 files changed

+40
-11
lines changed

src/librustc_typeck/check/vtable.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -190,11 +190,13 @@ fn check_object_safety_inner<'tcx>(tcx: &ty::ctxt<'tcx>,
190190
}
191191
}
192192

193-
/// Returns a vec of error messages. If hte vec is empty - no errors!
193+
/// Returns a vec of error messages. If the vec is empty - no errors!
194194
///
195195
/// There are some limitations to calling functions through an object, because (a) the self
196196
/// type is not known (that's the whole point of a trait instance, after all, to obscure the
197-
/// self type) and (b) the call must go through a vtable and hence cannot be monomorphized.
197+
/// self type), (b) the call must go through a vtable and hence cannot be monomorphized and
198+
/// (c) the trait contains static methods which can't be called because we don't know the
199+
/// concrete type.
198200
fn check_object_safety_of_method<'tcx>(tcx: &ty::ctxt<'tcx>,
199201
object_trait: &ty::PolyTraitRef<'tcx>,
200202
method: &ty::Method<'tcx>)
@@ -210,9 +212,11 @@ fn check_object_safety_inner<'tcx>(tcx: &ty::ctxt<'tcx>,
210212
}
211213

212214
ty::StaticExplicitSelfCategory => {
213-
// Static methods are always object-safe since they
214-
// can't be called through a trait object
215-
return msgs
215+
// Static methods are never object safe (reason (c)).
216+
msgs.push(format!("cannot call a static method (`{}`) \
217+
through a trait object",
218+
method_name));
219+
return msgs;
216220
}
217221
ty::ByReferenceExplicitSelfCategory(..) |
218222
ty::ByBoxExplicitSelfCategory => {}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Check that static methods are not object-safe.
12+
13+
trait Tr {
14+
fn foo();
15+
}
16+
17+
struct St;
18+
19+
impl Tr for St {
20+
fn foo() {}
21+
}
22+
23+
fn main() {
24+
let _: &Tr = &St; //~ ERROR cannot convert to a trait object because trait `Tr` is not
25+
//~^ NOTE cannot call a static method (`foo`) through a trait object
26+
}

src/test/run-pass/trait-object-safety.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,19 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// Check that object-safe methods are identified as such. Also
12-
// acts as a regression test for #18490
11+
// Check that object-safe methods are identified as such.
1312

1413
trait Tr {
15-
// Static methods are always safe regardless of other rules
16-
fn new() -> Self;
14+
fn foo(&self);
1715
}
1816

1917
struct St;
2018

2119
impl Tr for St {
22-
fn new() -> St { St }
20+
fn foo(&self) {}
2321
}
2422

2523
fn main() {
26-
&St as &Tr;
24+
let s: &Tr = &St;
25+
s.foo();
2726
}

0 commit comments

Comments
 (0)