Make traits with by-value-self be considered object safe.
This commit is contained in:
parent
fe512dacc8
commit
fd9f7da68e
5 changed files with 44 additions and 35 deletions
|
@ -42,9 +42,6 @@ pub enum ObjectSafetyViolation<'tcx> {
|
||||||
/// Reasons a method might not be object-safe.
|
/// Reasons a method might not be object-safe.
|
||||||
#[derive(Copy,Clone,Debug)]
|
#[derive(Copy,Clone,Debug)]
|
||||||
pub enum MethodViolationCode {
|
pub enum MethodViolationCode {
|
||||||
/// e.g., `fn(self)`
|
|
||||||
ByValueSelf,
|
|
||||||
|
|
||||||
/// e.g., `fn foo()`
|
/// e.g., `fn foo()`
|
||||||
StaticMethod,
|
StaticMethod,
|
||||||
|
|
||||||
|
@ -204,17 +201,15 @@ fn object_safety_violations_for_method<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The method's first parameter must be something that derefs to
|
// The method's first parameter must be something that derefs (or
|
||||||
// `&self`. For now, we only accept `&self` and `Box<Self>`.
|
// autorefs) to `&self`. For now, we only accept `self`, `&self`
|
||||||
|
// and `Box<Self>`.
|
||||||
match method.explicit_self {
|
match method.explicit_self {
|
||||||
ty::ByValueExplicitSelfCategory => {
|
|
||||||
return Some(MethodViolationCode::ByValueSelf);
|
|
||||||
}
|
|
||||||
|
|
||||||
ty::StaticExplicitSelfCategory => {
|
ty::StaticExplicitSelfCategory => {
|
||||||
return Some(MethodViolationCode::StaticMethod);
|
return Some(MethodViolationCode::StaticMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ty::ByValueExplicitSelfCategory |
|
||||||
ty::ByReferenceExplicitSelfCategory(..) |
|
ty::ByReferenceExplicitSelfCategory(..) |
|
||||||
ty::ByBoxExplicitSelfCategory => {
|
ty::ByBoxExplicitSelfCategory => {
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,14 +133,6 @@ pub fn check_object_safety<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||||
in the supertrait listing");
|
in the supertrait listing");
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectSafetyViolation::Method(method, MethodViolationCode::ByValueSelf) => {
|
|
||||||
tcx.sess.span_note(
|
|
||||||
span,
|
|
||||||
&format!("method `{}` has a receiver type of `Self`, \
|
|
||||||
which cannot be used with a trait object",
|
|
||||||
method.name.user_string(tcx)));
|
|
||||||
}
|
|
||||||
|
|
||||||
ObjectSafetyViolation::Method(method, MethodViolationCode::StaticMethod) => {
|
ObjectSafetyViolation::Method(method, MethodViolationCode::StaticMethod) => {
|
||||||
tcx.sess.span_note(
|
tcx.sess.span_note(
|
||||||
span,
|
span,
|
||||||
|
|
|
@ -15,8 +15,7 @@ fn needs_fn<F>(x: F) where F: Fn(isize) -> isize {}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let _: () = (box |_: isize| {}) as Box<FnOnce(isize)>;
|
let _: () = (box |_: isize| {}) as Box<FnOnce(isize)>;
|
||||||
//~^ ERROR object-safe
|
//~^ ERROR mismatched types
|
||||||
//~| ERROR mismatched types
|
|
||||||
//~| expected `()`
|
//~| expected `()`
|
||||||
//~| found `Box<core::ops::FnOnce(isize)>`
|
//~| found `Box<core::ops::FnOnce(isize)>`
|
||||||
//~| expected ()
|
//~| expected ()
|
||||||
|
|
29
src/test/compile-fail/object-safety-by-value-self-use.rs
Normal file
29
src/test/compile-fail/object-safety-by-value-self-use.rs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
// 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 while a trait with by-value self is object-safe, we
|
||||||
|
// can't actually invoke it from an object (yet...?).
|
||||||
|
|
||||||
|
#![feature(rustc_attrs)]
|
||||||
|
|
||||||
|
trait Bar {
|
||||||
|
fn bar(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Baz {
|
||||||
|
fn baz(self: Self);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn use_bar(t: Box<Bar>) {
|
||||||
|
t.bar() //~ ERROR cannot move a value of type Bar
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() { }
|
||||||
|
|
|
@ -8,9 +8,10 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
// Check that we correctly prevent users from making trait objects
|
// Check that a trait with by-value self is considered object-safe.
|
||||||
// from traits with a `fn(self)` method, unless `where Self : Sized`
|
|
||||||
// is present on the method.
|
#![feature(rustc_attrs)]
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
trait Bar {
|
trait Bar {
|
||||||
fn bar(self);
|
fn bar(self);
|
||||||
|
@ -26,27 +27,19 @@ trait Quux {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_bar<T:Bar>(t: &T) -> &Bar {
|
fn make_bar<T:Bar>(t: &T) -> &Bar {
|
||||||
t
|
t // legal
|
||||||
//~^ ERROR `Bar` is not object-safe
|
|
||||||
//~| NOTE method `bar` has a receiver type of `Self`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_bar_explicit<T:Bar>(t: &T) -> &Bar {
|
fn make_bar_explicit<T:Bar>(t: &T) -> &Bar {
|
||||||
t as &Bar
|
t as &Bar // legal
|
||||||
//~^ ERROR `Bar` is not object-safe
|
|
||||||
//~| NOTE method `bar` has a receiver type of `Self`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_baz<T:Baz>(t: &T) -> &Baz {
|
fn make_baz<T:Baz>(t: &T) -> &Baz {
|
||||||
t
|
t // legal
|
||||||
//~^ ERROR `Baz` is not object-safe
|
|
||||||
//~| NOTE method `baz` has a receiver type of `Self`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_baz_explicit<T:Baz>(t: &T) -> &Baz {
|
fn make_baz_explicit<T:Baz>(t: &T) -> &Baz {
|
||||||
t as &Baz
|
t as &Baz // legal
|
||||||
//~^ ERROR `Baz` is not object-safe
|
|
||||||
//~| NOTE method `baz` has a receiver type of `Self`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_quux<T:Quux>(t: &T) -> &Quux {
|
fn make_quux<T:Quux>(t: &T) -> &Quux {
|
||||||
|
@ -57,5 +50,6 @@ fn make_quux_explicit<T:Quux>(t: &T) -> &Quux {
|
||||||
t as &Quux
|
t as &Quux
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
#[rustc_error]
|
||||||
|
fn main() { //~ ERROR compilation successful
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue