Skip to content

Commit

Permalink
Make traits with by-value-self be considered object safe.
Browse files Browse the repository at this point in the history
  • Loading branch information
nikomatsakis committed Feb 23, 2015
1 parent fe512da commit fd9f7da
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 35 deletions.
13 changes: 4 additions & 9 deletions src/librustc/middle/traits/object_safety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,6 @@ pub enum ObjectSafetyViolation<'tcx> {
/// Reasons a method might not be object-safe.
#[derive(Copy,Clone,Debug)]
pub enum MethodViolationCode {
/// e.g., `fn(self)`
ByValueSelf,

/// e.g., `fn foo()`
StaticMethod,

Expand Down Expand Up @@ -204,17 +201,15 @@ fn object_safety_violations_for_method<'tcx>(tcx: &ty::ctxt<'tcx>,
return None;
}

// The method's first parameter must be something that derefs to
// `&self`. For now, we only accept `&self` and `Box<Self>`.
// The method's first parameter must be something that derefs (or
// autorefs) to `&self`. For now, we only accept `self`, `&self`
// and `Box<Self>`.
match method.explicit_self {
ty::ByValueExplicitSelfCategory => {
return Some(MethodViolationCode::ByValueSelf);
}

ty::StaticExplicitSelfCategory => {
return Some(MethodViolationCode::StaticMethod);
}

ty::ByValueExplicitSelfCategory |
ty::ByReferenceExplicitSelfCategory(..) |
ty::ByBoxExplicitSelfCategory => {
}
Expand Down
8 changes: 0 additions & 8 deletions src/librustc_typeck/check/vtable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,14 +133,6 @@ pub fn check_object_safety<'tcx>(tcx: &ty::ctxt<'tcx>,
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) => {
tcx.sess.span_note(
span,
Expand Down
3 changes: 1 addition & 2 deletions src/test/compile-fail/fn-trait-formatting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ fn needs_fn<F>(x: F) where F: Fn(isize) -> isize {}

fn main() {
let _: () = (box |_: isize| {}) as Box<FnOnce(isize)>;
//~^ ERROR object-safe
//~| ERROR mismatched types
//~^ ERROR mismatched types
//~| expected `()`
//~| found `Box<core::ops::FnOnce(isize)>`
//~| expected ()
Expand Down
29 changes: 29 additions & 0 deletions src/test/compile-fail/object-safety-by-value-self-use.rs
Original file line number Diff line number Diff line change
@@ -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() { }

26 changes: 10 additions & 16 deletions src/test/compile-fail/object-safety-by-value-self.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Check that we correctly prevent users from making trait objects
// from traits with a `fn(self)` method, unless `where Self : Sized`
// is present on the method.
// Check that a trait with by-value self is considered object-safe.

#![feature(rustc_attrs)]
#![allow(dead_code)]

trait Bar {
fn bar(self);
Expand All @@ -26,27 +27,19 @@ trait Quux {
}

fn make_bar<T:Bar>(t: &T) -> &Bar {
t
//~^ ERROR `Bar` is not object-safe
//~| NOTE method `bar` has a receiver type of `Self`
t // legal
}

fn make_bar_explicit<T:Bar>(t: &T) -> &Bar {
t as &Bar
//~^ ERROR `Bar` is not object-safe
//~| NOTE method `bar` has a receiver type of `Self`
t as &Bar // legal
}

fn make_baz<T:Baz>(t: &T) -> &Baz {
t
//~^ ERROR `Baz` is not object-safe
//~| NOTE method `baz` has a receiver type of `Self`
t // legal
}

fn make_baz_explicit<T:Baz>(t: &T) -> &Baz {
t as &Baz
//~^ ERROR `Baz` is not object-safe
//~| NOTE method `baz` has a receiver type of `Self`
t as &Baz // legal
}

fn make_quux<T:Quux>(t: &T) -> &Quux {
Expand All @@ -57,5 +50,6 @@ fn make_quux_explicit<T:Quux>(t: &T) -> &Quux {
t as &Quux
}

fn main() {
#[rustc_error]
fn main() { //~ ERROR compilation successful
}

0 comments on commit fd9f7da

Please sign in to comment.