From 3ed9fbd63c6a3c6226bc466786e6d3c1bfec856d Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 29 Nov 2012 18:37:33 -0800 Subject: [PATCH] impls of traits cannot define methods on the anonymous trait --- src/libcore/iter.rs | 1 + src/libcore/path.rs | 3 ++ src/libcore/pipes.rs | 23 +++++++----- src/libcore/reflect.rs | 7 ++-- src/librustc/middle/astencode.rs | 13 +++++-- src/librustc/middle/typeck/check/mod.rs | 2 +- src/librustc/middle/typeck/collect.rs | 27 ++++++++------ src/librustc/middle/typeck/infer/lub.rs | 8 +++-- src/libstd/map.rs | 4 ++- src/libstd/net_tcp.rs | 3 -- src/libstd/smallintmap.rs | 1 - src/libsyntax/ext/pipes/ast_builder.rs | 3 ++ src/libsyntax/ext/pipes/mod.rs | 1 - src/libsyntax/ext/pipes/parse_proto.rs | 1 + src/libsyntax/ext/pipes/pipec.rs | 5 +++ src/libsyntax/ext/trace_macros.rs | 1 - src/libsyntax/parse/common.rs | 36 +------------------ src/libsyntax/parse/mod.rs | 1 - src/libsyntax/parse/obsolete.rs | 7 +--- src/libsyntax/parse/parser.rs | 2 +- src/test/compile-fail/issue-3953.rs | 8 +++-- ...it-impl-can-not-have-untraitful-methods.rs | 7 ++++ src/test/run-pass/reflect-visit-data.rs | 7 +++- 23 files changed, 87 insertions(+), 84 deletions(-) create mode 100644 src/test/compile-fail/trait-impl-can-not-have-untraitful-methods.rs diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index d318c279999c..37491ae0b714 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -37,6 +37,7 @@ pub trait Times { pub trait CopyableIter { pure fn filter_to_vec(pred: fn(a: A) -> bool) -> ~[A]; pure fn map_to_vec(op: fn(v: A) -> B) -> ~[B]; + pure fn flat_map_to_vec>(op: fn(A) -> IB) -> ~[B]; pure fn to_vec() -> ~[A]; pure fn find(p: fn(a: A) -> bool) -> Option; } diff --git a/src/libcore/path.rs b/src/libcore/path.rs index f0fefee9d06d..a9a99565cf13 100644 --- a/src/libcore/path.rs +++ b/src/libcore/path.rs @@ -44,6 +44,9 @@ pub trait GenericPath { pure fn with_filestem((&str)) -> self; pure fn with_filetype((&str)) -> self; + pure fn dir_path() -> self; + pure fn file_path() -> self; + pure fn push((&str)) -> self; pure fn push_rel((&self)) -> self; pure fn push_many((&[~str])) -> self; diff --git a/src/libcore/pipes.rs b/src/libcore/pipes.rs index 561732057cf3..a06564a470e6 100644 --- a/src/libcore/pipes.rs +++ b/src/libcore/pipes.rs @@ -811,13 +811,22 @@ pub struct RecvPacketBuffered { } } -impl RecvPacketBuffered : Selectable { +impl RecvPacketBuffered { fn unwrap() -> *Packet { let mut p = None; p <-> self.p; option::unwrap(move p) } + fn reuse_buffer() -> BufferResource { + //error!("recv reuse_buffer"); + let mut tmp = None; + tmp <-> self.buffer; + option::unwrap(move tmp) + } +} + +impl RecvPacketBuffered : Selectable { pure fn header() -> *PacketHeader { match self.p { Some(packet) => unsafe { @@ -829,13 +838,6 @@ impl RecvPacketBuffered : Selectable { None => fail ~"packet already consumed" } } - - fn reuse_buffer() -> BufferResource { - //error!("recv reuse_buffer"); - let mut tmp = None; - tmp <-> self.buffer; - option::unwrap(move tmp) - } } pub fn RecvPacketBuffered(p: *Packet) @@ -1046,7 +1048,7 @@ pub fn PortSet() -> PortSet{ } } -impl PortSet : Recv { +impl PortSet { fn add(port: pipes::Port) { self.ports.push(move port) @@ -1057,6 +1059,9 @@ impl PortSet : Recv { self.add(move po); move ch } +} + +impl PortSet : Recv { fn try_recv() -> Option { let mut result = None; diff --git a/src/libcore/reflect.rs b/src/libcore/reflect.rs index 3fa37a2fb8e5..d9b18947779f 100644 --- a/src/libcore/reflect.rs +++ b/src/libcore/reflect.rs @@ -34,9 +34,7 @@ pub fn MovePtrAdaptor(v: V) -> MovePtrAdaptor { MovePtrAdaptor { inner: move v } } -/// Abstract type-directed pointer-movement using the MovePtr trait -impl MovePtrAdaptor: TyVisitor { - +impl MovePtrAdaptor { #[inline(always)] fn bump(sz: uint) { do self.inner.move_ptr() |p| { @@ -60,7 +58,10 @@ impl MovePtrAdaptor: TyVisitor { fn bump_past() { self.bump(sys::size_of::()); } +} +/// Abstract type-directed pointer-movement using the MovePtr trait +impl MovePtrAdaptor: TyVisitor { fn visit_bot() -> bool { self.align_to::<()>(); if ! self.inner.visit_bot() { return false; } diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 1c7338fe3170..8ee50986a00d 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -72,6 +72,10 @@ trait tr { fn tr(xcx: extended_decode_ctxt) -> self; } +trait tr_intern { + fn tr_intern(xcx: extended_decode_ctxt) -> ast::def_id; +} + // ______________________________________________________________________ // Top-level methods. @@ -168,13 +172,16 @@ impl extended_decode_ctxt { } } +impl ast::def_id: tr_intern { + fn tr_intern(xcx: extended_decode_ctxt) -> ast::def_id { + xcx.tr_intern_def_id(self) + } +} + impl ast::def_id: tr { fn tr(xcx: extended_decode_ctxt) -> ast::def_id { xcx.tr_def_id(self) } - fn tr_intern(xcx: extended_decode_ctxt) -> ast::def_id { - xcx.tr_intern_def_id(self) - } } impl span: tr { diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 32d7181b40d4..7be2f6bb9d3b 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -549,7 +549,6 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) { } impl @fn_ctxt: ast_conv { - fn infcx() -> infer::infer_ctxt { self.inh.infcx } fn tcx() -> ty::ctxt { self.ccx.tcx } fn ccx() -> @crate_ctxt { self.ccx } @@ -563,6 +562,7 @@ impl @fn_ctxt: ast_conv { } impl @fn_ctxt { + fn infcx() -> infer::infer_ctxt { self.inh.infcx } fn search_in_scope_regions(br: ty::bound_region) -> Result { diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index 0c6fe5857681..9dda2da458a4 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -465,22 +465,27 @@ fn check_methods_against_trait(ccx: @crate_ctxt, } } - for vec::each(*ty::trait_methods(tcx, did)) |trait_m| { - match vec::find(impl_ms, |impl_m| trait_m.ident == impl_m.mty.ident) { - Some(ref cm) => { + // Check that each method we impl is a method on the trait + // Trait methods we don't implement must be default methods, but if not + // we'll catch it in coherence + let trait_ms = ty::trait_methods(tcx, did); + for impl_ms.each |impl_m| { + match trait_ms.find(|trait_m| trait_m.ident == impl_m.mty.ident) { + Some(ref trait_m) => { compare_impl_method( - ccx.tcx, vec::len(tps), cm, trait_m, + ccx.tcx, tps.len(), impl_m, trait_m, &tpt.substs, selfty); } None => { - // If we couldn't find an implementation for trait_m in - // the impl, then either this method has a default - // implementation or we're using the trait-provided - // version. Either way, we handle this later, during the - // coherence phase. + // This method is not part of the trait + tcx.sess.span_err( + impl_m.span, + fmt!("method `%s` is not a member of trait `%s`", + tcx.sess.str_of(impl_m.mty.ident), + path_to_str(a_trait_ty.path, tcx.sess.intr()))); } - } // match - } // |trait_m| + } + } } // fn fn convert_field(ccx: @crate_ctxt, diff --git a/src/librustc/middle/typeck/infer/lub.rs b/src/librustc/middle/typeck/infer/lub.rs index 8c3357190f7b..80fcecb5d9e4 100644 --- a/src/librustc/middle/typeck/infer/lub.rs +++ b/src/librustc/middle/typeck/infer/lub.rs @@ -7,6 +7,11 @@ fn macros() { include!("macros.rs"); } // FIXME(#3114): Macro import/export. enum Lub = combine_fields; // "subtype", "subregion" etc +impl Lub { + fn bot_ty(b: ty::t) -> cres { Ok(b) } + fn ty_bot(b: ty::t) -> cres { self.bot_ty(b) } // commutative +} + impl Lub: combine { fn infcx() -> infer_ctxt { self.infcx } fn tag() -> ~str { ~"lub" } @@ -16,9 +21,6 @@ impl Lub: combine { fn lub() -> Lub { Lub(*self) } fn glb() -> Glb { Glb(*self) } - fn bot_ty(b: ty::t) -> cres { Ok(b) } - fn ty_bot(b: ty::t) -> cres { self.bot_ty(b) } // commutative - fn mts(a: ty::mt, b: ty::mt) -> cres { let tcx = self.infcx.tcx; diff --git a/src/libstd/map.rs b/src/libstd/map.rs index d68970679ad9..b1909bfb067a 100644 --- a/src/libstd/map.rs +++ b/src/libstd/map.rs @@ -390,7 +390,7 @@ pub mod chained { } } - impl T: ToStr { + impl T { fn to_writer(wr: io::Writer) { if self.count == 0u { wr.write_str(~"{}"); @@ -410,7 +410,9 @@ pub mod chained { }; wr.write_str(~" }"); } + } + impl T: ToStr { pure fn to_str() -> ~str unsafe { // Meh -- this should be safe do io::with_str_writer |wr| { self.to_writer(wr) } diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index 96897790fcdb..966cbbb6c145 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -824,9 +824,6 @@ impl TcpSocketBuf: io::Reader { bytes[0] as int } } - fn unread_byte(amt: int) { - self.data.buf.unshift(amt as u8); - } fn eof() -> bool { self.end_of_stream } diff --git a/src/libstd/smallintmap.rs b/src/libstd/smallintmap.rs index 3f9d308584d4..dd773d25687e 100644 --- a/src/libstd/smallintmap.rs +++ b/src/libstd/smallintmap.rs @@ -101,7 +101,6 @@ impl SmallIntMap: map::Map { } pure fn get(key: uint) -> V { get(self, key) } pure fn find(key: uint) -> Option { find(self, key) } - fn rehash() { fail } fn update_with_key(key: uint, val: V, ff: fn(uint, V, V) -> V) -> bool { match self.find(key) { diff --git a/src/libsyntax/ext/pipes/ast_builder.rs b/src/libsyntax/ext/pipes/ast_builder.rs index 652ad5533c4c..e9bb42aa2a13 100644 --- a/src/libsyntax/ext/pipes/ast_builder.rs +++ b/src/libsyntax/ext/pipes/ast_builder.rs @@ -79,7 +79,10 @@ trait ext_ctxt_ast_builder { fn stmt_let(ident: ident, e: @ast::expr) -> @ast::stmt; fn stmt_expr(e: @ast::expr) -> @ast::stmt; fn block_expr(b: ast::blk) -> @ast::expr; + fn move_expr(e: @ast::expr) -> @ast::expr; fn ty_option(ty: @ast::Ty) -> @ast::Ty; + fn ty_infer() -> @ast::Ty; + fn ty_nil_ast_builder() -> @ast::Ty; } impl ext_ctxt: ext_ctxt_ast_builder { diff --git a/src/libsyntax/ext/pipes/mod.rs b/src/libsyntax/ext/pipes/mod.rs index b064f39eb3a1..9f5c722afc3c 100644 --- a/src/libsyntax/ext/pipes/mod.rs +++ b/src/libsyntax/ext/pipes/mod.rs @@ -38,7 +38,6 @@ use ext::base::ext_ctxt; use ast::tt_delim; use parse::lexer::{new_tt_reader, reader}; use parse::parser::Parser; -use parse::common::parser_common; use pipes::parse_proto::proto_parser; diff --git a/src/libsyntax/ext/pipes/parse_proto.rs b/src/libsyntax/ext/pipes/parse_proto.rs index 8f2b92a720c0..9db2c1e6733f 100644 --- a/src/libsyntax/ext/pipes/parse_proto.rs +++ b/src/libsyntax/ext/pipes/parse_proto.rs @@ -8,6 +8,7 @@ use pipec::*; trait proto_parser { fn parse_proto(id: ~str) -> protocol; fn parse_state(proto: protocol); + fn parse_message(state: state); } impl parser::Parser: proto_parser { diff --git a/src/libsyntax/ext/pipes/pipec.rs b/src/libsyntax/ext/pipes/pipec.rs index 907a193d05c6..558e7d01259e 100644 --- a/src/libsyntax/ext/pipes/pipec.rs +++ b/src/libsyntax/ext/pipes/pipec.rs @@ -24,6 +24,7 @@ mod syntax { trait gen_send { fn gen_send(cx: ext_ctxt, try: bool) -> @ast::item; + fn to_ty(cx: ext_ctxt) -> @ast::Ty; } trait to_type_decls { @@ -34,6 +35,10 @@ trait to_type_decls { trait gen_init { fn gen_init(cx: ext_ctxt) -> @ast::item; fn compile(cx: ext_ctxt) -> @ast::item; + fn buffer_ty_path(cx: ext_ctxt) -> @ast::Ty; + fn gen_buffer_type(cx: ext_ctxt) -> @ast::item; + fn gen_buffer_init(ext_cx: ext_ctxt) -> @ast::expr; + fn gen_init_bounded(ext_cx: ext_ctxt) -> @ast::expr; } impl message: gen_send { diff --git a/src/libsyntax/ext/trace_macros.rs b/src/libsyntax/ext/trace_macros.rs index f8c85fa01b76..fb0d4bb128eb 100644 --- a/src/libsyntax/ext/trace_macros.rs +++ b/src/libsyntax/ext/trace_macros.rs @@ -3,7 +3,6 @@ use ext::base::ext_ctxt; use ast::tt_delim; use parse::lexer::{new_tt_reader, reader}; use parse::parser::Parser; -use parse::common::parser_common; fn expand_trace_macros(cx: ext_ctxt, sp: span, tt: ~[ast::token_tree]) -> base::mac_result diff --git a/src/libsyntax/parse/common.rs b/src/libsyntax/parse/common.rs index 1811951fc0e9..54ac776fb326 100644 --- a/src/libsyntax/parse/common.rs +++ b/src/libsyntax/parse/common.rs @@ -22,41 +22,7 @@ fn token_to_str(reader: reader, ++token: token::Token) -> ~str { token::to_str(reader.interner(), token) } -trait parser_common { - fn unexpected_last(t: token::Token) -> !; - fn unexpected() -> !; - fn expect(t: token::Token); - fn parse_ident() -> ast::ident; - fn parse_path_list_ident() -> ast::path_list_ident; - fn parse_value_ident() -> ast::ident; - fn eat(tok: token::Token) -> bool; - // A sanity check that the word we are asking for is a known keyword - fn require_keyword(word: ~str); - fn token_is_keyword(word: ~str, ++tok: token::Token) -> bool; - fn is_keyword(word: ~str) -> bool; - fn is_any_keyword(tok: token::Token) -> bool; - fn eat_keyword(word: ~str) -> bool; - fn expect_keyword(word: ~str); - fn expect_gt(); - fn parse_seq_to_before_gt(sep: Option, - f: fn(Parser) -> T) -> ~[T]; - fn parse_seq_to_gt(sep: Option, - f: fn(Parser) -> T) -> ~[T]; - fn parse_seq_lt_gt(sep: Option, - f: fn(Parser) -> T) -> spanned<~[T]>; - fn parse_seq_to_end(ket: token::Token, sep: seq_sep, - f: fn(Parser) -> T) -> ~[T]; - fn parse_seq_to_before_end(ket: token::Token, sep: seq_sep, - f: fn(Parser) -> T) -> ~[T]; - fn parse_unspanned_seq(bra: token::Token, - ket: token::Token, - sep: seq_sep, - f: fn(Parser) -> T) -> ~[T]; - fn parse_seq(bra: token::Token, ket: token::Token, sep: seq_sep, - f: fn(Parser) -> T) -> spanned<~[T]>; -} - -impl Parser: parser_common { +impl Parser { fn unexpected_last(t: token::Token) -> ! { self.span_fatal( copy self.last_span, diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index c290e7cf3073..c1afc43205cb 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -27,7 +27,6 @@ export parse_from_source_str; use parser::Parser; use attr::parser_attr; -use common::parser_common; use ast::node_id; use util::interner; use diagnostic::{span_handler, mk_span_handler, mk_handler, emitter}; diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index 89f2ef4d9392..1407b56336c3 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -52,12 +52,7 @@ impl ObsoleteSyntax: to_bytes::IterBytes { } } -pub trait ObsoleteReporter { - fn obsolete(sp: span, kind: ObsoleteSyntax); - fn obsolete_expr(sp: span, kind: ObsoleteSyntax) -> @expr; -} - -impl Parser : ObsoleteReporter { +impl Parser { /// Reports an obsolete syntax non-fatal error. fn obsolete(sp: span, kind: ObsoleteSyntax) { let (kind_str, desc) = match kind { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 96364790956b..d8fd58b3d508 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -16,7 +16,7 @@ use common::{seq_sep_trailing_disallowed, seq_sep_trailing_allowed, use dvec::DVec; use vec::{push}; use obsolete::{ - ObsoleteReporter, ObsoleteSyntax, + ObsoleteSyntax, ObsoleteLowerCaseKindBounds, ObsoleteLet, ObsoleteFieldTerminator, ObsoleteStructCtor, ObsoleteWith, ObsoleteClassMethod, ObsoleteClassTraits, diff --git a/src/test/compile-fail/issue-3953.rs b/src/test/compile-fail/issue-3953.rs index 45fa00bd672b..551c0bd2e368 100644 --- a/src/test/compile-fail/issue-3953.rs +++ b/src/test/compile-fail/issue-3953.rs @@ -9,9 +9,11 @@ trait Hahaha: Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, // enum Lol = int; -pub impl Lol: Hahaha { - pure fn eq(other: &Lol) -> bool { *self != **other } - pure fn ne(other: &Lol) -> bool { *self == **other } +pub impl Lol: Hahaha { } + +impl Lol: Eq { + pure fn eq(&self, other: &Lol) -> bool { **self != **other } + pure fn ne(&self, other: &Lol) -> bool { **self == **other } } fn main() { diff --git a/src/test/compile-fail/trait-impl-can-not-have-untraitful-methods.rs b/src/test/compile-fail/trait-impl-can-not-have-untraitful-methods.rs new file mode 100644 index 000000000000..b65b0d9d4acc --- /dev/null +++ b/src/test/compile-fail/trait-impl-can-not-have-untraitful-methods.rs @@ -0,0 +1,7 @@ +trait A { } + +impl int: A { + fn foo() { } //~ ERROR method `foo` is not a member of trait `A` +} + +fn main() { } \ No newline at end of file diff --git a/src/test/run-pass/reflect-visit-data.rs b/src/test/run-pass/reflect-visit-data.rs index 24ae16f25e1c..733679efc615 100644 --- a/src/test/run-pass/reflect-visit-data.rs +++ b/src/test/run-pass/reflect-visit-data.rs @@ -21,7 +21,8 @@ fn align(size: uint, align: uint) -> uint { enum ptr_visit_adaptor = { inner: V }; -impl ptr_visit_adaptor: TyVisitor { + +impl ptr_visit_adaptor { #[inline(always)] fn bump(sz: uint) { @@ -47,6 +48,10 @@ impl ptr_visit_adaptor: TyVisitor { self.bump(sys::size_of::()); } +} + +impl ptr_visit_adaptor: TyVisitor { + fn visit_bot() -> bool { self.align_to::<()>(); if ! self.inner.visit_bot() { return false; }