1
Fork 0

Make object types not implement associated trait. Fixes #5087.

This commit is contained in:
Niko Matsakis 2013-03-05 17:49:50 -05:00
parent 6267339d68
commit 6d764cc361
21 changed files with 65 additions and 339 deletions

View file

@ -69,6 +69,26 @@ pub trait Reader {
fn tell(&self) -> uint; fn tell(&self) -> uint;
} }
#[cfg(stage1)]
#[cfg(stage2)]
impl Reader for @Reader {
fn read(&self, bytes: &mut [u8], len: uint) -> uint {
self.read(bytes, len)
}
fn read_byte(&self) -> int {
self.read_byte()
}
fn eof(&self) -> bool {
self.eof()
}
fn seek(&self, position: int, style: SeekStyle) {
self.seek(position, style)
}
fn tell(&self) -> uint {
self.tell()
}
}
/// Generic utility functions defined on readers. /// Generic utility functions defined on readers.
pub trait ReaderUtil { pub trait ReaderUtil {
@ -631,6 +651,16 @@ pub trait Writer {
fn get_type(&self) -> WriterType; fn get_type(&self) -> WriterType;
} }
#[cfg(stage1)]
#[cfg(stage2)]
impl Writer for @Writer {
fn write(&self, v: &[const u8]) { self.write(v) }
fn seek(&self, a: int, b: SeekStyle) { self.seek(a, b) }
fn tell(&self) -> uint { self.tell() }
fn flush(&self) -> int { self.flush() }
fn get_type(&self) -> WriterType { self.get_type() }
}
impl<W:Writer,C> Writer for Wrapper<W, C> { impl<W:Writer,C> Writer for Wrapper<W, C> {
fn write(&self, bs: &[const u8]) { self.base.write(bs); } fn write(&self, bs: &[const u8]) { self.base.write(bs); }
fn seek(&self, off: int, style: SeekStyle) { self.base.seek(off, style); } fn seek(&self, off: int, style: SeekStyle) { self.base.seek(off, style); }
@ -1067,8 +1097,8 @@ pub fn buffered_file_writer(path: &Path) -> Result<Writer, ~str> {
// FIXME (#2004) it would be great if this could be a const // FIXME (#2004) it would be great if this could be a const
// FIXME (#2004) why are these different from the way stdin() is // FIXME (#2004) why are these different from the way stdin() is
// implemented? // implemented?
pub fn stdout() -> Writer { fd_writer(libc::STDOUT_FILENO as c_int, false) } pub fn stdout() -> @Writer { fd_writer(libc::STDOUT_FILENO as c_int, false) }
pub fn stderr() -> Writer { fd_writer(libc::STDERR_FILENO as c_int, false) } pub fn stderr() -> @Writer { fd_writer(libc::STDERR_FILENO as c_int, false) }
pub fn print(s: &str) { stdout().write_str(s); } pub fn print(s: &str) { stdout().write_str(s); }
pub fn println(s: &str) { stdout().write_line(s); } pub fn println(s: &str) { stdout().write_line(s); }

View file

@ -664,16 +664,6 @@ fn encode_vtable_origin(ecx: @e::EncodeContext,
} }
} }
} }
typeck::vtable_trait(def_id, tys) => {
do ebml_w.emit_enum_variant(~"vtable_trait", 1u, 3u) {
do ebml_w.emit_enum_variant_arg(0u) {
ebml_w.emit_def_id(def_id)
}
do ebml_w.emit_enum_variant_arg(1u) {
ebml_w.emit_tys(ecx, /*bad*/copy tys);
}
}
}
} }
} }
@ -720,16 +710,6 @@ impl vtable_decoder_helpers for reader::Decoder {
} }
) )
} }
2 => {
typeck::vtable_trait(
do self.read_enum_variant_arg(0u) {
self.read_def_id(xcx)
},
do self.read_enum_variant_arg(1u) {
self.read_tys(xcx)
}
)
}
// hard to avoid - user input // hard to avoid - user input
_ => fail!(~"bad enum variant") _ => fail!(~"bad enum variant")
} }

View file

@ -1405,7 +1405,6 @@ pub fn resolve_vtable_in_fn_ctxt(fcx: fn_ctxt, +vt: typeck::vtable_origin)
} }
} }
} }
vt => vt
} }
} }

View file

@ -478,14 +478,6 @@ pub fn trans_monomorphized_callee(bcx: block,
}) })
} }
} }
typeck::vtable_trait(_, _) => {
trans_trait_callee(bcx,
callee_id,
n_method,
base,
ty::vstore_box,
mentry.explicit_self)
}
typeck::vtable_param(*) => { typeck::vtable_param(*) => {
fail!(~"vtable_param left in monomorphized function's " + fail!(~"vtable_param left in monomorphized function's " +
"vtable substs"); "vtable substs");
@ -756,13 +748,7 @@ pub fn vtable_id(ccx: @CrateContext,
None, None,
None) None)
} }
typeck::vtable_trait(trait_id, substs) => {
@mono_id_ {
def: trait_id,
params: vec::map(substs, |t| mono_precise(*t, None)),
impl_did_opt: None
}
}
// can't this be checked at the callee? // can't this be checked at the callee?
_ => fail!(~"vtable_id") _ => fail!(~"vtable_id")
} }

View file

@ -30,7 +30,7 @@ itself (note that inherent impls can only be defined in the same
module as the type itself). module as the type itself).
Inherent candidates are not always derived from impls. If you have a Inherent candidates are not always derived from impls. If you have a
trait instance, such as a value of type `ToStr`, then the trait trait instance, such as a value of type `@ToStr`, then the trait
methods (`to_str()`, in this case) are inherently associated with it. methods (`to_str()`, in this case) are inherently associated with it.
Another case is type parameters, in which case the methods of their Another case is type parameters, in which case the methods of their
bounds are inherent. bounds are inherent.
@ -1221,7 +1221,7 @@ pub impl LookupContext {
} }
method_trait(trait_did, _, _) | method_self(trait_did, _) method_trait(trait_did, _, _) | method_self(trait_did, _)
| method_super(trait_did, _) => { | method_super(trait_did, _) => {
self.report_param_candidate(idx, trait_did) self.report_trait_candidate(idx, trait_did)
} }
} }
} }

View file

@ -18,7 +18,7 @@ use middle::typeck::infer::{fixup_err_to_str, InferCtxt};
use middle::typeck::infer::{resolve_and_force_all_but_regions, resolve_type}; use middle::typeck::infer::{resolve_and_force_all_but_regions, resolve_type};
use middle::typeck::infer; use middle::typeck::infer;
use middle::typeck::{CrateCtxt, vtable_origin, vtable_param, vtable_res}; use middle::typeck::{CrateCtxt, vtable_origin, vtable_param, vtable_res};
use middle::typeck::{vtable_static, vtable_trait}; use middle::typeck::{vtable_static};
use util::common::indenter; use util::common::indenter;
use util::ppaux::tys_to_str; use util::ppaux::tys_to_str;
use util::ppaux; use util::ppaux;
@ -81,7 +81,6 @@ pub fn lookup_vtables(vcx: &VtableContext,
location_info: &LocationInfo, location_info: &LocationInfo,
bounds: @~[ty::param_bounds], bounds: @~[ty::param_bounds],
substs: &ty::substs, substs: &ty::substs,
allow_unsafe: bool,
is_early: bool) -> vtable_res { is_early: bool) -> vtable_res {
debug!("lookup_vtables(location_info=%?, debug!("lookup_vtables(location_info=%?,
# bounds=%?, \ # bounds=%?, \
@ -110,8 +109,7 @@ pub fn lookup_vtables(vcx: &VtableContext,
debug!("after subst: %?", debug!("after subst: %?",
ppaux::ty_to_str(tcx, trait_ty)); ppaux::ty_to_str(tcx, trait_ty));
match lookup_vtable(vcx, location_info, *ty, trait_ty, match lookup_vtable(vcx, location_info, *ty, trait_ty, is_early) {
allow_unsafe, is_early) {
Some(vtable) => result.push(vtable), Some(vtable) => result.push(vtable),
None => { None => {
vcx.tcx().sess.span_fatal( vcx.tcx().sess.span_fatal(
@ -162,7 +160,6 @@ pub fn lookup_vtable(vcx: &VtableContext,
location_info: &LocationInfo, location_info: &LocationInfo,
ty: ty::t, ty: ty::t,
trait_ty: ty::t, trait_ty: ty::t,
allow_unsafe: bool,
is_early: bool) is_early: bool)
-> Option<vtable_origin> { -> Option<vtable_origin> {
debug!("lookup_vtable(ty=%s, trait_ty=%s)", debug!("lookup_vtable(ty=%s, trait_ty=%s)",
@ -224,30 +221,6 @@ pub fn lookup_vtable(vcx: &VtableContext,
} }
} }
ty::ty_trait(did, ref substs, _) if trait_id == did => {
debug!("(checking vtable) @1 relating ty to trait ty with did %?",
did);
relate_trait_tys(vcx, location_info, trait_ty, ty);
if !allow_unsafe && !is_early {
for vec::each(*ty::trait_methods(tcx, did)) |m| {
if ty::type_has_self(ty::mk_bare_fn(tcx, copy m.fty)) {
tcx.sess.span_err(
location_info.span,
~"a boxed trait with self types may not be \
passed as a bounded type");
} else if (*m.tps).len() > 0u {
tcx.sess.span_err(
location_info.span,
~"a boxed trait with generic methods may not \
be passed as a bounded type");
}
}
}
return Some(vtable_trait(did, /*bad*/copy (*substs).tps));
}
_ => { _ => {
let mut found = ~[]; let mut found = ~[];
@ -411,7 +384,7 @@ pub fn lookup_vtable(vcx: &VtableContext,
trait_vstore); trait_vstore);
let subres = lookup_vtables( let subres = lookup_vtables(
vcx, location_info, im_bs, &substs_f, vcx, location_info, im_bs, &substs_f,
false, is_early); is_early);
// Finally, we register that we found a // Finally, we register that we found a
// matching impl, and record the def ID of // matching impl, and record the def ID of
@ -542,8 +515,7 @@ pub fn early_resolve_expr(ex: @ast::expr,
} }
let vcx = VtableContext { ccx: fcx.ccx, infcx: fcx.infcx() }; let vcx = VtableContext { ccx: fcx.ccx, infcx: fcx.infcx() };
let vtbls = lookup_vtables(&vcx, &location_info_for_expr(ex), let vtbls = lookup_vtables(&vcx, &location_info_for_expr(ex),
item_ty.bounds, substs, false, item_ty.bounds, substs, is_early);
is_early);
if !is_early { if !is_early {
let vtable_map = cx.vtable_map; let vtable_map = cx.vtable_map;
vtable_map.insert(ex.id, vtbls); vtable_map.insert(ex.id, vtbls);
@ -573,7 +545,7 @@ pub fn early_resolve_expr(ex: @ast::expr,
let substs = fcx.node_ty_substs(callee_id); let substs = fcx.node_ty_substs(callee_id);
let vcx = VtableContext { ccx: fcx.ccx, infcx: fcx.infcx() }; let vcx = VtableContext { ccx: fcx.ccx, infcx: fcx.infcx() };
let vtbls = lookup_vtables(&vcx, &location_info_for_expr(ex), let vtbls = lookup_vtables(&vcx, &location_info_for_expr(ex),
bounds, &substs, false, is_early); bounds, &substs, is_early);
if !is_early { if !is_early {
insert_vtables(cx, callee_id, vtbls); insert_vtables(cx, callee_id, vtbls);
} }
@ -607,7 +579,6 @@ pub fn early_resolve_expr(ex: @ast::expr,
location_info, location_info,
mt.ty, mt.ty,
target_ty, target_ty,
true,
is_early); is_early);
match vtable_opt { match vtable_opt {
Some(vtable) => { Some(vtable) => {

View file

@ -22,7 +22,7 @@ use middle::typeck::infer::{force_all, resolve_all, resolve_region};
use middle::typeck::infer::{resolve_type}; use middle::typeck::infer::{resolve_type};
use middle::typeck::infer; use middle::typeck::infer;
use middle::typeck::method_map_entry; use middle::typeck::method_map_entry;
use middle::typeck::{vtable_param, vtable_trait, write_substs_to_tcx}; use middle::typeck::{vtable_param, write_substs_to_tcx};
use middle::typeck::{write_ty_to_tcx}; use middle::typeck::{write_ty_to_tcx};
use util::ppaux; use util::ppaux;

View file

@ -150,12 +150,7 @@ pub enum vtable_origin {
The first uint is the param number (identifying T in the example), The first uint is the param number (identifying T in the example),
and the second is the bound number (identifying baz) and the second is the bound number (identifying baz)
*/ */
vtable_param(uint, uint), vtable_param(uint, uint)
/*
Dynamic vtable, comes from something known to have a trait
type. def_id refers to the trait item, tys are the substs
*/
vtable_trait(ast::def_id, ~[ty::t]),
} }
pub impl vtable_origin { pub impl vtable_origin {
@ -171,12 +166,6 @@ pub impl vtable_origin {
vtable_param(x, y) => { vtable_param(x, y) => {
fmt!("vtable_param(%?, %?)", x, y) fmt!("vtable_param(%?, %?)", x, y)
} }
vtable_trait(def_id, ref tys) => {
fmt!("vtable_trait(%?:%s, %?)",
def_id, ty::item_path_str(tcx, def_id),
tys.map(|t| ppaux::ty_to_str(tcx, *t)))
}
} }
} }
} }

View file

@ -8,19 +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.
trait double { // Test that an object type `@Foo` is not considered to implement the
fn double() -> uint; // trait `Foo`. Issue #5087.
}
impl double for uint { trait Foo {}
fn double() -> uint { self * 2u } fn take_foo<F:Foo>(f: F) {}
} fn take_object(f: @Foo) { take_foo(f); } //~ ERROR failed to find an implementation of trait
fn main() {}
fn is_equal<D:double>(x: @D, exp: uint) {
assert x.double() == exp;
}
pub fn main() {
let x = @(@3u as @double);
is_equal(x, 6);
}

View file

@ -16,8 +16,16 @@ fn make_gc1(gc: get_ctxt/&a) -> get_ctxt/&b {
return gc; //~ ERROR mismatched types: expected `@get_ctxt/&b` but found `@get_ctxt/&a` return gc; //~ ERROR mismatched types: expected `@get_ctxt/&b` but found `@get_ctxt/&a`
} }
fn make_gc2(gc: get_ctxt/&a) -> get_ctxt/&b { struct Foo {
return @gc as get_ctxt; //~ ERROR cannot infer an appropriate lifetime r: &'self uint
}
impl get_ctxt/&self for Foo/&self {
fn get_ctxt() -> &self/uint { self.r }
}
fn make_gc2(foo: Foo/&a) -> get_ctxt/&b {
return @foo as get_ctxt; //~ ERROR cannot infer an appropriate lifetime
} }
fn main() { fn main() {

View file

@ -1,25 +0,0 @@
// Copyright 2012 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.
trait add {
fn plus(++x: Self) -> Self;
}
impl add for int {
fn plus(++x: int) -> int { self + x }
}
fn do_add<A:add>(x: A, y: A) -> A { x.plus(y) }
fn main() {
let x = @3 as @add;
let y = @4 as @add;
do_add(x, y); //~ ERROR a boxed trait with self types may not be passed as a bounded type
}

View file

@ -1,21 +0,0 @@
// Copyright 2012 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.
trait foo<T> { }
fn bar(x: foo<uint>) -> foo<int> {
return (@x as foo::<int>);
//~^ ERROR mismatched types: expected `@foo<int>` but found `@foo<uint>`
//~^^ ERROR mismatched types: expected `@foo<int>` but found `@foo<uint>`
// This is unfortunate -- new handling of parens means the error message
// gets printed twice
}
fn main() {}

View file

@ -14,7 +14,7 @@ extern mod cci_class_cast;
use core::to_str::ToStr; use core::to_str::ToStr;
use cci_class_cast::kitty::*; use cci_class_cast::kitty::*;
fn print_out<T:ToStr>(thing: T, expected: ~str) { fn print_out(thing: @ToStr, expected: ~str) {
let actual = thing.to_str(); let actual = thing.to_str();
debug!("%s", actual); debug!("%s", actual);
assert(actual == expected); assert(actual == expected);

View file

@ -79,7 +79,7 @@ fn cat(in_x : uint, in_y : int, in_name: ~str) -> cat {
} }
fn annoy_neighbors<T:noisy>(critter: T) { fn annoy_neighbors(critter: @noisy) {
for uint::range(0u, 10u) |i| { critter.speak(); } for uint::range(0u, 10u) |i| { critter.speak(); }
} }

View file

@ -56,7 +56,7 @@ impl ToStr for cat {
pure fn to_str(&self) -> ~str { copy self.name } pure fn to_str(&self) -> ~str { copy self.name }
} }
fn print_out<T:ToStr>(thing: T, expected: ~str) { fn print_out(thing: @ToStr, expected: ~str) {
let actual = thing.to_str(); let actual = thing.to_str();
debug!("%s", actual); debug!("%s", actual);
assert(actual == expected); assert(actual == expected);

View file

@ -1,39 +0,0 @@
pub trait Reader {
// FIXME (#2004): Seekable really should be orthogonal.
/// Read up to len bytes (or EOF) and put them into bytes (which
/// must be at least len bytes long). Return number of bytes read.
// FIXME (#2982): This should probably return an error.
fn read(&self, bytes: &mut [u8], len: uint) -> uint;
}
pub trait ReaderUtil {
/// Read len bytes into a new vec.
fn read_bytes(&self, len: uint);
}
impl<T:Reader> ReaderUtil for T {
fn read_bytes(&self, len: uint) {
let mut count = self.read(&mut [0], len);
}
}
struct S {
x: int,
y: int
}
impl Reader for S {
fn read(&self, bytes: &mut [u8], len: uint) -> uint {
0
}
}
pub fn main() {
let x = S { x: 1, y: 2 };
let x = @x as @Reader;
x.read_bytes(0);
}

View file

@ -1,39 +0,0 @@
pub trait Reader {
// FIXME (#2004): Seekable really should be orthogonal.
/// Read up to len bytes (or EOF) and put them into bytes (which
/// must be at least len bytes long). Return number of bytes read.
// FIXME (#2982): This should probably return an error.
fn read(&self, bytes: &mut [u8], len: uint) -> uint;
}
pub trait ReaderUtil {
/// Read len bytes into a new vec.
fn read_bytes(&self, len: uint);
}
impl<T:Reader> ReaderUtil for T {
fn read_bytes(&self, len: uint) {
let mut count = self.read(&mut [0], len);
}
}
struct S {
x: int,
y: int
}
impl Reader for S {
fn read(&self, bytes: &mut [u8], len: uint) -> uint {
0
}
}
pub fn main() {
let x = S { x: 1, y: 2 };
let x = @x as @Reader;
x.read_bytes(0);
}

View file

@ -1,39 +0,0 @@
pub trait Reader {
// FIXME (#2004): Seekable really should be orthogonal.
/// Read up to len bytes (or EOF) and put them into bytes (which
/// must be at least len bytes long). Return number of bytes read.
// FIXME (#2982): This should probably return an error.
fn read(&self, bytes: &mut [u8], len: uint) -> uint;
}
pub trait ReaderUtil {
/// Read len bytes into a new vec.
fn read_bytes(len: uint);
}
impl<T:Reader> ReaderUtil for T {
fn read_bytes(len: uint) {
let mut count = self.read(&mut [0], len);
}
}
struct S {
x: int,
y: int
}
impl Reader for S {
fn read(&self, bytes: &mut [u8], len: uint) -> uint {
0
}
}
pub fn main() {
let x = S { x: 1, y: 2 };
let x = @x as @Reader;
x.read_bytes(0);
}

View file

@ -1,39 +0,0 @@
pub trait Reader {
// FIXME (#2004): Seekable really should be orthogonal.
/// Read up to len bytes (or EOF) and put them into bytes (which
/// must be at least len bytes long). Return number of bytes read.
// FIXME (#2982): This should probably return an error.
fn read(bytes: &mut [u8], len: uint) -> uint;
}
pub trait ReaderUtil {
/// Read len bytes into a new vec.
fn read_bytes(len: uint);
}
impl<T:Reader> ReaderUtil for T {
fn read_bytes(len: uint) {
let mut count = self.read(&mut [0], len);
}
}
struct S {
x: int,
y: int
}
impl Reader for S {
fn read(bytes: &mut [u8], len: uint) -> uint {
0
}
}
pub fn main() {
let x = S { x: 1, y: 2 };
let x = @x as @Reader;
x.read_bytes(0);
}

View file

@ -11,12 +11,12 @@
use core::iter::BaseIter; use core::iter::BaseIter;
trait FlatMapToVec<A> { trait FlatMapToVec<A> {
fn flat_map_to_vec<B, IB:BaseIter<B>>(op: fn(&A) -> IB) -> ~[B]; fn flat_map_to_vec<B, IB:BaseIter<B>>(&self, op: fn(&A) -> IB) -> ~[B];
} }
impl<A:Copy> FlatMapToVec<A> for BaseIter<A> { impl<A:Copy> FlatMapToVec<A> for ~[A] {
fn flat_map_to_vec<B, IB:BaseIter<B>>(op: fn(&A) -> IB) -> ~[B] { fn flat_map_to_vec<B, IB:BaseIter<B>>(&self, op: fn(&A) -> IB) -> ~[B] {
iter::flat_map_to_vec(&self, op) iter::flat_map_to_vec(self, op)
} }
} }

View file

@ -1,26 +0,0 @@
// Copyright 2012 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.
trait double {
fn double() -> uint;
}
impl double for uint {
fn double() -> uint { self * 2u }
}
fn is_equal<D:double>(x: @D, exp: uint) {
assert x.double() == exp;
}
pub fn main() {
let x = @(@3u as @double);
is_equal(x, 6);
}